Search code examples
actionscript-3hittest

AS3 - How to properly stop player with hitTestObject and restrict player's movement based on colliding area?


I have two issues with collision, the player can glitch through the object when pressing the moving keys multiple times and both the player's x and y movement would stop once touching any side of the object. It should only stop x or y depending on which side it's touching.

While it touches the left/right sides of the bounding box, it should still be able to move up and down. While it touches the top/bottom sides of the bounding box, it should be able to move side to side.

My movement code inside Player class ENTER_FRAME:

private function onEnterFrame(event:Event):void
{
    _vx = 0;
    _vy = 0;

    if (isRight)
    {
        _vx = 5;
    }

    if (isLeft)
    {
        _vx = -5;
    }

    if (isUp)
    {
        _vy = -5;
    }

    if (isDown)
    {
        _vy = 5;
    }

    x += _vx;
    y += _vy;

}

My hitTestObject code in CollisionBase class ENTER_FRAME (Base Class for MovieClips):

private function onEnterFrame(event:Event):void
{
    if (MovieClip(parent).player.collisionArea.hitTestObject(this))
    {
        if (MovieClip(parent).player.isLeft)
        {
            MovieClip(parent).player.x -= MovieClip(parent).player._vx;
        }

        if (MovieClip(parent).player.isRight)
        {
            MovieClip(parent).player.x -= MovieClip(parent).player._vx;
        }

        if (MovieClip(parent).player.isUp)
        {
            MovieClip(parent).player.y -= MovieClip(parent).player._vy;
        }

        if (MovieClip(parent).player.isDown)
        {
            MovieClip(parent).player.y -= MovieClip(parent).player._vy;
        }
    }
}

FLA file: https://www.dropbox.com/s/k5dlxrsnvbrmtke/Subject.zip?dl=0

The FLA file includes a player and a bed for it to collide with.


Solution

  • Your game design is not well structured. You should have one single ENTER_FRAME for the game logic. Instead of that, you have one ENTER_FRAME for the player, one ENTER_FRAME to swap children, and one ENTER_FRAME in every obstacle. This design give you more than one headache and will put the performance of your game on the floor.

    To fix the problem with the hitTest do the next things:

    Put this code in the CollisionBase Class:

    private function onEnterFrame(event:Event):void
    {
    
        var player:MovieClip = MovieClip(this.parent).player;
    
        if (player.collisionArea.hitTestObject(this)) player.collision = true;
    }
    

    Add this property to the Player Class:

    private var _collision:Boolean = false;
    
    public function set collision(value:Boolean):void{
        _collision = value;
    }
    

    And next, add these lines at the beginning of the onEnterFrame function:

    private function onEnterFrame(event:Event):void
    {
    
        if(_collision){
    
            x -= _vx;
            y -= _vy;
    
            _collision = false;
    
           return;
    
        }
    
        _vx = 0;
        _vy = 0;
    
        if (isRight)
        {
        ....
    

    The problem has been fixed, but now your player going to flicker when hits an obstacle. This happens because the player ENTER_FRAME moves the player, and then other ENTER_FRAME checks the collision (in CollisionBase.class) and in the next cycle of the player ENTER_FRAME the player does a step back. If you have a single ENTER_FRAME, such thing never happens.

    I propose you other alternative. Look at this example and look how it is made, maybe it give you some ideas ;)

    Download the example