independent scrolling tutorial

a regular member here asked me help him with some scrolling issues since he noticed that I somehow fixed something most scrolling mechanics have in common:
they canīt update independently meaning if either booth axis need to be updated and or booth with different offset values the engine wont update propper since itīs often programmed in a linear manner wich only exepts linear speeds/ offsets. This idea is part of my "Tank Move" project wich requires something like this as the map can be navigated in realtime without movement delays.

My method wich I will explain in the following and wich is posted with source code and authoring files has some special features:
- scrolling wich updates only the tiles that really need to be updated. Not the whole screen. Though map movement requires only displacing 1 container movie
- gap control, if the offset is greater then 1 row (most engines) it updates thus more rows (if needed on booth axis)
- using only that many tiles as visible on the screen. No target swapping or _visible=true/false hack. Makes it even faster and less memory intense as other methods.

I assume that the readers are already familar with basic scrolling mechanics. For those that arent:
Basicly the aim is to save CPU resources by updating a grid- layout of graphics (called tiles) only at those spots where the camera is moved to. Movement is usually done with just 1 container instead of using a loop for all graphics aka tiles.

so first a demo:
http://www.renderhjs.net/bbs/flashki...ll/demo_03.swf
and here a performance demo:
http://www.renderhjs.net/bbs/flashki...ormance_03.swf
(this bigger screen demo manages 368 screen tiles (the ones that are visible!), the ones a map can contain are almost unlimited)

the red fading cells (in the first demo) are the ones that got updated recently, move the mouse to scroll the map and see wich cells are updated. If you move the mouse instantly youīd see that the whole screen or a big area of the screen is updated. The less tiles need to be updated the faster it runs, though if you move instantly to a new area you wont notice that much the delay since visually speaking there is anyway a flash.

Iīll let first these pictures explain some basics and the concept my method:

as mentioned in the last part here is smal video how we progress if booth axis change

here is a demo where the last fix isnīt applied:
http://www.renderhjs.net/bbs/flashki...rong_shift.swf
as you can see some lines are off wich we dont want and thus need that final fix


so how did I translate this into AS?
first some variables, array and object declarations- the ones that will be used on this level/ class, some additional explainations:
- matrix_x[]/matrix_x[] = are the rulers as I described them earlier. They contain the sequential numbers of the first lopps that we use init function later on.

PHP Code:
var screen = {w:320,h:200};//screen dimensions
var tile = {w:32,h:32};//tile dimensions

var matrix_x = new Array();//described before as ruler-x
var matrix_y= new Array();

var 
map = new Array();
map = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        [
1,0,0,0,1,0,1,1,1,1,0,1,1,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,1],
        [
1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1],
        [
1,0,0,1,1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,1,1,0,1,1,1],
        [
1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1],
        [
1,0,1,1,1,0,0,0,1,0,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1],
        [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        
        [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        [
1,0,0,0,1,0,1,1,1,1,0,1,1,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,1],
        [
1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1],
        [
1,0,0,1,1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,1,1,0,1,1,1],
        [
1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1],
        [
1,0,1,1,1,0,0,0,1,0,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1],
        [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]];

var 
last_cx 0;//last corner X
var last_cy 0;

var 
tiles_x 0;//x-tiles amount that are used for the screen width
var tiles_y 0
now some simple functions:

- getZ: function to manage the unique IDīs - this can be later used as well for the z-Ordering including sub-layer depth manegement. In this sample code a map can only be max. 100 cells width otherwise the values it returns are no unique ones anymore
- update_cell(): core function that updates a single tile. Add layers or whater complex structure here to give your tiles complexity
- init(): does what it stands for inite all basic elements like creating the tiles that are pushed later on the screen. tiles_x stand for the amount of tiles that are needed on the x-axis. The rulers-> now known as matrix_y and matrix_x are filled as well here with the i and j loop numbers so in each case 0,1,2,3,...
the init(); functions is called at the end and so does it all start. If you compile the current code it should already display the map - but scrolling doesnīt work yet.
PHP Code:
function getZ(x,y){//get unique depth ID
    
var val = (y*100)+x+1;
    return 
val;
}
function 
update_cell(z,x,y){//update single cell...
    
var trgt mc_scene.stage;
    
trgt["t"+z].tex.removeMovieClip();//remove previous item
    
if ( map[y][x] == 0){
        
trgt["t"+z].attachMovie("B","tex",1);
    }else{
        
trgt["t"+z].attachMovie("A","tex",1);
    }
}

function 
init(){//init screen, resets all
    
var trgt mc_scene.stage;//target to dump tiles inside
    
    
tiles_x Math.ceil(screen.tile.w)+1;//amount of tiles on x-axis
    
tiles_y Math.ceil(screen.tile.h)+1;
    
//check if those screen tiles are not more as the map dimensions
    
if (tilesX map[0].lengthtilesX map[0].length;
    if (
tilesY map.lengthtilesY map.length;
    
    
matrix_x = new Array();
    
matrix_y = new Array();
    
    for (var 
i=0;i<tiles_y;i++){
        
matrix_y.push(i);
        for (
j=0;j<tiles_x;j++){
            if (
i==0){
                
matrix_x.push(j);
            }
            var 
getZ(j,i);//unique ID
            
trgt.createEmptyMovieClip("t"+z,z);//create tile
            
            
trgt["t"+z]._x j*tile.w;
            
trgt["t"+z]._y i*tile.h;
            
            
update_cellzji);//z,x,y
        
}
    }
}
init(); 
now comes the difficult part , just kidding first something easy:
PHP Code:
_root.onEnterFrame = function(){
    var 
= (_xmouse-mc_scene._x)*-2.5;
    var 
= (_ymouse-Stage.height/2)*-2.5;
    
scroll_screen(x,y);

a enterFrame event will call a function named scroll_screen with negative values (remember opposite directions of camera/screen). This function will displace the map to the x and y coordinates and based on how much was moved move within that map movieClip the tiles that switch places