geometry-tower-defense/docs/IconColorDesgin.md

226 lines
4.6 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

使用的 5 个属性:
- AttackDamage(MuzzleComp)
- DamageRandomRate(MuzzleComp)
- RotateSpeed(BearingComp)
- AttackRange(BearingComp)
- AttackSpeed(BaseComp)
下面我给你一套专门为这 5 个属性设计的稳定映射方案,目标是:
* 不出现“未使用 RGB 位导致底色聚集”
* 不出现颜色难以区分
* 不随数值微调产生大跳变
* 能一眼看出“偏伤害 / 偏射速 / 偏范围”等方向
---
# 一、先定颜色语义(非常关键)
我们先给每个属性一个**语义色相Hue**,并且颜色间隔拉开,避免混淆。
| 属性 | 含义倾向 | Hue建议 |
|------------------|--------|----------|
| AttackDamage | 爆发/力量 | 0° |
| DamageRandomRate | 波动/暴击感 | 30° |
| RotateSpeed | 灵活/机动 | 200°青蓝 |
| AttackRange | 空间/覆盖 | 120°绿 |
| AttackSpeed | 频率/连发 | 270° |
解释:
* 伤害 → 红(直觉最强)
* 范围 → 绿(覆盖感)
* 攻速 → 紫(科技感/高频)
* 旋转 → 青蓝(灵活)
* 随机伤害 → 橙(不稳定爆发)
Hue 间隔 > 60°视觉上足够区分。
---
# 二、不要直接映射到 RGB而是走 HSV
### Step 1归一化
对每个属性:
```csharp
x_i = clamp01((value_i - min_i) / (max_i - min_i))
```
⚠️ 不要用当前组件的 min/max要用全局平衡区间。
---
# 三、核心算法:主导属性 + 混合属性
## 1⃣ 找出前两名属性
```csharp
i1 = argmax(x_i)
i2 = secondMax(x_i)
```
---
## 2⃣ Hue 插值
```csharp
w = x_i2 / (x_i1 + x_i2 + 0.0001f)
hue = lerp(Hue[i1], Hue[i2], w)
```
这能避免“单一属性颜色单调”的问题。
例如:
* 高伤害 + 高攻速 → 红紫之间
* 高范围 + 高旋转 → 绿青之间
---
# 四、饱和度Saturation
饱和度表达“专精度”。
```csharp
purity = x_i1 - x_i2
sat = lerp(0.45f, 0.9f, clamp01(purity * 1.5f))
```
* 越单一专精 → 越鲜艳
* 属性均衡 → 稍微偏灰
这样“杂牌组件”会看起来更灰一点,专精流派更亮。
---
# 五、明度Value
明度表达“整体强度”。
```csharp
intensity = (x1 + x2 + x3 + x4 + x5) / 5f
val = lerp(0.55f, 0.95f, intensity)
```
强度越高越亮。
⚠️ 不要让 val 太低,否则会看起来像“禁用状态”。
---
# 六、品质不要改 Hue
品质建议只影响:
* 外描边颜色
* 发光
* 明度偏移
* 图标底板
例如:
| 品质 | 处理方式 |
|----|-----------------|
| 白 | val × 0.9 |
| 绿 | 无变化 |
| 蓝 | 外发光 |
| 紫 | val ×1.05 + 外发光 |
| 红 | 双层发光 + 轻微高对比 |
不要把红品质直接改成红色,那会和 AttackDamage 冲突。
---
# 七、避免“颜色基地”的关键
你之前的问题是:
> 某些属性没有值 → RGB 位没用 → 颜色集中
用现在方案:
* 即便某些属性接近 0Hue 仍由主导属性决定
* 不会出现“默认黑色/灰色聚集”
另外建议:
```csharp
sat = max(sat, 0.4f);
val = max(val, 0.6f);
```
避免太灰太暗。
---
# 八、额外增强:组件类型偏移
你有三类组件(枪口/轴承/底座),可以轻微加一个 hue 偏移:
* 枪口:+0°
* 轴承:+15°
* 底座:-15°
这样即便数值类似,也能区分结构类型。
---
# 九、完整伪代码(你可以直接用)
```csharp
Color GenerateColor(float[] normalizedStats, ComponentType type)
{
float[] hueMap = { 0f, 30f, 200f, 120f, 270f };
int i1 = MaxIndex(normalizedStats);
int i2 = SecondMaxIndex(normalizedStats);
float w = normalizedStats[i2] /
(normalizedStats[i1] + normalizedStats[i2] + 0.0001f);
float hue = Mathf.Lerp(hueMap[i1], hueMap[i2], w);
float purity = normalizedStats[i1] - normalizedStats[i2];
float sat = Mathf.Lerp(0.45f, 0.9f, Mathf.Clamp01(purity * 1.5f));
float intensity = normalizedStats.Average();
float val = Mathf.Lerp(0.55f, 0.95f, intensity);
if (type == ComponentType.Axis) hue += 15f;
if (type == ComponentType.Base) hue -= 15f;
return Color.HSVToRGB(hue / 360f, sat, val);
}
```
---
# 十、视觉稳定性测试建议
做一个小测试场景:
* 随机生成 200 个组件
* 打印颜色到网格
* 看是否:
* 有大量颜色过于相似
* 有大面积灰色
* 是否能一眼区分“偏伤害”“偏范围”等
---
# 结论
你不应该:
❌ 把 5 个属性硬塞进 RGB 位
你应该:
✅ 用 Hue 表达方向
✅ 用 Saturation 表达专精
✅ 用 Value 表达强度
✅ 用外观表达品质