I use redux as a state container in a simple shooter game. The state is completely determinate, the only input that the system receives is user input (for example, a weapon has been fired, etc.). My problem is that I have to track (and process) certain events that occur during the game (for example, something was destroyed, etc.), and I'm not quite sure how to do this. My real solution is that the reducer maintains the events array in its current state, and each reducer simply adds events to it.
FIRE_WEAPON+-+ FIRE_WEAPON+-+ | | | | +-v--------+--------------v-------------> | | +->PLAYER_DESTROYED
Two FIRE_WEAPON actions get abbreviations FIRE_WEAPON and should "emit" the PLAYER_DESTROYED event (right now it is used to render there).
The project is open source, the gearbox looks something like this (it's just pseudo-code, but here is the corresponding game logic ):
// 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), }; }
We can assume that handleUserInput is a simple identity function x => x (it does not apply to the events array). During evolve I would like to βemitβ events, but since this would make evolve unclean, I cannot do this. As I said, now I am doing this, keeping the events that have happened in a state, but there may be a better way. Any suggestions?
These events are used during rendering, which looks like this:
let sprites = [];
But later, I would like to use events on the server (the reducer described above also runs on the server) to calculate various characteristics (for example, destroyed enemies, etc.).
Ps: these "emitted" events do not affect the state (they are completely unrelated), so I am sure that they should not be actions (because they will leave the state unchanged). They are processed after the reducer completes, after which they can be discarded (the reducer always receives an empty events array).