feat: 添加游戏内动画特效,优化玩家卡片UI并调整布局。
This commit is contained in:
parent
191895567c
commit
58d9edc766
File diff suppressed because it is too large
Load Diff
@ -156,12 +156,13 @@
|
||||
v-for="(cell, i) in gameState.grid"
|
||||
:key="i"
|
||||
class="grid-cell"
|
||||
:class="{
|
||||
'revealed': cell.revealed,
|
||||
'type-bomb': cell.revealed && cell.type === 'bomb',
|
||||
'bg-slate-800': !cell.revealed,
|
||||
'has-magnifier': myPlayer && myPlayer.revealedCells && myPlayer.revealedCells[i]
|
||||
}"
|
||||
:class="[
|
||||
cell.revealed ? (cell.type === 'bomb' ? 'type-bomb explosion' : (cell.type === 'item' ? 'type-item item-' + (cell.itemId || 'generic') : 'type-empty')) : 'bg-slate-800',
|
||||
{
|
||||
'revealed': cell.revealed,
|
||||
'has-magnifier': myPlayer && myPlayer.revealedCells && myPlayer.revealedCells[i]
|
||||
}
|
||||
]"
|
||||
@tap="handleCellClick(i)"
|
||||
>
|
||||
<view v-if="cell.revealed">
|
||||
@ -555,6 +556,11 @@ export default {
|
||||
console.log('[我的位置]', data.turnOrder?.indexOf(this.myUserId));
|
||||
console.log('[网格大小]', data.gridSize);
|
||||
console.log('[游戏状态]', data);
|
||||
console.log('[DEBUG] myUserId:', this.myUserId);
|
||||
console.log('[DEBUG] turnOrder:', data.turnOrder);
|
||||
console.log('[DEBUG] currentTurnIndex:', data.currentTurnIndex);
|
||||
console.log('[DEBUG] 当前回合玩家:', data.turnOrder?.[data.currentTurnIndex]);
|
||||
console.log('[DEBUG] isMyTurn?', data.turnOrder?.[data.currentTurnIndex] === this.myUserId);
|
||||
console.log('================================');
|
||||
} else if (opCode === 6) {
|
||||
// ========== 控制台日志 - 游戏结束 ==========
|
||||
@ -565,13 +571,42 @@ export default {
|
||||
console.log('================================');
|
||||
}
|
||||
|
||||
if (opCode === 1 || opCode === 2) {
|
||||
if (opCode === 1) {
|
||||
this.gameState = data;
|
||||
this.addLog('system', '战局开始,准备翻格!');
|
||||
} else if (opCode === 2) {
|
||||
// 状态更新 - 检测 HP 变化触发特效
|
||||
const prevState = this.gameState;
|
||||
if (prevState && prevState.players) {
|
||||
Object.keys(data.players || {}).forEach(uid => {
|
||||
const prevP = prevState.players[uid];
|
||||
const newP = data.players[uid];
|
||||
if (!prevP || !newP) return;
|
||||
|
||||
const hpDiff = newP.hp - prevP.hp;
|
||||
if (hpDiff < 0) {
|
||||
// 受伤
|
||||
const dmg = Math.abs(hpDiff);
|
||||
this.spawnLabel(0, 0, `-${dmg}`, 'damage', undefined, uid);
|
||||
this.triggerDamageEffect(uid, dmg);
|
||||
} else if (hpDiff > 0) {
|
||||
// 治疗
|
||||
const heal = Math.abs(hpDiff);
|
||||
this.spawnLabel(0, 0, `+${heal}`, 'heal', undefined, uid);
|
||||
this.healedPlayers.push(uid);
|
||||
setTimeout(() => this.healedPlayers = this.healedPlayers.filter(id => id !== uid), 600);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.gameState = data;
|
||||
if (opCode === 1) this.addLog('system', '战局开始,准备翻格!');
|
||||
} else if (opCode === 5) {
|
||||
this.handleEvent(data);
|
||||
} else if (opCode === 6) {
|
||||
this.gameState = data;
|
||||
if (data.gameState) {
|
||||
this.gameState = data.gameState;
|
||||
} else {
|
||||
this.gameState = data;
|
||||
}
|
||||
this.addLog('system', `战局结束:${data.winnerId === this.myUserId ? '您获得了胜利!' : '很遗憾失败了'}`);
|
||||
}
|
||||
},
|
||||
@ -593,6 +628,7 @@ export default {
|
||||
if (event.type === 'damage' || event.type === 'item') {
|
||||
if (iAmTarget && event.value) this.spawnLabel(0, 0, `-${event.value}`, 'damage', undefined, this.myUserId);
|
||||
}
|
||||
// 对于 opCode 5 的 damage 事件,也触发特效(通常 opCode 2 会覆盖,但多触发一次无妨,作为保险)
|
||||
if (event.type === 'damage' && iAmTarget) this.triggerDamageEffect(this.myUserId, event.value);
|
||||
}
|
||||
},
|
||||
@ -661,22 +697,32 @@ export default {
|
||||
return this.getItemIcon(content);
|
||||
},
|
||||
getPlayerAvatar(player) {
|
||||
// 如果服务器已经发送了avatar字段,直接使用
|
||||
if (player.avatar) {
|
||||
return player.avatar;
|
||||
// 优先从 character 字段获取 emoji
|
||||
const charAvatars = {
|
||||
dog: '🐶',
|
||||
elephant: '🐘',
|
||||
tiger: '🐯',
|
||||
monkey: '🐵',
|
||||
sloth: '🦥',
|
||||
hippo: '🦛',
|
||||
cat: '🐱',
|
||||
chicken: '🐔'
|
||||
};
|
||||
if (player.character && charAvatars[player.character]) {
|
||||
return charAvatars[player.character];
|
||||
}
|
||||
|
||||
// 否则,根据userId或username确定性分配一个动物头像
|
||||
const avatars = ['🐶', '🐘', '🐯', '🐵', '🦥', '🦛'];
|
||||
// 如果服务器直接发送了 avatar 字段
|
||||
if (player.avatar) return player.avatar;
|
||||
|
||||
// 使用userId或username作为哈希种子,确保同一玩家总是获得相同的头像
|
||||
// 降级:根据 userId 确定性分配
|
||||
const avatars = ['🐶', '🐘', '🐯', '🐵', '🦥', '🦛'];
|
||||
const seed = player.userId || player.username || player.id || '';
|
||||
let hash = 0;
|
||||
for (let i = 0; i < seed.length; i++) {
|
||||
hash = ((hash << 5) - hash) + seed.charCodeAt(i);
|
||||
hash = hash & hash; // 转换为32位整数
|
||||
}
|
||||
|
||||
const index = Math.abs(hash) % avatars.length;
|
||||
return avatars[index];
|
||||
},
|
||||
|
||||
@ -340,7 +340,8 @@ class NakamaManager {
|
||||
}
|
||||
this.isConnected = false;
|
||||
this.session = null;
|
||||
this.gameToken = null;
|
||||
// 注意:不要清空 gameToken,以便重连时仍然可以使用
|
||||
// this.gameToken 只在 logout 或新 authenticate 时才会被更新
|
||||
console.log('[Nakama] Disconnected');
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user