提交 16dd650a authored 作者: lidongxu's avatar lidongxu

大屏和微信小游戏球体爆炸数量和时长一致了但是大屏上为了兼容还是播放很多次炸裂效果

上级 cf3fae98
......@@ -63,11 +63,12 @@ function renderPlayer(state, offsetX, roomId) {
}
}
// 爆炸特效(传入pushAnimOffsetY修正位置)
// 爆炸特效:消费后立即清空,避免下一帧重复添加
if (state.explosions && state.explosions.length) {
appendExplosionsFromState(explosions, state.explosions, state.pushAnimOffsetY ?? 0)
appendExplosionsFromState(explosions, state.explosions)
state.explosions = []
}
updateAndDrawExplosions(ctx, explosions, frameCount)
updateAndDrawExplosions(ctx, explosions)
// 射击器
if (state.shooter) {
......
......@@ -280,67 +280,32 @@ export class Explosion {
// ─── 工具函数(供 main.js 调用)──────────────────────────────────────────────
/** 大屏帧计数器,用于控制爆炸更新频率 */
let globalFrameCount = 0
/**
* 更新并绘制爆炸列表,移除已结束的实例
* 注意:大屏是60fps,但小游戏只上报15fps,所以每4帧才更新一次爆炸动画,保持速度一致
*/
export function updateAndDrawExplosions(ctx, explosionList, frameCount) {
export function updateAndDrawExplosions(ctx, explosionList) {
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--) {
const e = explosionList[i]
if (shouldUpdate) {
e.update()
}
e.update()
e.render(ctx)
if (!e.alive) explosionList.splice(i, 1)
}
}
/**
* 单玩家最大爆炸实例数,超出丢弃避免卡顿
* 按玩家独立计算,避免4人同屏时互相抢占额度
* 考虑到一次消除可能有3-10个泡泡,悬空掉落可能更多,设置足够大的值
*/
/** 单玩家最大爆炸实例数 */
const MAX_EXPLOSIONS_PER_PLAYER = 50
/**
* 根据状态中的新爆炸事件追加 Explosion 实例
* 确保每个消除的泡泡都有爆炸效果,避免重复添加
* @param {number} pushAnimOffsetY 下推动画Y偏移(小游戏传来的爆炸坐标需要减去这个偏移)
* 小游戏端已保证每个爆炸只发送一次(待发送队列机制),这里直接添加即可
*/
export function appendExplosionsFromState(explosionList, newExplosions, pushAnimOffsetY = 0) {
export function appendExplosionsFromState(explosionList, newExplosions) {
if (!newExplosions || !newExplosions.length) return
// 偏移量:小游戏传来的爆炸坐标包含了当时的pushAnimOffsetY,需要减去当前偏移
const offsetY = pushAnimOffsetY || 0
// 去重:检查是否已存在相同位置和颜色的爆炸(避免每帧重复添加)
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
// 优先用 colorHex(小游戏序列化传来的十六进制),回退到颜色索引
const c = colorHex || color || 1
// 修正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))
explosionList.push(new Explosion(x, y, c, false))
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论