0
votes

This is my code:

package {
    import players.*;
    import physics.Engine;
    import flash.display.MovieClip;

    public class Mission extends MovieClip {
        public function Mission() {
            var player1:Player1 = new Player1();
            player1.playerWeight = 2;
            player1.walkingSpeed = 5;

            stage.addEventListener(KeyboardEvent.KEY_DOWN, player1.keyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, player1.keyUp);

            Engine.addPlayer(player1);
        }
    }

}

The Engine class:

package physics {
    import animation.Player;
    import flash.events.Event;
    import scene.Mission;

    public class Engine {
        private static var _players:Array = new Array();

        public static function addPlayer(player:*):void{
            _players.push(player);
        }

        public static function update(e:Event):void{
            for(var i:String in _players){
                _gravity(_players[i]);
            }
        }

        private static function _gravity(player:*):void{
            if(solidBelow(player)){
                player.jumps = 0;
                player.jumping = false;
                player.gravity = 0;
            } else{
                player.gravity += player.playerWeight;
            }

            if(player.gravity < 0 && player.currentLabel != 'jumping'){ 
                player.gotoAndStop('jumping');
                player.jumping = true;
            }                   

            if(player.gravity > 5 && player.currentLabel != 'falling' && solidBelow(player) == false){ 
                player.gotoAndStop('falling');          
            }

            if(player.gravity > -10 && player.gravity < 0 && player.jumping == true){
                player.jumps++;
                player.jumping = false;
            }

            if(player.currentLabel == 'falling' && solidBelow(player) == true){ 
                player.gotoAndStop('still');
            }

            if(player.gravity > 100){
                player.die();
            }

            player.y += player.gravity;
        }

        public static function solidBelow(object:*):Boolean{
            for(var i:String in Mission.solidArray){ //contains all the solid blocks
                if(Mission.solidArray[i].hitTestPoint(object.x + object.bottomBumpPoint.x, object.y + object.bottomBumpPoint.y, true)){
                object.y = Mission.solidArray[i].y;
                return true;
            }
            }
            return false;
        }

        public static function solidLeft(object:*):Boolean{
            for(var i:String in Mission.solidArray){
                if(
                    Mission.solidArray[i].hitTestPoint(object.x + object.leftBumpPoint.x, object.y + object.leftBumpPoint.y, true)){
                    return true;
                }
            }
            return false;
        }

        public static function solidRight(object:*):Boolean{
            for(var i:String in Mission.solidArray){
                if(
                    Mission.solidArray[i].hitTestPoint(object.x + object.rightBumpPoint.x, object.y + object.rightBumpPoint.y, true)){
                    return true;
                }
            }
            return false;
        }

        public static function moveLeft(object:*):void{
            if(solidBelow(object) == true && object.currentLabel != 'walking'){ 
                object.gotoAndStop('walking'); 
            }

            if(!solidLeft(object)){
                object.scaleX = object.scaleX > 0 ? object.scaleX * -1 : object.scaleX * 1;
                object.x -= object.walkingSpeed;
            }
        }

        public static function moveRight(object:*):void{
            if(solidBelow(object) == true && object.currentLabel != 'walking'){ 
                object.gotoAndStop('walking'); 
            }

            if(!solidRight(object)){
                object.scaleX = object.scaleX < 0 ? object.scaleX * -1 : object.scaleX * 1;
                object.x += object.walkingSpeed;
            }
        }

        public static function jump(object:*, jumpHeight:int):void{         
            object.gotoAndStop('still');
            object.gravity = jumpHeight;                
            object.y--;
        }

    }   
}

The Player class:

package animation {
    import flash.display.MovieClip;
    import flash.events.KeyboardEvent;
    import flash.geom.Point;
    import physics.Engine;
        import flash.Events.Event;

    public class Player extends MovieClip{
        public var gravity:int = 0;
        public var jumping:Boolean = false;
        public var jumps:int = 0;
        public var walkingSpeed:int = 5;
        public var movingLeft:Boolean = false;
        public var movingRight:Boolean = false;

        public var leftBumpPoint:Point = new Point(-19, -80);
        public var rightBumpPoint:Point = new Point(20, -80);
        public var topBumpPoint:Point = new Point(0, 170);
        public var bottomBumpPoint:Point = new Point(0, 0);

        public const DIED:String  = 'died';

        public function Player() {

        }

        public function keyDown(e:KeyboardEvent){
            var keyCode:int = e.keyCode;

            //w = 87
            //a = 65
            //s = 83
            //d = 68

            //up = 38
            //left = 37
            //down = 40
            //right = 39

            //space = 32

            if(keyCode == 37 || keyCode == 65) { 
                addEventListener(Event.ENTER_FRAME, moveLeft, false, 0, true);
                movingLeft = true;
                if(movingRight == true){
                    movingRight = false;
                    removeEventListener(Event.ENTER_FRAME, moveRight);
                }
            } //left

            if(keyCode == 39 || keyCode == 68) {
                addEventListener(Event.ENTER_FRAME, moveRight, false, 0, true);
                movingRight = true;
                if(movingLeft == true){
                    movingLeft = false;
                    removeEventListener(Event.ENTER_FRAME, moveLeft);
                }
            }//right

            if((keyCode == 38 || keyCode == 87 || keyCode == 32) && jumping == false && jumps < 2) {
                switch (jumps){
                    case 0:
                        var jumpHeight:int = -20;
                        break;

                    case 1:
                        var jumpHeight:int = -25;
                        break;
                }

                jump(jumpHeight);
            } //up

            if(keyCode == 40 || keyCode == 83) {  } //down
        }

        public function keyUp(e:KeyboardEvent){
            var keyCode:uint = e.keyCode;

            //w = 87
            //a = 65
            //s = 83
            //d = 68

            //up = 38
            //left = 37
            //down = 40
            //right = 39

            //space = 32

            if(keyCode == 37 || keyCode == 65) { 
                gotoAndStop('still');
                removeEventListener(Event.ENTER_FRAME, moveLeft);
            } //left

            if(keyCode == 39 || keyCode == 68) { 
                gotoAndStop('still');
                removeEventListener(Event.ENTER_FRAME, moveRight);
            }//right

            if(keyCode == 40 || keyCode == 83) {  } //down
        }

        public function moveLeft(e:Event):void{
            Engine.moveLeft(this);
        }

        public function moveRight(e:Event):void{
            Engine.moveRight(this);
        }

        public function jump(jumpHeight:int):void{
            Engine.jump(this, jumpHeight);
        }

        public function respawn(xPos, yPos){
            gravity = 0;
            x = xPos;
            y = yPos;
        }

        public function die():void{
            var event:Event = new Event(DIED);
            dispatchEvent(event);
        }

    }

}

I got the code for the collision detection from this page: http://as3gametuts.com/2012/01/08/platformer-3/. There are still lots of bugs in the code though: for example, if you move left while there is a solid object left of you but it is lower than the left bump point, you pass right through it. Also, if you are moving with high speed, you can move through objects. Does anyone know a proper tutorial, or even better: can anyone give me some tips to start off with?

Thanks in advance

Edit: If it helps, here is a link to the game: http://host.undeadzone.net/stackoverflow.php

Yet another edit: It's not a tile-based game!

1

1 Answers

1
votes

Hmm, ok, few comments on the current code:
I'm not a fan of adding/removing eventlisteners on keypresses. You already store the moveLeft/moveRight states as bools so I'd just have a single 'move' function that checks those, e.g.

addEventListener(Event.ENTER_FRAME, move, false, 0, true); 

public function move(e:Event):void{
    if(moveLeft) Engine.moveLeft(this);
    else if(moveRight) Engine.moveRight(this);
}

Far easier to clean up afterwards... in fact, in your current code I don't see you removing listeners on death (maybe it's done elsewhere, but this is exactly the type of reason I'd avoid creating event listeners so often, it can get hard to keep track and if they aren't all removed then the object will never be garbage collected)

The problem of moving through objects at high speeds is called tunneling. There may be better methods but what I do is generate a line from the old position to the new one and check for collisions on that. Not too difficult when your colliders are simple rectangles, but if they're abritrary shapes I think you'll have to go a step further: Create a polygon that encompasses all the positions that the charater passed through and check for polygon (player path) - polygon (obstacle) collisions.