My game is a top down 2D shmup programmed in a functional style. I'm struggling with abstracting the code that is responsible for animating the projectiles. There are many types of guns with many types of projectiles. Here are a few that are very different:

  1. A standard gun that shoots a bullet that travels a distance over time.
  2. A laser that shoots a line that goes from start to end in an instant.
    • This is different from the standard gun projectile because its projectile doesn't travel over time. It's drawn as a line. Unlike the standard gun, the laser beam animation should last after the projectile hits something.
  3. A psychic shockwave that forms a circular blast wave around your body and damages anything in range. The size of the circle is variable.
    • This is different from the standard gun projectile because its size is variable and circular. Also, it doesn't move. I'm struggling on how I can use a sprite sheet for this. It seems like the best way might be to draw a circle on the screen. All the other projectiles are sprites.
    • This is different from the laser because it's a circular shape rather than a line.

If this were object oriented, the path I'd take is straight-forward: I'd create an Animation class that is responsible for animating itself. The client code would have no idea how the animation occurs, it would just pass in the necessary objects in order to get it done.

But I'm not sure how to do something like this in a functional style. Right now I represent everything as data. A projectile contains animation data like so:

projectile: {
  type: "laser"
  animation: ...

But what feels very wrong is I have to have one switch to create this projectile, and then in my rendering code, I have to have another switch to decide how to use the data to animate it. EG:

if projectile.type is "standard gun"
if projectile.type is "laser"
if projectile.type is "psychic shockwave"

This doesn't seem very abstract to me. What's a better way to code this while still being functional about it?

  • 1
    I'm curious about the functional style you're using here, the common way of doing anything like games in a highly functional style is to have a stream of game and player states or a stream of game and player state changing functions that are GameAndPlayerState->GameAndOrPlayerState. I suspect you are using neither approach... Have you looked at Functional Reactive Programming much or at all? It's another common way of abstracting the componentry of games apart per functional style. Mar 3 '14 at 23:14
  • If this is something you're doing for kicks and could toss it on Github, I'd be curious to take a look. I try to do my own JavaScript as FP style as I can as well. If you want to talk about this more hop in the P.SE chat at chat.stackexchange.com/rooms/21/the-whiteboard Mar 4 '14 at 16:04
  • "If this were object oriented, the path I'd take is straight-forward: I'd create an Animation class that is responsible for animating itself." There's nothing un-functional about using objects. That aside, what exactly does the animation field of your projectile records contain?
    – Doval
    Mar 15 '14 at 23:40

I think you need to invert your dependencies here - those different animation types can be written as standalone functions that given a location, render an animation in that location (or returns an animation-renderer that will execute at that location that you may execute later).

Once you have implemented these rendering functions, what you need to do is have them passed down through the layers. I would put them into your players state such that they have an active gun, and everytime they switch guns, you get a new player state with the new shooting renderer, that renderer can be handed to whatever needs it when they try and shoot.

  • I could think of more functional approaches to some of these things such as using FRP style observer-driven behaviours for the gun switching, but not knowing more about your overall architecture I can only speculate about such things. Also I don't know your language, so I'm not certain what available features are easy vs hard. If possible I would use a type-class like behaviour here. That would invariably mean you're in Haskell, alternatively in a static language I might use an interfaces approach, if in a dynamic language neither of these things would be valuable. Mar 3 '14 at 23:08
  • I'm using javascript + "discipline" to code it in a functional style. I've also been trying to keep my data and behavior completely separate from each other, and I feel like the player state having-a function would be mixing the two together. My rule is somewhat arbitrary, but a nice benefit is I can easily serialize the state whenever I want to save it or have another programming language send it over the wire. That said, your answer is an easy way to accomplish the result I'm looking for. But, is there a way to do it while keeping behavior out of my state? Mar 4 '14 at 1:14
  • It also seems to be against the design of the Entity Component System design pattern. That said... If you think I should still just put the function in my state, I'll trust you on this. Mar 4 '14 at 1:17
  • 1
    You just have to put it somewhere consistently accessible to be doled to the execute-rendering code. It doesn't have to be in player or game state. Remember functional style does have a focus on attention to data rather than procedures as you're aware judging by your approach- but one of the parts of that is treating functions like data. That means handing them around as variables. @tieTYT Mar 4 '14 at 1:51

You could provide a function which supplies the path of the projectile given a time input and origin, and another which accepts the coordinates of the projectile and performs rendering.

  • 2
    What's a functor? Are you using the "Function Object" meaning of the word? Mar 3 '14 at 22:20
  • 1
    I think you are perhaps inferring the meaning of functor from context and getting it wrong. I believe you mean to say "function" (as in closure) there, which is not synonymous with functor. Mar 3 '14 at 23:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.