collision

Subscribe to collision 5 posts

avatar for skyfish19 skyfish19 2 posts
Flag Post

this is my code. I am total begginer in programming so i do not know, how i can make my character stop when it hits blackBlocks? any help would be great.

package 
{
	
	 import flash.display.MovieClip;
	 import flash.events.*;
	 import flash.display.*;
	 import flashx.textLayout.formats.BlockProgression;
	
	
	  public class Main extends MovieClip 
	  {
		 public var keyboardInput:keys
		 public var HeroSoul = new Soul();
		 public var bG = new bg();
		 public var character:Soul = new Soul();
		 public var BlackBlock = new blackBlock();
		 public var VioletBlock = new violetBlock();
		
		private var speedX:int = 0;
		private var speedY:int = 0;
		private var lastX:Number;
		private var lastY:Number;
		private var speedConstant:int = 5;
		private var friction:Number = 0.95;
		private var heroSpawnX:int = 4;
		private var heroSpawnY:int = 2;
		private var heroX=heroSpawnX
		private var heroY=heroSpawnY
		private var BackX:Number;
		private var BackY:Number;
		
		private var mapWidth = 28;
		private var mapHeight = 24;
		private var tileSide = 50;
        private var totalTiles = mapWidth * mapHeight;
		
		private var level:Array;
		
		public function Main()
		{
			addChild(bG);
			creatingLevel();
			addHero();
			var keyboard_sprite = new Sprite;
			addChild(keyboard_sprite);
			keyboardInput = new keys(keyboard_sprite);
			
			stage.addEventListener(Event.ENTER_FRAME, gameloop);

		}
		
		public function creatingLevel()
		{
			 
			level = [
					 [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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
					 [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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]
					 ]
					 
				
				
				for (var i:int=0; i<mapHeight; i++)
					{
						 for (var u:int=0; u<mapWidth; u++)
						 {
							if(level[i][u] == 1)
							 {
								VioletBlock = new violetBlock();
								VioletBlock.x=tileSide*u;
						  		VioletBlock.y=tileSide*i;
								bG.addChild(VioletBlock);
							 }
							if(level[i][u] == 0)
							{
								BlackBlock = new blackBlock();
								BlackBlock.x=tileSide*u;
						  		BlackBlock.y=tileSide*i;
								bG.addChild(BlackBlock);
							}
						  
						
						 }
					}
					
		}
		
		public function addHero()
		{
			
			addChild(character)
			character.x=heroSpawnX * tileSide
			character.y=heroSpawnY * tileSide
			
			
		}
		
		
		public function gameloop(e:Event)
		{
			
			
					if (keyboardInput.is_left())
					{
						speedX -= speedConstant;
						if (character.hitTestObject(VioletBlock))
							{
								trace("hit");
							}
						
					}
					if (keyboardInput.is_down())
					{
						speedY += speedConstant;
						if (character.hitTestObject(VioletBlock))
							{
								trace("hit");
							}
						
					}
					if (keyboardInput.is_right())
					{
						speedX += speedConstant;
						if (character.hitTestObject(VioletBlock))
							{
								trace("hit");
							}
						
					}
					if (keyboardInput.is_up())
					{
						speedY -= speedConstant;
						if (character.hitTestObject(VioletBlock))
							{
								trace("hit");
							}
						
					}
					
					speedX *= friction;
					speedY *= friction;
					
				
			bG.x -= speedX;
			bG.y -= speedY;
			
						
					
			
			speedX = lastX;
			speedY = lastY;
		}
		
		
	
	}
	
}
 
avatar for Khronosis Khronosis 130 posts
Flag Post

For starters, you’ll need an array to store all the instances of the violetBlock object.
Right now, you’re doing:

VioletBlock = new violetBlock();
and
if (character.hitTestObject(VioletBlock))
{
trace(“hit”);
}

The problem with this is that VioletBlock represents only the most recently created instance of violetBlock.
As you create each new instance of violetBlock, you’ll need to store the current value of VioletBlock into some array (“blockArray”, for example), then iterate through the array, checking for a collision between the player and each instance of violetBlock.

This will change your code to:

VioletBlock = new violetBlock();
blockArray.push(VioletBlock);
and
for(var i:int = 0; i < blockArray.length; i++)
{
if (character.hitTestObject(blockArray[i]))
{
trace(“hit”);
}
}

Of course this will result in a lot of hitTests per frame, so you may want to consider optimizing the collision detection by either:

a) only performing a hitTest if the block is within a short distance from the player.
b) using simple math instead of hitTest by calculating the difference between the player and block’s x and y positions to determine if an overlap is occuring.

 
avatar for skyfish19 skyfish19 2 posts
Flag Post

Thank you Khronosis for your time and help.
Could you please, give me an example of how to create character radius and how to set, that hitTest performs only when wall is near?
Im sorry about my english mistakes.

 
avatar for Khronosis Khronosis 130 posts
Flag Post

If you’re going to use a radius around the player to determine if the block is close enough, you’ll want to use the Pythagorean theorem (simply, a^2 + b^2 = c^2), and compare “c” with your radius.

First, create a constant variable that will hold the value of the radius (“hitTestRadius”, for example).

Now, you’ll need to set up the Pythagorean theorem in your code. “a” will be the difference in x position between the player and block, and “b” will be the difference in y position. Solving for “c” will give you the length of the hypotenuse of the imaginary triangle created by “a” and “b”.

Setting up the theorem in code will end up looking something like this:

deltaX = blockArray[i].x – character.x;
deltaY = blockArray[i].y – character.y;
blockDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

Finally, you simply compare blockDistance with the radius you assigned your player (“hitTestRadius”). If blockDistance is smaller, it has passed your distance test, and you can allow it to perform the hitTestObject.

Fitting everything into your code, it’ll end up looking something like:

for(var i:int = 0; i < blockArray.length; i++)
{
	deltaX = blockArray[i].x - character.x;
	deltaY = blockArray[i].y - character.y;
	blockDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
	if(blockDistance < hitTestRadius)
	{
		if (character.hitTestObject(blockArray[i]))
		{
			trace(“hit”);
		}
	}
}
 
avatar for JamesObscura JamesObscura 250 posts
Flag Post

Khronosis has it close, but I don’t think he noticed you’re using a 2D array. Also, because it’s a tilebased system we can forgo using the distance formula all together.


var relativeX:int = (int)(character.x/tileWidth);
var relativeY:int = (int)(character.y/tileWidth);
//Convert the characters x/y coordinates to their corresponding array coordinates.

var i:int;
if(relativeY < 5){
    i = 0;
}else{
    i = relativeY-5;
}

var j:int;
if(relativeX < 5){
    j = 0;
}else{
    j = relativeX-5;
}

while(i < blockArray.length && i < (relativeY+5) ){
    while(j < blockArray[i].length && j < (relativeX + 5)){
        if (blockArray[i][j] is BlackBlock && character.hitTestObject(blockArray[i][j])){
            trace(“hit”);
        }
        j++;
    }
    i++;
}

Something like that?