Moving many things vs. moving the camera (and moving the things as well, but less)

I spend a great number of hours thinking about efficiency. When google maps told me that my preferred route to work was a minute shorter than the two other alternatives i considered - cutting my journey from a frankly unmanageable 10 minute walk to a delightful 9 minute walk - i felt absolutely elated.

Now I have a complicated question: I have a part of my game in which you are looking out into space at various planets, stars, and levels that you can select to access them. They scroll at different rates to give the illusion of depth. Originally, they all moved (at different rates) as the player scrolled and the camera stayed still. However, britzl or somebody told me it would be more efficient to move the camera rather than moving all the objects. So, I painstakingly programmed a moving camera. Then, in order to keep the parralax scrolling effect, I re-programmed every object so that as well as moving the camera, each individual object would also move a little bit. So, in the end, the camera moves AND the objects move (although not as much as they did before).

My question is: if (almost) everything is going to move a little bit anyway, does it really make things easier to program a moving camera?

Also, what is the best way to tell all the objects the current location of the camera, in order to move each of them at a slightly different pace? At the moment I use a global variable.

You could just use a perspective camera . . .

Otherwise, I would probably use a lua module to communicate the camera position—it’s just as convenient as a global variable but easier to keep track of and won’t cause name collisions. If your parallax things will be moving around more or less constantly you could just have them grab the camera pos from the module on update. Or you could use a subscription system where each object gives its URL to the module, which stores them all in a table and messages each of them when the camera moves. Just remember to remove each object from the table when it is deleted or deactivated.

Also I would put the parallax code in one script with a script property for its “depth” value, so you don’t have to duplicate any code, just drop the script component on and set the depth.

Is thinking about efficiency for many hours efficient? :stuck_out_tongue:

I did an Angry Birds clone as an example a while back and I decided that I wanted a parallax effect for the background layers (hills, trees, clouds etc) of the game. The game uses a camera to follow the thrown bird or when the player pans around the level, and I had to take the camera into account when the parallax effect was applied.

What I ended up doing was to create a script that I could attach to anything where the parallax effect should be applied. The script directly reads the camera position (ie go.get_position(“camera”)) and updates the game object’s position every update to create the parallax effect. I use the z-value of the object to determine how much to offset the game objects position, based on how far the camera has moved from it’s initial position:

3 Likes

In terms of Defold and simplicity, I think the best you can do is define a few depths, each leading to different movement speeds in a parallax scenario. Make a game object for each depth, child everything at a particular depth under that respective game object, and move that parent through go.animate. What happens in the engine is that a few game objects are animated (quite fast) and the remaining game objects have their transforms updated based on those (really fast).

The moving camera is only a win if everything else stands still.

To go even faster, you would need to offload the work to the GPU through custom shaders. It’s not too tricky once you get the hang of it, easiest would probably be to use a shader constant which defined parallax offset and add it in the vertex shader.

5 Likes

I have noticed that things quickly tend to jitter or move choppy if I move the camera instead of the positions of objects. One way of fixing that is to change the shaders to use highp positions instead of mediump, but highp is of course more expensive than mediump.

This may not be a problem for your game, but it could. So it adds a point in the moving many game objects way.

4 Likes

I use lerping and so jittering is not a problem @Mattias_Hedberg . It’s a good system. What are you using to move the camera? go.set_position or animate?

@britzl what is the benefit of moving the camera as well as moving the objects?

Imagine a really long map that the player navigate by dragging when he does we move the camera, everything on the map i static but it is built up from different sprites and spine animations. The sprites doesn’t move at all but the spines have some idle animations.

The issue is that the further along the map you go (the further from the world origin) the less floating point precision you get. You will see that sprites, even though they are not moving, start to jitter and jumping around, the spine animations will start to do the same even if you are not moving the camera (but are far from the world origin). So to fix it we can use a higher precision on our position values. Or move the world.

Well, for me it makes sense that you use a camera component to move around in the game world. It’s just so much easier to only have to keep track of the camera and move that instead of having to move a ton of different game objects (yes, they could be parented to a main go, but still).

The parallax effect on the other hand is just a visual thing totally unrelated to the choice of using a camera and to get that to work I still need to move the different layers of the parallax effect.

We should also add that these different methods of moving things really only apply to non-interactive background stuff. Moving a game world with platforms etc is often problematic. If you have dynamic physics it’s basically impossible, unless you deal with it with custom code tightly integrated into the pysics engine.

Good point!

Thanks for everybody’s help.

In my specific case, the scene is small enough (it basically goes from 0 to 1200 pixels on the Y axis, and only -300 to 300 on the X) and there are not many objects (124 sprites, some text, and some particles) so I think I’m going to forget about the camera movement, which is completely unnecessary in my case.

thanks everyone!