The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki
How to implement a camera
This short tutorial will teach you how to implement a camera. A camera is useful when your game world is bigger than the screen and you want to be able to scroll around the world. For example, in most platformers the camera follows the player and as he moves around the world more of it is revealed. Another example is strategy games where you need to control units at different locations of the map, thus the player is now in direct control of the camera as he wants to see different parts of the game world.
First, we need some variables:
// the screen size (the actual resolution of our display or window) int screenWidth = 640; int screenHeight = 480; // the world size int worldWidth = 1000; int worldHeight = 1000; // the camera's position int cameraX = 0; int cameraY = 0;
The method is pretty straightforward. First, we keep the coordinates of every object in the world as world coordinates. This means that if your map is of the size 1000x1000, and you have an object at the lower right corner of the map, then its coordinates could be something like (900, 900).
Second, when you want to draw an object you must first translate its world coordinates to screen coordinates. This is how you do it:
// translating from world coordinates to screen coordinates int x = object.x - cameraX; int y = object.y - cameraY;
If you don't understand why we do this, try drawing it on paper. If we have moved our camera (cameraX and cameraY) down towards the object at (900, 900), eventually the camera coordinates will be large enough so that the translated coordinates of the object (x and y) will be within the size of the screen (screenWidth and screenHeight). To clarify, the object's coordinates (object.x and object.y) are the variables which you change when you want to move the object. It's only when you need to draw the object that you translate the coordinates (e.g. x and y above) and it's the translated coordinates that you then use when you draw the object.
Moving the camera
Moving the camera is easy. We just manipulate cameraX and cameraY so that the camera goes in the direction we want. However, we need to somehow stop the camera when it reaches the boundary of the game world. This is fairly easy:
// making sure the camera stays within the boundary of the game world if (cameraX < 0) cameraX = 0; if (cameraY < 0) cameraY = 0; if (cameraX > worldWidth - screenWidth) cameraX = worldWidth - screenWidth; if (cameraY > worldHeight - screenHeight) cameraY = worldHeight - screenHeight;
If the camera's coordinates are less than zero then we reset them to zero. If the camera's coordinates are bigger than the world's coordinates minus the size of the screen, we reset them to those values. Why do we subtract the size of the screen? Well, the origin in this coordinate system is at the upper left, so it should make sense right? If we don't subtract the screen size we'll move too far down and right.
Making the camera follow the player
This is easy enough! If the camera should follow the player, then the camera's coordinates must somehow depend on the player's coordinates. Thus:
// make the camera follow the player cameraX = player.x - screenWidth / 2; cameraY = player.y - screenHeight / 2;
We update the camera's coordinates to be the player's coordinates minus half of the screen's width and height so that the player is at the center of the screen at all times.
What should happen when we reach the edge of the world? If the player is always at the center of the camera he might never be able to touch the edges of the world. This could be solved in two ways:
- when making sure the camera stays within the limits of the game world, we can just make the boundary larger than the game world so that the player can reach the edges
- when the camera reaches the edge of the world, make it not follow the player anymore so that he can move around freely and then start following him again when he starts to move away from the edges
I leave the implementation details as an excercise to the reader :) I hope that these techniques can come in handy for you! It should be fairly trivial to implement this for tilemaps for example.