Tilebased games in Flash 5 - Part 4


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,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]] ];
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:
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 120x120 tiles, but our visible area is just 10x10 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] );

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)] );
      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)) {
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.

(C) OutsideOfSociety 2002.