How To Do The Scrolling Effect

Every game does it from Super Mario to Sonic the Hedgehog, but when it comes to a good game design book they all come short; What am I talking about? Scrolling, because seriously! who is planning on making a space invaders clone? or a complex 3D project?

Posted by on - Basic Client Side Coding

One of the most frustrating experiences I had learning game design was finding a good book that didn't teach how to make another pong clone or space invaders clone. When people think of a 2D video game they think of Super Mario Bros or Sonic the Hedgehog. Of all the books I've seen out there and of all the books in my collection, not a single one talked about the one subject seen in almost every modern video game; the scrolling effect. The scrolling effect is what allows a character to walk on a portion of a level and move as if a camera was following. The camera is used to reveal the rest of the level as you move. So why would most game design books leave out such a fundamental subject? Maybe they think who ever is reading the book is not capable of doing something as complex as scrolling and yet it is such an easy thing to implement.

The first thing you need to do is define a class that has the following properties: an x and y axis, used to define it's location relative to the world. You'll need a reference to the main playable character (we need access to the playable characters x and y values, as well as it's width and height).This class which we'll call viewport or camera, should also define the size of the overall level in pixels, it should define the width and height of the screen: in our case 320x240. There should be a structure to hold the playable character's previous coordinates; we use this to determine which direction the playable character is going.

``````	public function ViewportManager(source:Core):void {

core = source;
playable_dolphin = core.playable_dolphin;

x = 0; y = 0;
width = 320; height = 240;

WorldWidth = 0; WorldHeight = 0;
previous = new Point(0, 0);

return;
}``````

The next thing our viewport or camera should have is a set of functions that allow the camera or viewport to move. In the case with Agartha, the camera follows the playable character as he swims over the center of the screen. There are two important points that trigger camera movement, one on the x-axis and another on the y-axis:

``````	public function xUpdate():void {

var Center:int = x+(width/2);

if (playable_dolphin.x < previous.x) {

if ((x > 0) and (playable_dolphin.x+playable_dolphin.width <= Center))
x+= (playable_dolphin.x-previous.x);

}

else if (playable_dolphin.x > previous.x) {

if ((x+width < WorldWidth) and (playable_dolphin.x >= Center))
x+= (playable_dolphin.x-previous.x);
}

if (x < 0) x = 0;
else if (x+width > WorldWidth)
x = WorldWidth-width;

previous.x = playable_dolphin.x;
return;
}``````

The proceeding code is a bit of an ugly beast but I'll explain; The xUpdate method takes the coordinates of the camera: x and determines where the center of the screen is located: (width/2). An 'If' statement determines if the camera is greater than 0 (we don't want it to travel off our world map). The If statement then determines if the players location (x) plus it's overall width, is not greater than the center of the screen. If the playable dolphin is traveling left, we want it's location + width to trigger camera movement if it hits the center of the viewport (our screen). A yUpdate method will do the same with the y axis, replacing all the x's in the xUpdate method with y's and replacing all the width's with heights.

``````	public function Update():void {

xUpdate();
yUpdate();

return;
}``````

Within our viewport class is an Update method that takes our xUpdate and yUpdate methods (used to move the camera if the playable character travels over the screens center). The Update method should be located in the main game event loop as it is used to move our camera.

Every object in your game should have coordinates relative to your level, so if your level is 2000 in width and 2000 in height, your characters should be located anywhere from 0-2000 for x and 0-2000 for y. The next function takes the coordinates of your character and objects throughout the level and translates them relative to the screen. This following method should be located before the drawing routine in your playable character, your tiles (used to build the level) and enemies. It translates all your on screen objects global coordinates to coordinates relative to the screen.

``````	public function TranslateToViewport(current:Rectangle):Rectangle {

return (new Rectangle(current.x-x, current.y-y,
current.width, current.height));
}``````

TranslateToViewport takes one parameter; your characters rectangle (containing the x and y coordinates and the width and height). In this example current equals your playable character or enemy object, it's coordinates are subtracted from the coordinates of the camera, the result are coordinates friendly to the display. The translation function should be located within your viewport class (or camera class, depending on what you want to call it).

Basically the camera works like this; it is an object like anything else thats on screen; such as the main character or enemies. The camera will need something to trigger it's movement, in the case of my game Agartha, I use the center of the screen, but you can theoretically use anything you like to trigger movement, (or you can make it autoscroll as found in the game Lifeforce for the NES). The second most important method is the one that takes the coordinates of your objects and translates them relative to the screen, this is accomplished by subtracting your cameras coordinates from your objects.

When I first devised how to do scrolling I had no resources available, I had to figure it our from scratch. The proceeding code is my masterpiece, sad to say it took years for me to devise but when I did, I couldn't believe how simple it was to do. Most books on game design don't teach this technique, but it is a fundamental aspect required for almost all 2D games.