I've been working on a Tetris Attack clone in Clojure using Penumbra (a Clojure opengl wrapper in functional style). I've had quite a rough time with code organization, primarily because the physics of the game has a lot of frame-to-frame dependencies and I've been adamant about avoiding mutable state (because what is the point otherwise?). The Penumbra stuff provides frame callbacks, and you can return a state object which will be passed to you on the next frame. But even with that, I've still had some difficulty. I'm trying to implement a little macro language for animations, so that you could write, e.g.,:
and have a block spend 3 frames in the "moving-to" animation, followed by an actual position update on a grid.
We have a state shuffling problem: this 'anim' macro has to maintain frame-to-frame state, and each animation frame also has to accept the gameboard and possibly return a new gameboard, in order to be able to update the position of the block in question. And I'm having trouble wrapping my brain around it. I really don't want to have to explicitly name a 'state' variable everywhere, although a state variable obviously needs to be passed.
This is the first time I've attempted to do something game-like in a Lisp. I've done a small amount of programming language implementations, garbage collectors and so on, in Scheme. I've also done a decent amount of Haskell. A monad would be exactly what I want, and I am capable of designing them in Haskell, but I was sort of disappointed and frustrated when I tried to figure out how to design one in Clojure.
Have you posted your ideas/issues to the Penumbra mailing list? Zach Tellman (Penumbra maintainer) might have some feedback/pointers for you, he's a pretty responsive and helpful guy.
Posting the main Clojure mailing list might bring up some interesting perspectives as well.
No, I haven't attempted to seek outside help at all (I'm not explicitly seeking help here, either, more sharing an experience). It is probably a good idea though!
Hey Lincoln, I'm the guy who made Penumbra. A few thoughts:
1. Frames are not a unit of time. In the :update and :display callbacks you're given both the total elapsed time and elapsed time since the last frame (in seconds); use those to calculate the positions of objects.
2. I think the major confusion you have is what the (anim ...) macro should return. The answer's actually pretty straightforward: a function which takes the current time, and returns the position for that time. That function will be stored in the global state of the application, and sampled every time you draw a frame.
If you want to change an animation, all you need to do is swap out the animation in one of the callbacks. These callbacks don't have to necessarily be in response to user actions; look at how app/periodic-update is used in the Tetris and Asteroids examples.
We have a state shuffling problem: this 'anim' macro has to maintain frame-to-frame state, and each animation frame also has to accept the gameboard and possibly return a new gameboard, in order to be able to update the position of the block in question. And I'm having trouble wrapping my brain around it. I really don't want to have to explicitly name a 'state' variable everywhere, although a state variable obviously needs to be passed.
This is the first time I've attempted to do something game-like in a Lisp. I've done a small amount of programming language implementations, garbage collectors and so on, in Scheme. I've also done a decent amount of Haskell. A monad would be exactly what I want, and I am capable of designing them in Haskell, but I was sort of disappointed and frustrated when I tried to figure out how to design one in Clojure.