Tilebased games in Flash 5 – Part 4

Scrolling…

Ok, the first thing we´re going to change from the previous example-files is that we´re going to use 3-dimensioal arrays instead of 2-dimensioal, to build the map. Earlier we had something like this:

myMap=[ [1,1,1,1,1,1,1,1],
	[1,0,0,0,0,0,0,1],
	[1,0,1,0,0,0,0,1],
	[1,0,0,0,0,1,0,1],
	[1,0,0,0,0,0,0,1],
	[1,1,1,1,1,1,1,1] ];

Now we´re going to to it something like this:

myMap=[ [['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]],
	[['a1',1],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0],['a0',0]] ];

It´s no big deal really, what have changed is that an element that looked like this: ‘1’, have changed into this: [‘a1’,1]. This approach makes it easier to use in flash and makes it a little simpler when doing more complex stuff with many different tiles and properties. The first one:

[->'a1'<-,1]

are going to represent a label in our tile-movieclip, so we can say something like:

gotoAndStop ( map1[i][j][0] );

Just go to and stop at that label(‘a1’).
The second one, the number are going to represent the type of the tile. Maybe 0 is the ones you can walk on, 1 can´t walk on them, 2 can´t walk on them but you can blow them up, 3 can´t walk on them but you can move them if you got the supergloves and so on.

It looks a little more complex but it really isn´t much to it, it´s the same principle.

The most important thing when making a scrolling map: DON´T draw what you can´t see.
If you can´t see it there´s no point in showing it. Just look at 3d-games like quake, they don´t render stuff that´s behind you, do they? Well you don´t know, cause you can´t see them. But they DON´T.

So let´s say we got a big-ass map like 120×120 tiles, but our visible area is just 10×10 tiles. So we just the draw the tiles which we can see. Then if we move up with our character, we simply start adding tiles at the top and removing the ones at the bottom, thus keeping the same amount of tiles on the screen all the time.

When our maps get bigger and bigger, it´s good idea to keep them in external .as-files(just textfiles) and then include them into flash. The flash action-script window can get a little slow if you got giant monster-arrays in it.

Let´s get into it.
First we start with setting up some constants and including our map:

// includes the map array from an external file
#include "map.as"

// how big is our map?
mapW = map1[0].length;
mapH = map1.length;

// the visible area, what we should draw.
visAreaX = 10;
visAreaY = 9;

// the tiles width and height
tileW = 16;
tileH = 16;

// the x and y positions where our map should be positioned on the stage
startX = 100;
startY = 40;

// used later on for the actual scrolling
majorX = 0;
majorY = 0;
scrSpeed = 3;

// attach an empty movieclip from library, inside this we draw our map.
this.attachMovie("empty", "scrClip", 0);
this.scrClip._x = startX;
this.scrClip._y = startY;

I´m not going to explain this further since it´s pretty straigtforward.
Next is our buildMap-function, which should be familiar with if you read the previous tutorials.

// builds the map
function buildMap () {
	for ( i=0; i<(visAreaY); ++i ) {
		for ( j=0; j<(visAreaX+1); ++j ) {
			this.scrClip.attachMovie("tile", "t_"+i+"_"+j, ++d);
			this.scrClip["t_"+i+"_"+j]._x = j*tileW;
			this.scrClip["t_"+i+"_"+j]._y = i*tileH;
			this.scrClip["t_"+i+"_"+j].gotoAndStop ( map1[i][j][0] );
		}
	}
}

buildMap();

The main differences now, is that instead of drawing the entire map, we only draw as far as our visAreaY and visAreaX variables go. We also attaches the tile movieclips inside the ‘scrClip’ which we created in beginning. And we make use of the labels in the map-array. We also don´t keep the i and j variables as local variables, using: var i=0, because we´re going to use them later on in the scroll-function.

Now the scroll-function, we´re just going to make it scroll to the right, just to keep it simple.
Here we go:

// scroll-function
function doScroll (dir) {
  // right
  if ( dir == "right" && j <= mapW ) {
    this.scrClip._x -= scrSpeed;
    majorX += scrSpeed;
    if ( majorX >= tileW ) {
      for ( var lasti=(i-visAreaY); lasti < i; ++lasti ) {
        for ( var lastj=j; lastj < (j+1); ++lastj ) {
          this.scrClip.attachMovie("tile", "t_"+lasti+"_"+lastj, ++d);
          this.scrClip["t_"+lasti+"_"+lastj]._x = lastj*tileW;
          this.scrClip["t_"+lasti+"_"+lastj]._y = lasti*tileH;
          this.scrClip["t_"+lasti+"_"+lastj].gotoAndStop ( map1[lasti][lastj][0] );
          removeMovieClip ( this.scrClip["t_"+lasti+"_"+(lastj-visAreaX-1)] );
        }
      }
      ++j;
      majorX -= tileW;
    }
  }
}

As an argument in this function we expect a direction(dir), it´s just “right” for now, but we probably want more directions in the future.
So if the dir is equal to “right” and we´re not at the end of the map(j <= mapW), then we should scroll:

this.scrClip._x -= scrSpeed;

Just moves scrClip, our “container”-movieclip, where all the tiles are drawn.
We also increment the variable ‘majorX’ with the amount we just moved the scrClip.

Then we check if majorX is more or equal to the tileWidth, if it is then we should add a row of tiles on the right side of our last visible tiles. We should also remove tiles on the left, which are no longer visible. That is accomlished by the two for-loops, which you should recognize by now.
After that we increment ‘j'(our width-loop) and decrement ‘majorX’ with the width of the tile.

So to test this we can simply add an empty movieclip with these clip-parameters:

onClipEvent (enterFrame) {
	if (Key.isDown(Key.RIGHT)) {
		_parent.doScroll("right");
	}
}

Here´s an example(Focus, left and right arrowkeys):

Here you can download a version wich you can scroll right and left.

This works perfectly for jump and run games like Super mario, which only scrolls in one direction. It also works great for labyrint games like Gaunlet(or my bomberman-clone), where you simlpy add the abbility to scroll in all four directions.

But there are of course other ways to scrolling, in Zelda they just scroll one screen at the time, like in this example I made a while back.

Im not going to go through that, but it´s almost easier. The basic idea is that you have two empty movieclips, ‘a’ and ‘b’. If ‘a’ is the active one, the one I can see, then if I move left out of that map, we simply attach ‘b’ one screen to left of ‘a’. We draw the new map in ‘b’, then we move both ‘a’ and ‘b’ to the right(the scrolling), when ‘b’ is in place, we remove ‘a’.
Now if we move up out of that map, we attach ‘a’ one screen over ‘b’, scroll them and remove ‘b’. And on it goes…

Next up, isometric maps. Stay tuned.

Twitter

    Sorry, no Tweets were found.

Categories