Search code examples
actionscript-3actionscriptgame-physics

AS3 Character only stops at walls in one direction


I tried almost everything to make my character stop when it detects a wall. It only works for UP and RIGHT or DOWN and LEFT but not all 4 directions, so only one y movement and one x movement. So I decided to make 4 functions, one for each direction. But then it only works when the left key is pressed and hits a wall.

My question to you is; What do I have to do to make the collision detection stop the character from moving in all 4 directions? Thanks in advance

var leftArrow:Boolean;
var upArrow:Boolean;
var rightArrow:Boolean;
var downArrow:Boolean;
var speed:int = 10;
var hitting:Boolean;
var ismoving:Boolean;
var wallsRect:Rectangle = bounds.getBounds(this);
var charRect:Rectangle = char.getBounds(this);

var boundsBmpData = new BitmapData(wallsRect.width, wallsRect.height, true, 0);
var charBmpData = new BitmapData(charRect.width, charRect.height, true, 0);

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, detectHit2);
stage.addEventListener(Event.ENTER_FRAME, walkingLEFT);
stage.addEventListener(Event.ENTER_FRAME, walkingUP);
stage.addEventListener(Event.ENTER_FRAME, walkingDOWN);
stage.addEventListener(Event.ENTER_FRAME, walkingRIGHT);

boundsBmpData.draw(bounds);
charBmpData.draw(char);

function keyPressed(event:KeyboardEvent):void 
    {
        if (event.keyCode == Keyboard.LEFT) 
            {
                leftArrow = true;

            }
        if (event.keyCode == Keyboard.UP) 
            {
                upArrow = true;
            }
        if (event.keyCode == Keyboard.RIGHT) 
            {
                rightArrow = true;
            }
        if (event.keyCode == Keyboard.DOWN) 
            {
                downArrow = true;
            }


    }





function keyReleased(event:KeyboardEvent):void
    {
        if (event.keyCode == Keyboard.LEFT) 
            {
                leftArrow = false;

            }
        if (event.keyCode == Keyboard.UP) 
            {
                upArrow = false;
            }
        if (event.keyCode == Keyboard.RIGHT) 
            {
                rightArrow = false;

            }
        if (event.keyCode == Keyboard.DOWN) 
            {
                downArrow = false;
            }
    }


function walkingLEFT(event:Event):void 
{
    if (leftArrow && ! hitting) 
        {
            char.x -= speed;

        }else
                                {
                                    hitting = false;
                                    ismoving = false;

                                }
}

function walkingRIGHT(event:Event):void 
{
    if (rightArrow && ! hitting) 
        {
            char.x += speed;

        }else
                                {
                                    hitting = false;
                                    ismoving = false;

                                }
}


function walkingUP(event:Event):void
{

                    if (upArrow && ! hitting)
                        {
                            char.y -= speed;

                        }
                            else
                                {
                                    hitting = false;
                                    ismoving = false;

                                }
                }

function walkingDOWN(event:Event):void
{

                    if (downArrow && ! hitting)
                        {
                            char.y += speed;

                        }
                            else
                                {
                                    hitting = false;
                                    ismoving = false;

                                }
                }




function detectHit2(e:Event):void
{
    if(boundsBmpData.hitTest(new Point(bounds.x, bounds.y),
                                255,
                                charBmpData,
                                new Point(char.x, char.y),
                                255))
        {

            hitting = true;
            ismoving = false;

        }
            else 
                { 

                      hitting = false;

                      bounds.filters = [];
                }
        }

Solution

  • The above code will indeed not work for all other directions then left.

    The order of the listener calls, is that same as you added them.

    So first detectHit2() is performed which will set hitting to true if there is an overlap.

    Next left is checked via walkingLEFT(); if the user does not press left the variable hitting is set to false again.

    With the additional walkingXXXX() methods hitting will be false, and the coordinate will always be adjusted if the specific key is pressed down.

    Like the previous answer said, try to use 1 single event listener.

    Something like this:

    this.addEventListener(Event.ENTER_FRAME, handleEnterFrame);
    
    function handleEnterFrame(anEvent: Event): void
    {
      var newx: Number = char.x - (leftArrow ? speed : 0) + (rightArrow ? speed : 0);
      var newy: Number = char.y - (upArrow ? speed : 0) + (downArrow ? speed : 0);
      if(!boundsBmpData.hitTest(new Point(bounds.x, bounds.y),
                                255,
                                charBmpData,
                                new Point(newx, newy),
                                255))
      {
         char.x = newx;
         char.y = newy;
      }
    }
    

    If you allow your player to press multiple direction keys, you might need to refine the above code by adjusting first the X and then the Y coordinate (so requiring two times a hitTest call). So the char glides across walls when the user presses two direction keys and one of those keys keeps bumping the char into the wall.