AS3 Collision Issue

Started by
2 comments, last by proto_typical 11 years, 7 months ago
In this project I've been working on, the Player remains stationary in the center of the screen while the maps moves around based on keyboard input.
-Map is tile-based; all of the tiles I have placed manually into a Movie Clip which is 1280x896 pixels, the script then places each of these tiles into an Array (blockArray). Historically, I have always been fairly successful in passing collision information between the Parent script and the Child script (Movie Clip tile-holder) without much trouble using point collision.

-In more physics-based projects, I've had more success with rectangular collision (getRect, and such). In these cases, however, I've never used it before in conjunction with Tile Holder/Movie Clip approached described above.

The following code runs as part of the MoveBall/Player script, which updates per frame. When I run this in the test window, it always crashes the program - perhaps it can't get out of the "for" Loop?


for(var i:int=blockArray.length-1;i>=0;i--)
{
var theBlock = blockArray;
var blockRect:Rectangle = getRect(theBlock);
if (blockRect.intersects (newBallRect))
{
//collision treatment here
}
}


Below is the method I have been using to build the level in the constructor function:


public function startGame()
{
//constructor code
stage.focus = stage;

if (_Level == null)
{
_Level = new level_obj(); // this Movie Clip, "level_obj", is where the blocks that are loaded into the blockArray reside.
addChild (_Level);

for (var i:int = _Level.numChildren-1;i>=0;i--) // this "for" Loop loads the blocks from inside the _Level Movieclip into the blockArray
{
if (_Level.getChildAt(i) is block_obj)
{
blockArray.push(_Level.getChildAt(i));
}
}
}


the main problem I've been encountering here is that "getRect(theBlock)" is not getting the Rectangle of the specific block that the Player/Ball is supposedly colliding with - "blockArray(i)". According to my traces, the size of the "blockRect" is 1280x896 - the size of the entire Movie Clip that holds all of the blocks in the "blockArray" - rather than just one of the blocks "(i)", which are 64x64.

Curiously, I made a sort of marker Movie Clip that gets added to the _Level Movie Clip during the for Loop in the collision/movement script; this Movie Clip always attaches to the registration point of first Block that I placed there, rather than the registration point of the _Level Movie Clip, which is in the upper-left corner on (0,0), and is what the "getRect" command seems to be referencing.


So, my question is: is this a lost cause or is there something that I can put in or take out to make this work?

and if I am wasting my time with this approach, then which of these approaches sound the most viable?
1) use the regular Array method (newArray = [Block, Block, Block, Lavapit, Block, etc.] - the construction of the level is handled completely in the Game/Constructor Class.

2) go back to point collision; not sure how well this will work for a physics-based project, though.

3) or is there perhaps an alternate method that I am unaware of?

In any case; much obliged, all! Good night/morning/afternoon/evening.
Advertisement
I believe your issue is a misunderstanding of how to use getRect()

you should try :

var blockRect:Rectangle = theBlock.getRect(_Level);


the parameter for getRect is -- targetCoordinateSpace:DisplayObject — The display object that defines the coordinate system to use.

The parent of the object is what I believe you should intend to use to define to the coordinate system. I'm assuming that is _Level in this case based on the code I see.
Thanks for the clarification; I don't usually get involved as much in the coding end of things, so this really helps!

over the past few days, I've been researching Separation of Axis Theory as well as some other literature on collision and physics. I managed to create a crude, but workable collision system from scratch based on measuring the distance between the four corners of each _block/tile against the center of the _ball/player object. The system worked pretty well, and I even got some basic jumping and gravity effects going.

Unfortunately, I needed to get the level to rotate. When I made the _Level mC rotate, however, the _ball would only respond to the _Level's non-rotated collision - while the level had the appearance of being rotated, the _ball kept running into "invisible" walls - presumably because the collision information was based on the non-rotated stage, which contains both the _ball and the _Level.

In order to fix this, I put the _ball mC into the _Level mC. This had the effect of causing all of the block_obj's/tiles to become undefined terms and "lose" their properties partway into the script - perhaps because the script couldn't distinguish between the block_obj's and the new _ball?

I'm running out of things to try right now, so any suggestions or advice would be a great help!


public function startTest()
{
// constructor code
collideUp = false;
collideDown = false;
collideRight = false;
collideLeft = false;
stage.focus = stage;

if (_Level == null)
{
_Level = new level_obj;
stage.addChild(_Level);
_Level.x = 320;
_Level.y = 224;

}

if (_ball == null)
{
_ball = new ball_obj;
_Level.addChild(_ball);
_ball.x = 320;
_ball.y = 224;
_ball.gotoAndStop("no_collision");


}

for(var i:int = _Level.numChildren-1;i>=0;i--)
{

//blockArray.visible = false;
if(_Level.getChildAt(i) is block_obj)
{
//trace("more!: " +more);
blockArray.push(_Level.getChildAt(i));


//trace("blockArray: " +blockArray);
} else if (_Level.getChildAt(i) is ball_obj)
{
//extraArray.push(_Level.getChildAt(i));
//I thought perhaps that the _Level didn't know what to do with the _ball mC, since it wasn't in an array, so I created another one. No dice.

}
}

//Event Listeners, etc.//

}//END FUNCTION

public function collision(event:Event):Array
{

_ball.gotoAndStop("no_collision");
for (var i:int = _Level.numChildren-1;i>=0;i--)
{
if (blockArray == _ball)
{
trace("ball");//perhaps the _Level was confused by the extra child?
}

var theBlock = blockArray;
//trace ("i.x: " +blockArray.x +" i.y: " +blockArray.y);
//trace ("ball.x: " +_ball.x +" ball.y: " +_ball.y);
//trace ("Level.x: " +(_Level.x) +" Level.y: " +(_Level.y));

//var ballCenterX = (-_Level.x+ballOffsetX);
//var ballCenterY = (-_Level.y+ballOffsetY);

var blockCenterX = _Level.theBlock.x; //This is where the "term" - presumably "blockArray "loses" it's definition/properties.
var blockCenterY = _Level.theBlock.y;

var ballCenterX = (ballOffsetX); //the 2 ballOffsets's were defined earlier in the script so that the collision funcion wouldn't need to rely directly on the coordinates of the _ball itself.
var ballCenterY = (ballOffsetY);

//trace("ballCenterX: " +ballCenterX +" ballCenterY: " +ballCenterY);

var blockLX = (blockCenterX +(theBlock.width/2))-ballCenterX;
var blockRX = (blockCenterX -(theBlock.width/2))-ballCenterX;
var blockUY = (blockCenterY +(theBlock.height/2))-ballCenterY;
var blockDY = (blockCenterY -(theBlock.height/2))-ballCenterY;

var DistX = blockCenterX - ballCenterX;
var DistY = blockCenterY - ballCenterY;
var Dist:Number = Math.sqrt(DistX*DistX + DistY*DistY);

var DistUL:Number = Math.sqrt(blockLX*blockLX +blockUY*blockUY);
var DistUR:Number = Math.sqrt(blockRX*blockRX +blockUY*blockUY);
var DistDL:Number = Math.sqrt(blockLX*blockLX +blockDY*blockDY);
var DistDR:Number = Math.sqrt(blockRX*blockRX +blockDY*blockDY);

//Code for determining collision directions, etc//
}

}//END FUNCTION


I'd really start with by addressing this statement you made "This had the effect of causing all of the block_obj's/tiles to become undefined terms and "lose" their properties partway into the script"

Does it make logical sense that putting the ball into the level would directly cause that ? To me, that sounds like a bug, and I'd not just trash a given direction just because of a bug. I'd hunt down the bug.

How might something become undefined ? It doesn't happen by just adding the ball as a child to the level or to an array.

If you are getting a run-time error with undefined objects or whatever, I'd start right there.

This topic is closed to new replies.

Advertisement