Register | Members | Trouble Logging In? | Downloads | My Webcomic

Top-Down Wall Collision (Actionscript 2.0)

First off, this tutorial is in response to the Top-Down movement tutorial, so make sure you read that before moving on.

Ok, so before I begin I want to say while this code isn't 100% perfect, it is much better than what other tutorials will tell you. This is basically the same code that I used in Hero RPG (this code is actually a little better). Before you add this code you are going to need to add a MovieClip to the main timeline with the instance name of Wall, this is where all the obstacles will the place that the player with have to move around. Here is the code:

Note that this code will be added to the Player.onEnterFrame function that we built in the previous tutorial.

if (_root.Wall.hitTest((this._x-(speed*2)), this._y, true) && Key.isDown(Key.LEFT) || 
	_root.Wall.hitTest((this._x+(speed*2)), this._y, true) && Key.isDown(Key.RIGHT)) {
	speed = speed/2;
	this.dx -= this.dx;
}
if(speed >= 20){
	fix = 2;
}else{
	fix = 4;
}
if (_root.Wall.hitTest(this._x, (this._y-(speed*fix)), true) && Key.isDown(Key.UP) || 
	_root.Wall.hitTest(this._x, (this._y+(speed*fix)), true) && Key.isDown(Key.DOWN)) {
	speed = speed/fix;
	this.dy -= this.dy;
}

The code in action -- arrow keys to move.

Wow, now that isn't very much code now is it! There are really only two parts to it, one of which only controls a small variable that saves the code from a minor bug which I'll explain later. Let's look at the first part:

if (_root.Wall.hitTest((this._x-(speed*2)), this._y, true) && Key.isDown(Key.LEFT) || 
	_root.Wall.hitTest((this._x+(speed*2)), this._y, true) && Key.isDown(Key.RIGHT)) {
	speed = speed/2;
	this.dx -= this.dx;
}

Here we start of by finding out if the player runs into the wall by moving left or right (these two checks can be made in the same if statement because the player can never be moving both left and right at the same time). The (this._x-(speed*2)) part of this tutorial makes a check to see if the player is going to hit the wall (not if it is hitting the wall), we double the speed to basically put the registration point one step ahead of what it will be. Once you find that out, then we cut the speed in half and subtract the dx value by itself (which will be 0), and that stops the player from moving any farther in that direction. Lets look at the next part:

if(speed >= 20){
	fix = 2;
}else{
	fix = 4;
}
if (_root.Wall.hitTest(this._x, (this._y-(speed*fix)), true) && Key.isDown(Key.UP) || 
	_root.Wall.hitTest(this._x, (this._y+(speed*fix)), true) && Key.isDown(Key.DOWN)) {
	speed = speed/fix;
	this.dy -= this.dy;
}

This is the exact same as above in Up and Down movement, expect that we apply a fixed variable to the equation. What this does, is the if(speed >= 20){ asks if player is not touching the walls on the left or right to the player. If it is, then we have to double the fix variable to override the previous equation where flash reduces the speed, and therefore reduces the hitTest registration point. Yes, there are other ways to go about doing this, but this is the way I went about it, meh.

Well that is pretty much it for the collision tutorial, here is the whole movement and collision code in its fullest form:

movePlayer = function () {
	if (!_root.Wall.hitTest(Player._x, Player._y, true)) {
		angle = Player._rotation-90;
		radians = angle*Math.PI/180;
		deltax = Math.cos(radians)/2;
		deltay = Math.sin(radians)/2;
		Player.dx = (deltax*speed);
		Player.dy = (deltay*speed);
	}
};

Player.onEnterFrame = function():Void{
	speed = 20;
	this._x += this.dx;
	this._y += this.dy;
	
	if (Key.isDown(Key.DOWN) && Key.isDown(Key.LEFT)){
		this._rotation = -135;
		movePlayer();
	}else if (Key.isDown(Key.DOWN) && Key.isDown(Key.RIGHT)){
		this._rotation = 135;
		movePlayer();
	}else if(Key.isDown(Key.UP) && Key.isDown(Key.RIGHT)){
		this._rotation = 45;
		movePlayer();
	}else if (Key.isDown(Key.UP) && Key.isDown(Key.LEFT)){
		this._rotation = -45;
		movePlayer();
	}else if (Key.isDown(Key.RIGHT)){
		this._rotation = 90;
		movePlayer();
	}else if (Key.isDown(Key.LEFT)){
		this._rotation = -90;
		movePlayer();
	}else if (Key.isDown(Key.UP)){
		this._rotation = 0;
		movePlayer();
	}else if (Key.isDown(Key.DOWN)){
		this._rotation = 180;
		movePlayer();
	}else if (!Key.isDown(Key.DOWN) && !Key.isDown(Key.RIGHT)
			&& !Key.isDown(Key.LEFT) && !Key.isDown(Key.UP)){
		this.dx = 0;
		this.dy = 0;
	}
    
    //Wall Collision
    
    if (_root.Wall.hitTest((this._x-(speed*2)), this._y, true) && Key.isDown(Key.LEFT) || 
        _root.Wall.hitTest((this._x+(speed*2)), this._y, true) && Key.isDown(Key.RIGHT)) {
        speed = speed/2;
        this.dx -= this.dx;
    }
    if(speed >= 20){
        fix = 2;
    }else{
        fix = 4;
    }
    if (_root.Wall.hitTest(this._x, (this._y-(speed*fix)), true) && Key.isDown(Key.UP) || 
        _root.Wall.hitTest(this._x, (this._y+(speed*fix)), true) && Key.isDown(Key.DOWN)) {
        speed = speed/fix;
        this.dy -= this.dy;
    }
}

Download the Source file: movement2.fla.zip
Comments

by Michael Neumann
November 11, 2008