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

差不多了,但是多量词

上级 0d709a43
...@@ -63,11 +63,11 @@ function renderPlayer(state, offsetX, roomId) { ...@@ -63,11 +63,11 @@ function renderPlayer(state, offsetX, roomId) {
} }
} }
// 爆炸特效 // 爆炸特效(传入pushAnimOffsetY修正位置)
if (state.explosions && state.explosions.length) { if (state.explosions && state.explosions.length) {
appendExplosionsFromState(explosions, state.explosions) appendExplosionsFromState(explosions, state.explosions, state.pushAnimOffsetY ?? 0)
} }
updateAndDrawExplosions(ctx, explosions) updateAndDrawExplosions(ctx, explosions, frameCount)
// 射击器 // 射击器
if (state.shooter) { if (state.shooter) {
......
...@@ -149,7 +149,7 @@ export class Explosion { ...@@ -149,7 +149,7 @@ export class Explosion {
const R = BUBBLE_RADIUS const R = BUBBLE_RADIUS
const cfg = QUALITY_CONFIG[currentQuality] const cfg = QUALITY_CONFIG[currentQuality]
this.flashLife = isFloating ? 4 : 10 this.flashLife = isFloating ? 1 : 1 // 只闪一下
this._x = x this._x = x
this._y = y this._y = y
this._colorHex = colorHex this._colorHex = colorHex
...@@ -280,14 +280,27 @@ export class Explosion { ...@@ -280,14 +280,27 @@ export class Explosion {
// ─── 工具函数(供 main.js 调用)────────────────────────────────────────────── // ─── 工具函数(供 main.js 调用)──────────────────────────────────────────────
/** 大屏帧计数器,用于控制爆炸更新频率 */
let globalFrameCount = 0
/** /**
* 更新并绘制爆炸列表,移除已结束的实例 * 更新并绘制爆炸列表,移除已结束的实例
* 注意:大屏是60fps,但小游戏只上报15fps,所以每4帧才更新一次爆炸动画,保持速度一致
*/ */
export function updateAndDrawExplosions(ctx, explosionList) { export function updateAndDrawExplosions(ctx, explosionList, frameCount) {
if (!explosionList || !explosionList.length) return if (!explosionList || !explosionList.length) return
// 使用传入的帧计数器或内部计数器
globalFrameCount = frameCount ?? globalFrameCount + 1
// 每4帧更新一次爆炸动画(与小游戏15fps同步)
const shouldUpdate = (globalFrameCount % 4 === 0)
for (let i = explosionList.length - 1; i >= 0; i--) { for (let i = explosionList.length - 1; i >= 0; i--) {
const e = explosionList[i] const e = explosionList[i]
if (shouldUpdate) {
e.update() e.update()
}
e.render(ctx) e.render(ctx)
if (!e.alive) explosionList.splice(i, 1) if (!e.alive) explosionList.splice(i, 1)
} }
...@@ -302,18 +315,32 @@ const MAX_EXPLOSIONS_PER_PLAYER = 50 ...@@ -302,18 +315,32 @@ const MAX_EXPLOSIONS_PER_PLAYER = 50
/** /**
* 根据状态中的新爆炸事件追加 Explosion 实例 * 根据状态中的新爆炸事件追加 Explosion 实例
* 确保每个消除的泡泡都有爆炸效果 * 确保每个消除的泡泡都有爆炸效果,避免重复添加
* @param {number} pushAnimOffsetY 下推动画Y偏移(小游戏传来的爆炸坐标需要减去这个偏移)
*/ */
export function appendExplosionsFromState(explosionList, newExplosions) { export function appendExplosionsFromState(explosionList, newExplosions, pushAnimOffsetY = 0) {
if (!newExplosions || !newExplosions.length) return if (!newExplosions || !newExplosions.length) return
// 如果新爆炸数量超过限制,优先保留前面的(确保每个泡泡都有爆炸) // 偏移量:小游戏传来的爆炸坐标包含了当时的pushAnimOffsetY,需要减去当前偏移
const availableSlots = Math.max(0, MAX_EXPLOSIONS_PER_PLAYER - explosionList.length) const offsetY = pushAnimOffsetY || 0
const explosionsToAdd = newExplosions.slice(0, availableSlots)
// 去重:检查是否已存在相同位置和颜色的爆炸(避免每帧重复添加)
const existingKeys = new Set(explosionList.map(e => `${e._x},${e._y},${e._colorHex}`))
for (const { x, y, colorHex, color } of newExplosions) {
// 如果已满,停止添加
if (explosionList.length >= MAX_EXPLOSIONS_PER_PLAYER) break
for (const { x, y, colorHex, color } of explosionsToAdd) {
// 优先用 colorHex(小游戏序列化传来的十六进制),回退到颜色索引 // 优先用 colorHex(小游戏序列化传来的十六进制),回退到颜色索引
const c = colorHex || color || 1 const c = colorHex || color || 1
explosionList.push(new Explosion(x, y, c, false)) // 修正Y坐标
const correctedY = y - offsetY
// 去重检查:相同位置和颜色的爆炸只添加一次
const key = `${x},${correctedY},${c}`
if (existingKeys.has(key)) continue
existingKeys.add(key)
explosionList.push(new Explosion(x, correctedY, c, false))
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论