Skip to main content
December 28, 2010
Answered

Collision detection - falling through objects

  • December 28, 2010
  • 1 reply
  • 518 views

*EnglishVersion follows after German*

Hallo Zusammen,

ich habe ein ernsthaftes Problem in Flash. Ich bin eigentlich ganz gut in der Materie drin und programiere gerade ein Jump & Run Spiel.
Allerdings kommt es gerade dennoch zu einem ernsthaften Problem, das ich nicht lösen kann.
Wenn ich in meinem Spiel die Figur bewege, soll sich nicht die Figur, sondern das Level darum herum bewegen. Dabei gibt es hier mehrere Container, die für Gegner und für Bonus Items usw.
Alle Objekte haben eine "Gravitation" (im ENTER_FRAME), die dafür sorgt, dass sie nach unten fallen, wenn sie nicht auf einen Boden auftreffen.
Das funktioniert im Prinzip recht einfach, nur dass Objekte verschiedener Ebenen durcheinander hindurchfallen. Liegt das vielleicht an den (localToGlobal)-Koordinaten oder so etwas??
Konkret ist das Problem, dass Objekte einer extra Ebene (bsp. eine "Bonusitem-Ebene") durch den Boden(in der "Boden-Ebene") fallen. Objekte, die in der selben Ebene wie der Boden sind, tun das allerdings nicht.

Ich habe das mal in Kurzform als CS3 gespeichert, so dass ihr euch das Problem anschauen könnt.
Der Link lautet:
www.tobias-reich.de/flashproblem.fla

Hier ist auch noch einmal der Code:

/* Press anykey for a while to see whats happening! */
addEventListener(Event.ENTER_FRAME, fall);
stage.addEventListener(KeyboardEvent.KEY_DOWN, move);
var ballLayer:MovieClip = new MovieClip();
addChild(ballLayer);
// ball is falling -> falling through ground after a while
var ball:MovieClip = new Ball();
ball.x = 100;
ball.y = 150;
ballLayer.addChild(ball);
// ball on same layer -> it works perfectly well!
var ball2:MovieClip = new Ball2();
ball2.x = 120;
ball2.y = 150;
addChild(ball2);
var ground:MovieClip = new Ground();
ground.x = 100;
ground.y = 200;
addChild(ground);
function fall(e:Event):void {
    if(!ground.hitTestPoint(ball.x, ball.y, true)){
        ball.y +=5
  }  
   if(!ground.hitTestPoint(ball2.x, ball2.y, true)){
        ball2.y +=5
   }
}
function move(e:KeyboardEvent):void {
    ground.x +=5
    ballLayer.x +=5;
    ball2.x +=5;
}

P.S. Mir ist natürlich klar, dass im richtigen Spiel in eigenen Klassen und nicht in der Timeline programmiert wird. Das dient hier nur der Einfacheit der Situation.
Ich hoffe, ihr versteht mein Problem.
Ich bin ratlos, bitte helft mir!

Alles gute und einen guten Rutsch ins Neue Jahr,

Tobias

----------------------------------------------

Hello there,

I have a serious problem with Action Script. I'm about to code a new Jump&Run game with a simple gravitation Engine.


And this is where I got my problem I can not solve!

When moving the player through the levels, I want to move the layers instead of him. So the player stays somehow where he is but the enemies, ground, items ... move around - as in most of these games.

The gravitation is intendet to affect every item/enemy (by ENTER_FRAME) and moves every object downwards until it hits the ground.

The problem is, objects of different Layers somehow don't get the right hitTest information. So when having two objects - the first on the same layer as the ground, moving both, everything is fine. But as soon as I put the object into a separate container like "itemsContainer:MovieClip" and I move that, the object doesn't get the right result for hitTestPoints. (Maybe it has something to do with localToGlobal??)

So after a while when moving the ground and the itemLayer, it doesn't check its still on the ground and falls "down" - out of the scene...

I was saving the code for you in a separate CS3 file. I hope someone can see this problem and knows an answer!

tobias-reich.de/flashproblem.fla

For those who don't want to download the code:

ActionScript Code:
/* Press anykey for a while to see whats happening! */
addEventListener(Event.ENTER_FRAME, fall);
stage.addEventListener(KeyboardEvent.KEY_DOWN, move);
var ballLayer:MovieClip = new MovieClip();
addChild(ballLayer);
// ball is falling -> falling through ground after a while
var ball:MovieClip = new Ball();
ball.x = 100;
ball.y = 150;
ballLayer.addChild(ball);
// ball on same layer -> it works perfectly well!
var ball2:MovieClip = new Ball2();
ball2.x = 120;
ball2.y = 150;
addChild(ball2);
var ground:MovieClip = new Ground();
ground.x = 100;
ground.y = 200;
addChild(ground);
function fall(e:Event):void {
    if(!ground.hitTestPoint(ball.x, ball.y, true)){
        ball.y +=5;
   }  
   if(!ground.hitTestPoint(ball2.x, ball2.y, true)){
        ball2.y +=5;
    }
}
function move(e:KeyboardEvent):void {
    ground.x +=5;
     ballLayer.x +=5;
    ball2.x +=5;
}
P.S. Of course I know I'm not supposed to code into the timeline but I did for you to easily see the point.

I hope someone might help me with that. I'm quite desparate!!!

Have a happy new year to all of you!
This topic has been closed for replies.
Correct answer Ned Murphy

There is no rule that states you cannot use the timeline... feel free to ignore anyone who insists it is improper.

The problem arises because your ground is gradually moving to the right, its x property increasing, but the ball (ball) is not (ballLayer is).  So when the ground moves beyond that x property of ball - 100 (which is inside the ballLayer)...

if(!ground.hitTestPoint(ball.x, ball.y, true)){

becomes a true condition and the first ball drops.  Since the other, ball2, is being moved, its x property is changing as the ground changes.  I don't know if the following will give you the result you are expecting/after, but it is more in line with what you are doing....

if(!ground.hitTestPoint(ballLayer.x, ball.y, true)){

.

1 reply

Ned Murphy
Ned MurphyCorrect answer
Legend
December 28, 2010

There is no rule that states you cannot use the timeline... feel free to ignore anyone who insists it is improper.

The problem arises because your ground is gradually moving to the right, its x property increasing, but the ball (ball) is not (ballLayer is).  So when the ground moves beyond that x property of ball - 100 (which is inside the ballLayer)...

if(!ground.hitTestPoint(ball.x, ball.y, true)){

becomes a true condition and the first ball drops.  Since the other, ball2, is being moved, its x property is changing as the ground changes.  I don't know if the following will give you the result you are expecting/after, but it is more in line with what you are doing....

if(!ground.hitTestPoint(ballLayer.x, ball.y, true)){

.