I have a small Clojure game (think Snake but multiplayer; if you hit another snake, you lose) running over WebSockets - logic is in the Clojure backend, rendering is in the browser.
Every "turn" of the game takes 100ms, during which the game step
s, which involves 1) calculating the next state of the game, 2) sending the game state to every player over WebSockets 3) checking if the game is over, and if not 4) sleeping for 100ms minus the time it took to do steps 1-3, and 5) looping back to 1.
There is a global atom games
, which is a map from a UUID to a game map (has player coordinates, directions, etc.). When a player presses an arrow key, the browser sends a message containing the game's UUID, the player's UUID, and the move. On receiving that message (independent of the game loop), the server directly modifies the games atom to update its to-moves
map to say that the player with some UUID wants to turn :right
. Step 1) above takes the to-moves list and changes each players' directions accordingly before moving each player forward (every 100ms). This method works.
I learned about core.async (go, channels, parking, etc.) but I'm not sure if it would be applicable in this case. I was originally thinking that instead of a :to-moves
map as part of the Game, I have a buffered channel instead. Then when a player submits a move I can do (>!! ch [<player-uuid> :left])
, for example. And when I calculate the next game, I can get the moves with (
This is more of a learning project, so if core.async will pretty much be the same as my current method that's fine. But is it applicable in the first place?
Thanks.