2D side scroller - How to implement X/Y movement?

I'm currently writing a small 2D, side-scroller-ish kind of game.

I have a simple camera that follows the player around and the physics are ready.

I'm using 32x32 tiles that build out the world, they are all stored in a 2D array, something along this:

[ 0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 1,
1, 1, 1, 1  ]


The 1s are land and 0s are air.

Now the world is dynamic and I want it to be quite large (1 big world) around 1000x800 tiles total.

My biggest issue atm is how to implement the "scrolling effect". Also keep in mind that the player can go in any direction (up/right/left/right).

Thanks

• Are you trying to implement a camera that follows the player? What frameworks are you using to make your game? – doppelgreener Mar 17 '12 at 0:35
• @JonathanHobbs - I'm using Starling and Box2D and already implemented physics, movement, a bound world and a camera that follows the player. I want to add tiles in the mix and to manage a large world without harming performance. – Ron Mar 17 '12 at 0:42
• @Ron If you already have a camera, find which tiles intersect the camera's bounds and draw only those tiles. This is just a matter of finding the minimum and maximum X and Y tile coordinates on the camera's edges and doing a double for loop on your tiles within those bounds. – David Gouveia Mar 17 '12 at 0:51
• @JonathanHobbs I have already found out what tiles I need to draw - I don't want to redraw all my tiles all the time that drops the FPS dramatically. – Ron Mar 17 '12 at 0:59
• Most games redraw everything (that is visible) every frame; avoiding it severely constrains the sort of animations you can do. I think you should be looking into optimizing your tile drawing. If you are doing anything that loops over every tile (as opposed to every visible tile, determined based on coordinates as David Gouveia described) then you need to fix that. – Kevin Reid Mar 17 '12 at 1:51

Handling large worlds requires two things.

First, you want to break your world into a grid of macro cells. Think of the tiles you are using for the world, but on a bigger level. Each cell might have 32x32, 64x64, or even 128x128 tiles in it. The advantages of this approach are that memory accesses will be quicker, it's easier to figure out which in-world objects are close to the player and hence should be active or inactive, and you can page and unpage the cells for on-deman loading of game world content.

The second problem to deal with is how you deal with you world coordinates. For large enough game worlds, a floating point number loses too much accuracy. When objects are near the frites of the world this inaccuracy can result in very noticeable glitches. Fixes include switching to doubles, using two sets of position vectors (an integer vector to denote cell or tile and a float to denote position in the cell/tile). Keep in mind that for the latter approach you will need to convert into float vectors for physics and graphics; when doing so, convert to positions relative to the camera and not the world origin, so that there are never any inaccuracies in the players view.

Complementary to both of those is the idea of just sleeping/disabling all game objects far away from the camera. If the player can't see something, there's no reason to do it. That allows you to potentially unload whole cells from memory ( useful if you have a lot of game data per cell and want to support memory-constrained mobile or console devices ), and it means that you will never have to deal with float inaccuracy and can simply use camera- relative floats for physics and graphics always.

• This seems to produce the best results so far using Starling. Steady 60 FPS when I break down the world into blocks of 32x32 tiles. – Ron Mar 17 '12 at 23:48
• BTW it seems that I have some FPS spikes when I remove unneeded macro cells and draw new ones in. Do you might have any pointers online regarding this technique? – Ron Mar 20 '12 at 0:22
• By "loading new ones in" do you mean reading data of disk into memory? If so, you want to do that asynchronously (using async file I/O or threads), and make the range at which you start loading data large enough that a moving player won't be able to reach an unloaded cell before it loads off disk. – Sean Middleditch Mar 20 '12 at 4:53
  if player.x > (screen.width-300) or player.x < 300:
everything.x -= player.dx
if(player.y > (screen.height-300) or player.y < 300:
everything.y -= player.dx


By player.dx and dy, I mean the player's x and y velocities. By everything, I mean every object on the screen, including the player (because you both add and subtract the player's change in coordinates, he will not move on the screen during scrolling).

• I really do not recommend scrolling a scene by manually moving every single entity it contains in the opposite direction. That approach scales terribly as the number of entities increases. That might have been okay in the old days of non-hardware accelerated 2D games as there was probably little alternative, but nowadays most 2D APIs are built on top of a 3D layer, so you're much better served by using a view matrix for your camera and letting the GPU take care of the scrolling on the vertex shader automatically. Doing that in XNA for instance is extremely easy (just google XNA 2D camera). – David Gouveia Mar 17 '12 at 21:03