Parallax Paralysis

Yeah, there’s nothing particularly paralytic about the parallax effects I’ve been implementing in Paper Zeppelin. I just like alliteration when it comes to post titles. Call it an affect. Right then, so I’ve been spending some time putting together the last few bits of the port and I’ve finally (finally!) gotten to the part where I can start adding features again. It’s pretty great.

The big thing that I’ve been working on is getting the engine to have features to make Paper Zeppelin actually pretty. The more things that are built into the engine means that there will be less (or at least easier) things to actually do to make the game look nice. One of the main features is to get the backgrounds to look like something that doesn’t look like ass.

I came to a couple of conclusions pretty quickly regarding the backgrounds. Let’s discuss them in list form, but also in no particular order.

1: I realized that if there were any real number of background objects then I would quickly run out of available informational bandwidth. Don’t worry, I’ll translate what I mean. The total map for Paper Zeppelin is only 25 tiles tall, and everything takes up a single tile to summon. Now there are objects that are larger than a single tile, but on the level data itself it’s all just a single character.

That means though, that if I start adding a seriously robust number of background objects (of which there will be) then I might run out of space. Or I’ll need to design the backgrounds around where the enemies and everything else happen to spawn. That’s not great.

Now if I had my druthers, the level data would all be divided into layers so this wouldn’t be a problem at all. The next game engine I build will have layers by design. So for Paper Zeppelin I realized that I should construct a secondary set of level data that is only background objects. So that’s what I did. Which leads me to..

2: I wanted the background data to be object agnostic. Let’s start translating again. So for the backgrounds there will be different things that will spawn based on what level it is, but they will use the same character to spawn them. For example, we’re using ‘C’ as the symbol for Clouds because I’m clever like that. In one level the clouds might be wispy, but the art might be fluffy clouds in another. But they both us the same character in the editor. And since I didn’t have the ability to really pass a lot of data along via a single character that means that…

3: The background object behaviors needed to be based on something that was consistent across all levels. Early thinking about it made me think that maybe they should all just be the same speed and basically I would create a backdrop as I went. That would be fine, but would have the effect of making a background that wasn’t very dynamic.

What I came up with was the idea of a virtual horizon. Let’s talk about the concept of Parallax for a moment. Let’s use an analogy. Parallax is the effect where things that are further away have less apparent motion than things that are closer, even if the scale of said objects is the same relative to the viewer. So if you drive past a fence post and there is a mountain in the distance they may both be the same height, but that fence post rushed by at (almost) the same speed you are going while the mountain may have seemed to move hardly at all (if at all).

It’s the kind of thing that you internalize without thinking about. Although you can actually use that effect to calculate the distance to an object based on how large the object is. That also means that the parallax effect will make the game made out of paper and miscellaneous mixed media look a lot more “real.”

Which means that I used an equation to give things a speed based on how close they are to the middle of the screen and my virtual horizon. It worked out fine with one minor (major) caveat…

4: The draw function is bullshit. I’ll translate. The draw function as written in Paper Zeppelin is complete bullshit. There is a short list of variables to draw things on the screen. Like there’s a size, and a rotation and a color and a position and all of that. There is also an order that they are supposed to be drawn in. Generally speaking this doesn’t matter because things do not overlap in the main engine and if they do the most recently spawned thing always had priority if they were in the same list.

Let’s play with an illustration to, well, illustrate? Let’s take a list of sprites and call them duck, chicken, and goose. When we call the draw commend for this list the system will draw them from first in the list to last. So duck, then chicken and then goose, which means that the goose will be in front. Now let’s try that again and dump them into the parallax draw function so that the duck is at the top of the screen, the chicken is sort of in the middle and the goose is at the horizon. Well, if we draw them they will still come out the same way, and the important thing re:bullshit is that the draw function does not care what I tells it.

So obviously a workaround was in order. I found that if I dumped things into the front of the list it worked the way that it was supposed to by giving draw priority to newest object, which means that when it actually goes on the screen it will be behind the things drawn afterwards. That more or less worked great. Then I added the additional complication of moving from horizon towards the edges of the screen as part of the loading loop. All of this is a way of saying that from a technical perspective the parallax effect in Paper Zeppelin works. Well except for the fact that…

5: It looks like ass. I had added a function that scaled objects based on their row and apparent distance to the horizon, which didn’t really look like I wanted it to and gave it the effect of making mountains and whatnot float in the sky. I hadn’t really considered that maybe if you are looking at the actual horizon you need to have, like, the ground. But if I have ground I can’t automatically scale things.

Going back to Number 2, that just means that if there is a “C” value, I need to load a different cloud object based on row. I could probably add the row number to the name of the image to automate that entire thing, but it’s the next thing I need to do to make the parallax work the way that it is supposed to.


Due to some unforeseen and wildly unexpected circumstances, I think that I have lost the card file for Dungeon Quest: Adventure. Let’s say right up front – that is unfortunate. Although not all is lost, since I have an entire card set on TableTopia. What’s that? You haven’t played the demo yet? Off you go.

I’ve decided that I’m going to treat this as an opportunity. First of all it gives me the ability to reformat all of the card text, which is a little all over the place. It also allows me to refort the actual card data itself, and add the features like rarity which were not part of the original file.

Finally, I think I am actually going to take a crack at switching the theme. I previously spoke about theme and laid out the reasons for the theme that I had. But the more that I think about it, I think that what I really want is a hybrid sci-fi fantasy theme. Like I want mech pilots that cast magic and use flaming plasma swords while flying to different planets to discover ancient artifacts of power and upgrade their computers.

What I’m not going to do is add anything that makes the game crunchier. It doesn’t need that in my estimation. But having a theme that allows for being goofy and serious at the same time seems like something that I would very much like to write content for. So since I need to rebuild the card file I’ll modify the templates so that I can summon either the hybrid or the straight fantasy version. Then we’ll let the people decide. Democratic like. Or I’ll make the all. Autocratic like. Stay tuned.


I wonder if anybody will at some point calculate the distance to my virtual horizon based on the mountains that I put back there? I know the answer to that question already. Yes, “somebody” will calculate that. Of course I will.

Leave a Reply

Your email address will not be published. Required fields are marked *