@nbtheduke not sure about your OO envy, if it's that strong you may want to reconsider idiomatic Clojure as your language. In terms of how to structure your code, a turn-based game and a simple platformer need not be so different. This depends a lot on how the platformer is setup, but often (and in my own games, which are typically shmups) the game has a fixed frame rate. I try for 60fps, so I essentially pass the game state (a nested map) through everything. It gets updated, and finally rendered. Your turn-based would be similar, just that it's not updated at 60fps. Store the game state in some kind of map structure, and when an action is performed, update the state. Finally, once a turn is complete, and various checks are made, you update the screen.
So doing a lot of (swap! gamestate update-in [...] blah blah)
isn't a code smell in game dev? I think that's one of the issues I'm facing: clojure is built for immutability, and game state manipulation is very mutable, so it feels like I'm doing something wrong by relying on it
and thanks for the reply, it's helpful to hear from other devs
Well, swap! is unnecessary in my case until the last step, pre-rendering. Before that, a 2D game is best (my opinion) as a single thread. So just thread the map (state) through your functions and swap! at the end. I suspect you don't need to swap! a lot either.
Oh clever
How do you handle user interaction without pausing the whole thread?
dang, yeah, i love the idea of threading with a swap at the end
I'm using play-clj which wraps lib-gdx. What it ends up looking like is each frame I check the state of mouse/joystick/keyboard elements I'm interested in. Been awhile since I've looked at some of the code, but in my "move player ship" function I'll check the state of, for example, arrow keys and shot keys and modify the player component of the state map accordingly. Update location, spawn a bullet, etc. All gets added to the state map and eventually rendered that 'tick' of the clock.
(keypressed? UP) etc.
that makes sense
so no 'event' thread for input, just current state
(are you cool with me asking more questions? i don't wanna bother if you're busy!)
Ask away, I may not be able to answer immediately but I check in on this channel as do others.
thanks, holmes
https://github.com/the2bears/DS3 is fairly complete as a playable game, while https://github.com/the2bears/the-iron-council is a work in progress that hasn't seen enough love this last year
with netrunner, there are many times where we're doing something like moving a card from one location to another, or applying some effect to the game state, and an event fires that requires user input (open a prompt, etc). we have an "await" system so both players can interact with the game while we wait for the one to make their decision. how do you handle such things? if at all, lol
I suspect this is more of a generic game dev question and not specific to clojure, but the idea of threading game-state changes is intruiging
I think for something like this, I might consider an event queue. The event fires and is added to the queue. This should be handled asynchronously, outside the main game loop. Then, each 'tick' I would check and consume any events on that queue. This is different than keypressed? and more like the key was pressed and we add that to the event queue.