/** * big_watermelon.aigameplay — reducer 接口模板 * * Agent 生成实际 reducer 时,必须导出以下函数。 * 此文件是接口约束模板,不是可执行代码。 * * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ * ⚠️ 重要:渲染层(GameScene)不应直接调用 dispatch() * * dispatch() 是一体化接口,内部跑完整个物理帧 + 合并检测后只返回最终状态, * 中间过程(每帧位置更新、合并特效触发位置、新水果生成点)全部丢失。 * * 渲染层需要逐帧同步精灵位置、播放合并特效、实时更新分数, * 因此必须使用下方的「分步函数」逐步驱动,每步之间同步物理引擎和渲染状态。 * * dispatch() 的用途:无头测试、AI 模拟、快速跳过动画等场景。 * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ * * ⚠️ 物理集成说明: * 此 reducer 提供简化物理模拟(圆形碰撞体、重力积分)。 * 实际项目推荐将物理计算交给 Matter.js 或 Phaser Arcade Physics, * 每帧结束后将物理引擎的位置/速度数据写回 state.fruits。 */ // ─── 配置类型 ───────────────────────────────────────────────────────────────── export type Vec2 = { x: number; y: number }; export type BigWatermelonConfig = { /** 容器宽度(px) */ containerWidth: number; /** 容器高度(px) */ containerHeight: number; /** 溢出判定线(距顶部 y 坐标,px) */ overflowLine: number; /** 重力加速度(px/s²) */ gravity: number; /** 每个等级水果的半径(索引 0 = tier 1) */ fruitRadii: [number, number, number, number, number, number, number, number, number, number, number]; /** 下一个水果的最大等级(随机范围 1~nextFruitMaxTier) */ nextFruitMaxTier: number; /** 弹性系数(碰撞时速度保留比例,0~1) */ restitution: number; }; // ─── 动作类型 ───────────────────────────────────────────────────────────────── export type BigWatermelonAction = | { type: 'aimFruit'; x: number } | { type: 'dropFruit' } | { type: 'tick'; deltaMs: number } | { type: 'checkMerges' } | { type: 'checkOverflow' } | { type: 'reset' }; // ─── 状态类型 ───────────────────────────────────────────────────────────────── export type FruitPhysicsState = 'falling' | 'resting'; export type Fruit = { id: string; /** 水果等级 1~11 */ tier: number; /** 圆心坐标 */ position: Vec2; /** 速度(px/s) */ velocity: Vec2; /** 碰撞圆半径 */ radius: number; state: FruitPhysicsState; }; export type BigWatermelonState = { fruits: Fruit[]; score: number; currentFruit: { tier: number; x: number; radius: number; }; nextFruit: { tier: number; }; gameOver: boolean; win: false; lastMergeEvents: MergeEvent[]; }; // ─── 分步操作返回类型 ───────────────────────────────────────────────────────── export type MergeEvent = { fruitAId: string; fruitBId: string; mergedTier: number; mergePos: Vec2; scoreGained: number; }; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 必须导出的函数 // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // ─── 初始化 ────────────────────────────────────────────────────────────────── /** * init:根据配置初始化游戏状态 */ export declare function init(config: BigWatermelonConfig): BigWatermelonState; // ─── 一体化接口(测试/AI 模拟用) ─────────────────────────────────────────── /** * dispatch:接收动作,返回新状态(纯函数,不得修改原 state) * * ⚠️ 仅用于无头测试和 AI 模拟。渲染层请使用下方分步函数。 */ export declare function dispatch(state: BigWatermelonState, action: BigWatermelonAction): BigWatermelonState; /** * getState:返回当前状态快照 */ export declare function getState(state: BigWatermelonState): BigWatermelonState; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // 分步函数(渲染层/场景层必须使用这些函数驱动动画) // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** * aimFruit:玩家左右移动当前水果的水平位置 * 场景层根据返回的 currentFruit 更新瞄准线和预览水果精灵 x 坐标 * * x 会被钳制在 [radius, containerWidth - radius] 范围内 */ export declare function aimFruit( state: BigWatermelonState, x: number, ): { currentFruit: BigWatermelonState['currentFruit'] }; /** * dropFruit:投放当前水果,生成下一个预览水果 * 场景层创建物理刚体,设置初始速度 y=0,开始受重力影响 */ export declare function dropFruit( state: BigWatermelonState, ): { droppedFruit: Fruit; nextFruit: BigWatermelonState['nextFruit']; }; /** * applyPhysics:推进物理模拟一帧 * 对所有 falling 状态的水果: * - velocity.y += gravity * deltaMs / 1000 * - position += velocity * deltaMs / 1000 * - 检测底部和容器壁碰撞 * - 检测与 resting 水果的碰撞,碰撞后 state = resting * * 场景层根据返回的 fruits 数组逐个更新精灵位置(x, y) */ export declare function applyPhysics( state: BigWatermelonState, deltaMs: number, ): Fruit[]; /** * checkMerges:检测所有相同 tier 的水果是否发生碰撞触发合并 * 返回所有合并事件,场景层根据 mergePos 播放合并特效 * * 合并规则:两个圆心距 < r1 + r2,且 tier 相同 * 合并结果:移除两个旧水果,在 mergePos 生成 tier+1 新水果 */ export declare function checkMerges( state: BigWatermelonState, ): MergeEvent[]; /** * mergeFruits:执行一次具体的合并操作 * 场景层在播放合并动画(两球缩小 → 中点生成新球)后调用 */ export declare function mergeFruits( state: BigWatermelonState, fruitAId: string, fruitBId: string, ): { newFruit: Fruit; score: number; }; /** * checkOverflow:检查是否有静止水果超过溢出线 * 场景层在每次水果静止后调用 * gameOver=true 时场景层触发失败面板动画 */ export declare function checkOverflow( state: BigWatermelonState, ): { gameOver: boolean; overflowFruitId: string | null }; /** * calculateScore:计算合并该等级水果所得的分数 * 公式建议:tier^2 * 10(等级越高得分指数级增长) */ export declare function calculateScore(tier: number): number;