提交 f2fef882 authored 作者: lidongxu's avatar lidongxu

大屏碎裂效果完美版本

上级 16dd650a
...@@ -9,7 +9,7 @@ import { drawBubbleGrid } from './renderer/bubbleGrid.js' ...@@ -9,7 +9,7 @@ import { drawBubbleGrid } from './renderer/bubbleGrid.js'
import { drawBubble3D, BUBBLE_RADIUS } from './renderer/bubble.js' import { drawBubble3D, BUBBLE_RADIUS } from './renderer/bubble.js'
import { drawShooter } from './renderer/shooter.js' import { drawShooter } from './renderer/shooter.js'
import { drawGameInfo, drawTeamResultOverlay } from './renderer/gameinfo.js' import { drawGameInfo, drawTeamResultOverlay } from './renderer/gameinfo.js'
import { updateAndDrawExplosions, appendExplosionsFromState, Explosion, setExplosionQuality } from './renderer/explosion.js' import { detectAndCreateBursts, updateAndDrawBursts, clearPrevGrid } from './renderer/explosion.js'
import { drawIdleScreen } from './renderer/idleScreen.js' import { drawIdleScreen } from './renderer/idleScreen.js'
import { SCREEN_WIDTH, SCREEN_HEIGHT } from './constants.js' import { SCREEN_WIDTH, SCREEN_HEIGHT } from './constants.js'
...@@ -19,8 +19,8 @@ const ctx = canvas.getContext('2d') ...@@ -19,8 +19,8 @@ const ctx = canvas.getContext('2d')
const SCREEN_NAME = import.meta.env.VITE_SCREEN_NAME || 'big-screen-1' const SCREEN_NAME = import.meta.env.VITE_SCREEN_NAME || 'big-screen-1'
/** 每个玩家独立的爆炸列表:Map<playerId, Explosion[]> */ /** 每个玩家独立的碎裂效果列表:Map<playerId, BubbleBurst[]> */
const playerExplosions = new Map() const playerBursts = new Map()
let frameCount = 0 let frameCount = 0
...@@ -42,9 +42,9 @@ function applyScaler(playerCount = 1) { ...@@ -42,9 +42,9 @@ function applyScaler(playerCount = 1) {
function renderPlayer(state, offsetX, roomId) { function renderPlayer(state, offsetX, roomId) {
const pid = state.playerId ?? 1 const pid = state.playerId ?? 1
// 初始化该玩家的爆炸列表 // 初始化该玩家的碎裂效果列表
if (!playerExplosions.has(pid)) playerExplosions.set(pid, []) if (!playerBursts.has(pid)) playerBursts.set(pid, [])
const explosions = playerExplosions.get(pid) const bursts = playerBursts.get(pid)
ctx.save() ctx.save()
ctx.translate(offsetX, 0) ctx.translate(offsetX, 0)
...@@ -63,12 +63,11 @@ function renderPlayer(state, offsetX, roomId) { ...@@ -63,12 +63,11 @@ function renderPlayer(state, offsetX, roomId) {
} }
} }
// 爆炸特效:消费后立即清空,避免下一帧重复添加 // 碎裂特效:通过对比前后帧grid自动检测消失的球
if (state.explosions && state.explosions.length) { if (state.grid) {
appendExplosionsFromState(explosions, state.explosions) detectAndCreateBursts(bursts, pid, state.grid, state.pushAnimOffsetY ?? 0)
state.explosions = []
} }
updateAndDrawExplosions(ctx, explosions) updateAndDrawBursts(ctx, bursts)
// 射击器 // 射击器
if (state.shooter) { if (state.shooter) {
...@@ -196,15 +195,15 @@ function loop() { ...@@ -196,15 +195,15 @@ function loop() {
const teamBStates = states.filter(s => getPlayerTeam(s.playerId ?? 1) === 'B') const teamBStates = states.filter(s => getPlayerTeam(s.playerId ?? 1) === 'B')
const totalSlots = Math.max(teamAStates.length + teamBStates.length, 1) const totalSlots = Math.max(teamAStates.length + teamBStates.length, 1)
// 人数变化时重新计算缩放和爆炸质量 // 人数变化时重新计算缩放
if (totalSlots !== _lastPlayerCount) { if (totalSlots !== _lastPlayerCount) {
_lastPlayerCount = totalSlots _lastPlayerCount = totalSlots
applyScaler(totalSlots) applyScaler(totalSlots)
setExplosionQuality(totalSlots) // 根据人数调整爆炸效果质量 // 清理消失玩家的碎裂列表和grid快照
// 清理消失玩家的爆炸列表 for (const pid of playerBursts.keys()) {
for (const pid of playerExplosions.keys()) {
if (!states.find(s => (s.playerId ?? 1) === pid)) { if (!states.find(s => (s.playerId ?? 1) === pid)) {
playerExplosions.delete(pid) playerBursts.delete(pid)
clearPrevGrid(pid)
} }
} }
} }
...@@ -250,11 +249,9 @@ function loop() { ...@@ -250,11 +249,9 @@ function loop() {
// ── 检测是否所有玩家都结束,显示队伍比分 ───────────────────────────── // ── 检测是否所有玩家都结束,显示队伍比分 ─────────────────────────────
const allGameOver = states.every(s => s.isGameOver) const allGameOver = states.every(s => s.isGameOver)
console.log('[BigScreen] 游戏状态检查', { allGameOver, statesCount: states.length, totalSlots, canvasWidth: canvas.width, SCREEN_WIDTH })
if (allGameOver && states.length > 1) { if (allGameOver && states.length > 1) {
// 全屏显示队伍比分(传入实际的大屏宽度) // 全屏显示队伍比分(传入实际的大屏宽度)
const totalWidth = SCREEN_WIDTH * totalSlots const totalWidth = SCREEN_WIDTH * totalSlots
console.log('[BigScreen] 显示队伍比分', { totalSlots, totalWidth, canvasWidth: canvas.width, states: states.length })
ctx.save() ctx.save()
ctx.setTransform(1, 0, 0, 1, 0, 0) ctx.setTransform(1, 0, 0, 1, 0, 0)
drawTeamResultOverlay(ctx, states, getPlayerTeam, totalWidth) drawTeamResultOverlay(ctx, states, getPlayerTeam, totalWidth)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论