Godsend Programming #7: Moving Backgrounds

One of the things Juan (my background artist teammate) really pushed for is animated backgrounds. This was one of the trickier subject when it came to memory consumption. After all, background objects tend to be quite huge. As an initial attempt, he tried to do a single animation sprite sheet for each background, but we quickly found that to be infeasible, as the spritesheets would be absolutely massive. Our second approach was to move things programmatically instead. After all, the animations we were after could be classified into two areas: bobbing and flowing horizontally through the screen.

There were many areas where such animation types were needed before, and the artists chose to implement them as sprite animation, mainly due to time constraints from the programmers. To be honest, I think it makes us look slightly bad, because sprite animation of bobbing takes up a lot of memory and can definitely be done via programmatic animation. However, being pressed by other tasks deemed as more crucial for the project, we went with it (most of them got taken out anyway).

So coming around to moving backgrounds, bobbing and flowing in spritesheets became unacceptable. And so I ended up creating two classes to represent the behaviour: CGCObjBobbingBackground and CGCObjFlowingBackground. Here’s a brief overview of each class:

Bobbing_Ground

Flowing_Ground

Unfortunately, this meant that you couldn’t have an object that bobs and flows at the same time, and that the effects were limited to background objects. However, that’s all we needed for the game so the limitations did not cause any problems. If I were to do it again though, I would have definitely used composition rather than inheritance and have a bobbing and flowing classes as components which you initialise with the object you want to bob/flow and they’d apply their respective effects at each frame. This is way more re-usable, as you can apply a combo of these effects to anything you want. You might notice from the update functions that it sets the sprite positions rather than using the physics objects:

Bobbing_Update

This is desirable for backgrounds, but would need to be changed for other types of objects. Backgrounds don’t have a physics shape, but others do, so if the physics shape stayed where it is, and only the sprite moved, it would look glitchy. That’s one more consideration in the list then.

Finally, since we had 6 different backgrounds with different effects in the game, I realised that I would need to load them dynamically, as only the data is different – behaviour is essentially the same. So I exposed the bobbing/flow speed, direction and range, as well as the object position and put them all to be read from a text file:

BGSpecification

The structure of the text file is obviously a mess. However, this functionality was done in one day over 10 or so hours, on the Tuesday of the Beta sprint, so it’s what you’d call adding features to a feature-complete game – not much time to fuss over the quality of the solution if you want the feature to be in the game. And having it in did pay off, as the game looks so much better when stuff moves in the background.

If I did it again

For the PS4 project/if I did it again, I think we’d need to consider using simple XML or JSON to structure the files though, as that would make it more manageable, more easily tweakable and more extendable in the future. If we’re doing a data-driven object type like this, we want to be able to manage the data and how it changes over 8 months. This solution is only acceptable given the time frame to do it and the fact that it was done at the end of the production cycle in my opinion.

To wrap up the moving backgrounds, here’s actually how the text file gets processed:

Mov_BGParsing

There’s nothing special about it, except for the assumption that all data is in the correct order in the text file. Since the file only got edited by me and only done once, there’s little harm in it. However, if we wanted to add a new realm, and add dynamic backgrounds to that realm after a good chunk of time, it might as well become problematic. At the very least, it could definitely make better use of assertions for the data that it reads in and it should do some validation before going on and using it.

Related files

GCObjBobbingBackground.h – https://drive.google.com/open?id=0B_BnvnFZLH7mcVJaN0NiMFBVejg

GCObjBobbingBackground.cpp – https://drive.google.com/open?id=0B_BnvnFZLH7mdEhvS2xDVWtoYWM

GCObjFlowingBackground.h – https://drive.google.com/open?id=0B_BnvnFZLH7mWWtzZnpNTTIxSms

GCObjFlowingBackground.cpp – https://drive.google.com/open?id=0B_BnvnFZLH7mV3hjWjRQam4tV1U

GCGameLayerPlatformer.cpp – https://drive.google.com/open?id=0B_BnvnFZLH7mU3pDRkVpZmdycVU