提交 7dd0cad2 authored 作者: lidongxu's avatar lidongxu

大方向是对了

上级 7b6d9a2c
......@@ -6,7 +6,7 @@ import { getAllPlayerStates, clearGameState, getCurrentRoom, getPlayerTeam, getC
import { initSocket, getConnectionStatus } from './socket.js'
import { drawBackground } from './renderer/background.js'
import { drawBubbleGrid } from './renderer/bubbleGrid.js'
import { drawBubble3D, BUBBLE_RADIUS } from './renderer/bubble.js'
import { drawBubble3D, getBubbleRadius, configureBubbleLayout } from './renderer/bubble.js'
import { drawShooter } from './renderer/shooter.js'
import { drawGameInfo, drawTeamResultOverlay } from './renderer/gameinfo.js'
import { detectAndCreateBursts, updateAndDrawBursts, clearPrevGrid } from './renderer/explosion.js'
......@@ -42,6 +42,12 @@ function applyScaler(playerCount = 1) {
function renderPlayer(state, offsetX, roomId) {
const pid = state.playerId ?? 1
// 从 grid 数据推算偶数行列数,动态调整泡泡大小
// 偶数行(row 0)的列数决定了整个网格的列配置
if (state.grid && state.grid.length && state.grid[0]) {
configureBubbleLayout(state.grid[0].length)
}
// 初始化该玩家的碎裂效果列表
if (!playerBursts.has(pid)) playerBursts.set(pid, [])
const bursts = playerBursts.get(pid)
......@@ -58,7 +64,7 @@ function renderPlayer(state, offsetX, roomId) {
if (state.fireBubbles && state.fireBubbles.length) {
for (const fb of state.fireBubbles) {
if (fb.active !== false) {
drawBubble3D(ctx, fb.x, fb.y, BUBBLE_RADIUS, fb.color || 1)
drawBubble3D(ctx, fb.x, fb.y, getBubbleRadius(), fb.color || 1)
}
}
}
......
......@@ -4,9 +4,31 @@
*/
import { SCREEN_WIDTH, SAFE_AREA_TOP } from '../constants.js'
// 11 个泡泡平铺满屏幕宽度:SCREEN_WIDTH = 11 × 2R = 22R
export const BUBBLE_RADIUS = SCREEN_WIDTH / 22
const ROW_HEIGHT = BUBBLE_RADIUS * Math.sqrt(3)
// ─── 动态列数适配 ────────────────────────────────────────────
// 默认 11 列(手机端),iPad 端可能 14~15 列
// 大屏端从收到的 grid 数据推算列数,动态调整泡泡大小
export let BUBBLE_RADIUS = SCREEN_WIDTH / 22
let ROW_HEIGHT = BUBBLE_RADIUS * Math.sqrt(3)
let GRID_OFFSET_X = 0
let _evenCols = 11
/**
* 根据偶数行列数重新计算泡泡大小和网格偏移
* 在每帧渲染前调用,从 grid 数据推算列数
* @param {number} evenCols 偶数行列数
*/
export function configureBubbleLayout(evenCols) {
if (evenCols === _evenCols) return
_evenCols = evenCols
BUBBLE_RADIUS = SCREEN_WIDTH / (evenCols * 2)
ROW_HEIGHT = BUBBLE_RADIUS * Math.sqrt(3)
GRID_OFFSET_X = (SCREEN_WIDTH - evenCols * 2 * BUBBLE_RADIUS) / 2
}
/** 获取当前泡泡半径(供需要实时值的模块使用) */
export function getBubbleRadius() { return BUBBLE_RADIUS }
/** 获取当前网格偏移 */
export function getGridOffsetX() { return GRID_OFFSET_X }
/**
* 9 种泡泡颜色(颜色索引 1-9),用于爆炸粒子效果取色。
......@@ -102,7 +124,7 @@ export function getActiveColorCount(score) {
*/
export function gridToScreen(row, col) {
const R = BUBBLE_RADIUS
const x = row % 2 === 0 ? col * 2 * R + R : col * 2 * R + 2 * R
const y = row * ROW_HEIGHT + R + SAFE_AREA_TOP
const x = GRID_OFFSET_X + (row % 2 === 0 ? col * 2 * R + R : col * 2 * R + 2 * R)
const y = ROW_HEIGHT * row + R + SAFE_AREA_TOP
return { x, y }
}
......@@ -2,7 +2,7 @@
* 泡泡网格渲染(移植自 minigame-1)
* 根据 state 中的 grid 二维数组和 pushAnimOffsetY 绘制网格泡泡
*/
import { BUBBLE_RADIUS, gridToScreen, drawBubble3D } from './bubble.js'
import { getBubbleRadius, gridToScreen, drawBubble3D } from './bubble.js'
/**
* 绘制泡泡网格
......@@ -20,7 +20,7 @@ export function drawBubbleGrid(ctx, grid, pushAnimOffsetY = 0) {
const color = rowArr[col]
if (!color) continue
const { x, y } = gridToScreen(row, col)
drawBubble3D(ctx, x, y + offsetY, BUBBLE_RADIUS, color)
drawBubble3D(ctx, x, y + offsetY, getBubbleRadius(), color)
}
}
}
......@@ -6,7 +6,7 @@
*
* 动画过程:闪光 → 碎片四散 → 渐隐消失,只播放一次。
*/
import { BUBBLE_RADIUS, BUBBLE_COLORS, gridToScreen } from './bubble.js'
import { getBubbleRadius, BUBBLE_COLORS, gridToScreen } from './bubble.js'
// ─── 碎片粒子 ─────────────────────────────────────────────────────────────────
......@@ -68,8 +68,8 @@ class Ring {
this.x = x
this.y = y
this.color = color
this.r = BUBBLE_RADIUS * 0.3
this.maxR = BUBBLE_RADIUS * 2.2
this.r = getBubbleRadius() * 0.3
this.maxR = getBubbleRadius() * 2.2
this.life = 0
this.maxLife = 40
}
......@@ -81,7 +81,7 @@ class Ring {
update() {
this.life++
const t = this.life / this.maxLife
this.r = BUBBLE_RADIUS * 0.3 + (this.maxR - BUBBLE_RADIUS * 0.3) * t
this.r = getBubbleRadius() * 0.3 + (this.maxR - getBubbleRadius() * 0.3) * t
this.alpha = 0.6 * (1 - t)
}
......@@ -107,7 +107,7 @@ class BubbleBurst {
this._y = y
const colorHex = BUBBLE_COLORS[colorIdx] || '#ffffff'
const R = BUBBLE_RADIUS
const R = getBubbleRadius()
this.flashAlpha = 1.0
this.ring = new Ring(x, y, colorHex)
......@@ -156,7 +156,7 @@ class BubbleBurst {
ctx.globalAlpha = this.flashAlpha * 0.7
ctx.fillStyle = '#ffffff'
ctx.beginPath()
ctx.arc(this._x, this._y, BUBBLE_RADIUS * 1.3, 0, Math.PI * 2)
ctx.arc(this._x, this._y, getBubbleRadius() * 1.3, 0, Math.PI * 2)
ctx.fill()
ctx.restore()
}
......
......@@ -3,7 +3,7 @@
* 三种状态:未连接、已连接无房间、已连接有房间等待游戏
*/
import { SCREEN_WIDTH, SCREEN_HEIGHT } from '../constants.js'
import { drawBubble3D, BUBBLE_RADIUS } from './bubble.js'
import { drawBubble3D, getBubbleRadius } from './bubble.js'
let _frame = 0
......@@ -26,7 +26,7 @@ function rr(ctx, x, y, w, h, r) {
// ─── 装饰泡泡(顶部三行漂浮泡泡)────────────────────────────────────────────────
const _decorBubbles = (() => {
const R = BUBBLE_RADIUS
const R = getBubbleRadius()
const list = []
let sx = 0.456
const rand = () => { sx = (sx * 9301 + 49297) % 233280; return sx / 233280 }
......@@ -47,7 +47,7 @@ function drawDecorBubbles(ctx) {
ctx.globalAlpha = 0.55
for (const b of _decorBubbles) {
const dy = Math.sin(_frame * 0.018 + b.phase) * 3
drawBubble3D(ctx, b.x, b.y + dy, BUBBLE_RADIUS, b.color)
drawBubble3D(ctx, b.x, b.y + dy, getBubbleRadius(), b.color)
}
ctx.restore()
}
......@@ -344,11 +344,11 @@ export function drawIdleScreen(ctx, width, height, roomId, connStatus, screenNam
drawDecorBubbles(ctx)
// 顶部遮罩(让泡泡看起来更像背景)
const topMask = ctx.createLinearGradient(0, 0, 0, BUBBLE_RADIUS * 4)
const topMask = ctx.createLinearGradient(0, 0, 0, getBubbleRadius() * 4)
topMask.addColorStop(0, 'rgba(30,12,60,0)')
topMask.addColorStop(1, 'rgba(30,12,60,0.55)')
ctx.fillStyle = topMask
ctx.fillRect(0, 0, width, BUBBLE_RADIUS * 4)
ctx.fillRect(0, 0, width, getBubbleRadius() * 4)
// 浮动粒子
drawParticles(ctx, width, height)
......
......@@ -3,15 +3,8 @@
* 鸡身体朝向跟随瞄准方向倾斜 + 呼吸浮动 + 弹跳动画
*/
import { SCREEN_WIDTH, SCREEN_HEIGHT, SAFE_AREA_BOTTOM } from '../constants.js'
import { BUBBLE_RADIUS, drawBubble3D } from './bubble.js'
// 鸡的尺寸
const CHICKEN_WIDTH = BUBBLE_RADIUS * 5
const CHICKEN_HEIGHT = BUBBLE_RADIUS * 6
const CHICKEN_BOTTOM_MARGIN = BUBBLE_RADIUS * 0.8
const BUBBLE_TOP_OFFSET = BUBBLE_RADIUS * 0.4
const NEXT_X_OFFSET = BUBBLE_RADIUS * 3.2
const NEXT_Y_OFFSET = BUBBLE_RADIUS * 0.5
import { getBubbleRadius, drawBubble3D } from './bubble.js'
const NEXT_SCALE = 0.65
// 鸡朝向参数
......@@ -20,7 +13,6 @@ const MAX_ANGLE = 165 * Math.PI / 180
const MAX_LEAN_ANGLE = 25 * Math.PI / 180
const LEAN_LERP = 0.15
const BOB_SPEED = 0.03
const BOB_AMOUNT = BUBBLE_RADIUS * 0.15
// 加载鸡图片
const _chickenImg = new Image()
......@@ -31,7 +23,7 @@ let _currentLean = 0
let _bobPhase = 0
function calcAimPoints(originX, originY, angle) {
const R = BUBBLE_RADIUS
const R = getBubbleRadius()
const points = [{ x: originX, y: originY }]
let cx = originX, cy = originY
let vx = Math.cos(angle), vy = -Math.sin(angle)
......@@ -76,10 +68,17 @@ function drawAimLine(ctx, aimPoints) {
export function drawShooter(ctx, shooterState) {
if (!shooterState) return
const R = getBubbleRadius()
const CHICKEN_WIDTH = R * 5
const CHICKEN_HEIGHT = R * 6
const CHICKEN_BOTTOM_MARGIN = R * 0.8
const BUBBLE_TOP_OFFSET = R * 0.4
const NEXT_X_OFFSET = R * 3.2
const NEXT_Y_OFFSET = R * 0.5
const x = SCREEN_WIDTH / 2
const chickenBottom = SCREEN_HEIGHT - SAFE_AREA_BOTTOM - CHICKEN_BOTTOM_MARGIN
const bubbleBaseY = chickenBottom - CHICKEN_HEIGHT - BUBBLE_TOP_OFFSET
const R = BUBBLE_RADIUS
const aimAngle = shooterState.aimAngle ?? Math.PI / 2
const isAiming = shooterState.isAiming ?? false
......@@ -100,7 +99,7 @@ export function drawShooter(ctx, shooterState) {
// 呼吸浮动
_bobPhase += BOB_SPEED
if (_bobPhase > Math.PI * 2) _bobPhase -= Math.PI * 2
const bobOffset = Math.sin(_bobPhase) * BOB_AMOUNT
const bobOffset = Math.sin(_bobPhase) * R * 0.15
// 瞄准线
const aimPoints = shooterState.aimPoints ?? (isAiming ? calcAimPoints(x, bubbleBaseY, aimAngle) : [])
......
minigame-1 @ 6fe51eaf
Subproject commit 8ab3c7c4b7f885eea0ef9c4d9f51f3fa08188665
Subproject commit 6fe51eaf29c8e38ac9804b5991a841aa88ea235f
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论