2. 技能系统中的二进制应用

2.1 技能状态管理

使用位运算来管理角色的各种状态效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 定义状态效果
const StatusEffects = {
NONE: 0,
STUN: 1 << 0, // 眩晕
SILENCE: 1 << 1, // 沉默
POISON: 1 << 2, // 中毒
BURN: 1 << 3, // 燃烧
FREEZE: 1 << 4, // 冰冻
INVINCIBLE: 1 << 5, // 无敌
STEALTH: 1 << 6, // 隐身
HASTE: 1 << 7 // 加速
};

class Character {
constructor() {
this.activeEffects = StatusEffects.NONE;
this.immunities = StatusEffects.NONE;
}

// 添加状态效果
addEffect(effect) {
// 如果角色对该效果免疫,则不添加
if (this.immunities & effect) {
return false;
}
this.activeEffects |= effect;
return true;
}

// 移除状态效果
removeEffect(effect) {
this.activeEffects &= ~effect;
}

// 检查是否有某个效果
hasEffect(effect) {
return (this.activeEffects & effect) !== 0;
}

// 添加免疫
addImmunity(effect) {
this.immunities |= effect;
}

// 检查能否施放技能
canCastSpells() {
// 被沉默或眩晕时无法施放技能
return !this.hasEffect(StatusEffects.SILENCE | StatusEffects.STUN);
}

// 检查能否移动
canMove() {
// 被眩晕或冰冻时无法移动
return !this.hasEffect(StatusEffects.STUN | StatusEffects.FREEZE);
}
}

2.2 技能冷却系统

使用位运算来管理技能冷却状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class SkillSystem {
constructor() {
this.availableSkills = 0; // 当前可用的技能
this.skillCount = 8; // 最多8个技能
this.cooldowns = new Array(this.skillCount).fill(0);
}

// 标记技能为可用
setSkillAvailable(skillId) {
this.availableSkills |= (1 << skillId);
}

// 标记技能为冷却中
setSkillOnCooldown(skillId) {
this.availableSkills &= ~(1 << skillId);
}

// 检查技能是否可用
isSkillAvailable(skillId) {
return (this.availableSkills & (1 << skillId)) !== 0;
}

// 更新技能冷却
update(deltaTime) {
for (let i = 0; i < this.skillCount; i++) {
if (this.cooldowns[i] > 0) {
this.cooldowns[i] -= deltaTime;
if (this.cooldowns[i] <= 0) {
this.setSkillAvailable(i);
}
}
}
}
}

2.3 技能效果组合

使用位运算来组合多个技能效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class SkillEffect {
static Elements = {
NONE: 0,
FIRE: 1 << 0, // 火
ICE: 1 << 1, // 冰
LIGHTNING: 1 << 2,// 雷
EARTH: 1 << 3 // 土
};

static combine(effect1, effect2) {
// 特殊组合效果
if ((effect1 & SkillEffect.Elements.FIRE) &&
(effect2 & SkillEffect.Elements.ICE)) {
return 'STEAM'; // 火+冰=蒸汽
}
if ((effect1 & SkillEffect.Elements.LIGHTNING) &&
(effect2 & SkillEffect.Elements.EARTH)) {
return 'MAGNETISM'; // 雷+土=磁力
}
return effect1 | effect2; // 默认直接组合
}
}

高级状态管理实现

当需要处理大量状态时,有几种更好的实现方式:

1. 使用TypedArray实现大量状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 使用Uint32Array可以处理32个状态,如果需要更多可以使用多个数组
class StatusManager {
private static readonly BITS_PER_ELEMENT = 32;
private states: Uint32Array;

constructor(totalStates: number) {
// 计算需要多少个Uint32来存储所有状态
const arraySize = Math.ceil(totalStates / StatusManager.BITS_PER_ELEMENT);
this.states = new Uint32Array(arraySize);
}

// 设置状态
setStatus(statusId: number, value: boolean): void {
const arrayIndex = Math.floor(statusId / StatusManager.BITS_PER_ELEMENT);
const bitPosition = statusId % StatusManager.BITS_PER_ELEMENT;
if (value) {
this.states[arrayIndex] |= (1 << bitPosition);
} else {
this.states[arrayIndex] &= ~(1 << bitPosition);
}
}

// 检查状态
hasStatus(statusId: number): boolean {
const arrayIndex = Math.floor(statusId / StatusManager.BITS_PER_ELEMENT);
const bitPosition = statusId % StatusManager.BITS_PER_ELEMENT;
return (this.states[arrayIndex] & (1 << bitPosition)) !== 0;
}
}

2. 使用枚举和状态组实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 使用枚举定义状态ID
enum StatusEffectType {
NONE = -1,
// 控制类状态
STUN = 0,
SILENCE = 1,
ROOT = 2,
// 伤害类状态
POISON = 32,
BURN = 33,
BLEED = 34,
// 增益类状态
HASTE = 64,
SHIELD = 65,
REGENERATION = 66,
}

// 定义状态组
const StatusGroups = {
CONTROL: 0, // 0-31 用于控制类状态
DAMAGE: 1, // 32-63 用于伤害类状态
BUFF: 2, // 64-95 用于增益类状态
} as const;

class AdvancedStatusManager {
private statusArrays: Uint32Array[];

constructor() {
// 为每个状态组创建一个Uint32Array
this.statusArrays = new Array(Object.keys(StatusGroups).length)
.fill(null)
.map(() => new Uint32Array(1));
}

private getGroupAndBit(statusId: number): [number, number] {
const group = Math.floor(statusId / 32);
const bit = statusId % 32;
return [group, bit];
}

addStatus(status: StatusEffectType): void {
const [group, bit] = this.getGroupAndBit(status);
this.statusArrays[group][0] |= (1 << bit);
}

removeStatus(status: StatusEffectType): void {
const [group, bit] = this.getGroupAndBit(status);
this.statusArrays[group][0] &= ~(1 << bit);
}

hasStatus(status: StatusEffectType): boolean {
const [group, bit] = this.getGroupAndBit(status);
return (this.statusArrays[group][0] & (1 << bit)) !== 0;
}

// 检查是否有任何控制类状态
hasAnyControlEffect(): boolean {
return this.statusArrays[StatusGroups.CONTROL][0] !== 0;
}

// 清除所有伤害类状态
clearAllDamageEffects(): void {
this.statusArrays[StatusGroups.DAMAGE][0] = 0;
}
}

// 使用示例
const statusManager = new AdvancedStatusManager();
statusManager.addStatus(StatusEffectType.STUN);
statusManager.addStatus(StatusEffectType.POISON);

console.log(statusManager.hasStatus(StatusEffectType.STUN)); // true
console.log(statusManager.hasAnyControlEffect()); // true

3. 使用状态优先级系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
interface StatusEffect {
id: number;
priority: number;
duration: number;
group: number;
}

class PriorityStatusManager {
private activeEffects: Map<number, StatusEffect> = new Map();
private effectStates: Uint32Array[];

constructor(groupCount: number) {
this.effectStates = new Array(groupCount)
.fill(null)
.map(() => new Uint32Array(1));
}

addEffect(effect: StatusEffect): void {
// 检查是否已有更高优先级的效果
const existing = this.activeEffects.get(effect.id);
if (existing && existing.priority > effect.priority) {
return;
}

const [group, bit] = this.getGroupAndBit(effect.id);
this.effectStates[group][0] |= (1 << bit);
this.activeEffects.set(effect.id, effect);
}

// ... 其他方法类似
}

这些实现方式各有优势:

  1. TypedArray实现:

    • 内存效率高
    • 适合处理大量状态
    • 位操作性能好
  2. 枚举和状态组:

    • 更好的代码组织
    • 状态分类管理
    • 易于扩展和维护
  3. 优先级系统:

    • 支持状态优先级
    • 可以处理状态冲突
    • 更适合复杂的游戏系统

选择哪种实现方式取决于你的具体需求:

  • 如果主要考虑性能,使用TypedArray
  • 如果需要好的代码组织和可维护性,使用枚举和状态组
  • 如果需要处理复杂的状态交互,使用优先级系统

3. 性能优化

3.1 碰撞检测优化

  1. 预计算和缓存:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class CollisionOptimizer {
constructor() {
this.cachedResults = new Map();
}

// 缓存碰撞结果
cacheCollision(obj1Id, obj2Id, result) {
const key = this.getCacheKey(obj1Id, obj2Id);
this.cachedResults.set(key, {
result,
timestamp: Date.now()
});
}

// 使用位运算生成缓存键
getCacheKey(id1, id2) {
// 确保较小的ID在前
const minId = Math.min(id1, id2);
const maxId = Math.max(id1, id2);
// 组合两个ID成一个唯一的键
return (minId << 16) | maxId;
}
}

3.2 技能系统优化

  1. 状态更新优化:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class StatusManager {
constructor() {
this.activeEffects = new Map();
}

// 使用位运算批量更新状态
batchUpdate(character, newEffects) {
const oldEffects = character.activeEffects;
const addedEffects = newEffects & ~oldEffects;
const removedEffects = oldEffects & ~newEffects;

// 处理新增的效果
if (addedEffects) {
this.processAddedEffects(character, addedEffects);
}

// 处理移除的效果
if (removedEffects) {
this.processRemovedEffects(character, removedEffects);
}

character.activeEffects = newEffects;
}
}

4. 注意事项

  1. 碰撞检测注意事项:

    • 合理设计碰撞层级,避免不必要的检测
    • 定期清理碰撞缓存
    • 考虑物体大小差异
  2. 技能系统注意事项:

    • 状态效果的优先级处理
    • 免疫机制的实现
    • 效果的持续时间管理
  3. 性能优化建议:

    • 使用TypedArray存储大量数据
    • 实现对象池减少垃圾回收
    • 使用空间分区减少检测次数

总结

通过使用位运算,我们可以:

  1. 高效管理碰撞检测的层级关系
  2. 简化技能系统的状态管理
  3. 优化内存使用和计算性能
  4. 实现复杂的游戏机制

这些优化对于大型游戏尤其重要,可以显著提升游戏性能。