我redux
在一个简单的射击游戏中用作状态容器.状态是完全确定的,系统接收的唯一输入是用户输入(例如,武器被解雇等).我的问题是我必须跟踪(和处理)在游戏过程中发生的某些事件(例如某些东西被破坏等),而我不太清楚如何做到这一点.我目前的解决方案是reducer events
在当前状态下维护一个数组,每个reducer只是向它添加事件.
FIRE_WEAPON+-+ FIRE_WEAPON+-+ | | | | +-v--------+--------------v-------------> | | +->PLAYER_DESTROYED
这里减少接收两个FIRE_WEAPON
动作,并应"发出"一个PLAYER_DESTROYED
事件(现在,它用于在那里渲染爆炸).
该项目是开源的,reducer看起来像这样(它只是伪代码,但这是相关的游戏逻辑):
// combine is just (f, g) => ((s, a) => g(f(s, a), a)) const reducer = combine( // simulate world (state, action) => { while (state.time < action.time) { state = evolve(state, delta); // evolve appends the happened in-game events to the state } return state; }, // handle actual user input (state, action) => { return handleUserInput(state, action); } ); const evolve = (state, delta) => { const events = []; // some game logic that does some `events.push(...)` return { ...state, time: state.time + delta, events: state.events.concat(events), }; }
我们可以假设,这handleUserInput
是一个简单的x => x
身份函数(它不接触events
数组).期间evolve
,我想"发出"事件,但由于这会使evolve
不纯洁,我不能这样做.正如我所说,现在我通过将发生的事件存储在州中来做到这一点,但可能有更好的方法.有什么建议?
这些events
在渲染过程中使用,看起来像这样:
let sprites = []; // `subscribe`d to store function onStateChange() { // `obsolete` removes old sprites that should not be displayed anymore // `toSprite` converts events to sprites, you can assume that they are just simple objects sprites = sprites.filter(obsolete).concat(store.getState().events.map(toSprite)); } function render(state) { renderState(state); renderSprites(sprites); }
但是后来我想events
在服务器上使用(上面描述的reducer也在服务器上运行),用于计算各种统计数据(例如,被摧毁的敌人等).
Ps:这些"发射"事件对国家没有影响(它们完全不相关),所以我确信它们不应该是行动(因为它们会使状态保持不变).在reducer完成后处理它们,之后它们可以被丢弃(reducer总是接收一个空events
数组).