AS3 - Movie Clip animations (undesirably) bob up and down. [Playable SWF included]

和自甴很熟 提交于 2019-12-10 11:55:18

问题


Im making a game where the player controls a movieclip (_character) around the stage with the arrows or WASD. On the stage there are squares/boxes with collision detection. Plus a 50 pixel stage boundary.

_character has five key frames, each with an animation inside, which plays when the four direction buttons are pressed, plus the red stationary animation when no keys are pressed. While moving the characters body and head should be still, with the legs moving. Example below

_character Right Animation

However my problem is that the Movie clip bobs up and down at different areas around the stage, then is fine in others.

In the SWF example below you’ll see the characters mouth and shoulders bobbing up and down around the stage, but strangely enough its back to normal at the bottom of the play area. (Apart from in-between the two boxes to the lower right.)

Rookies Game SWF

This is the embedded SWF featuring all frames. The only thing that should change is the body colour and the eyes and legs moving. The head and shoulders dont bob up and down.

ChAracter Resource SWF

Does anyone have any idea what this is or why its happening? I triple checked my character swf just in case there is a miss-positioned frame to create the bouncing/bobbing animation, but they are all correct, the swf should not be doing that.

If I remove some boxes, the bobbing effect stops in some areas, but comes back in others. Sometimes when it touches a box it bobs and other sides of boxes it doesnt(?) Strangely enough, the bobbing returns when I press down at the bottom of the play area. In the other SWF the bottom of the stage was one of the few areas where the MovieClip didnt bob/bounce.

Rookies Game SWF w/ less boxes

If I remove all the boxes, the bobbing stops except when I press down on the bottom of the playable area. But only that one side causes the bobbing. If I remove the stage boundaries also, the bobbing completely stops presumably because there is nothing for the MovieClip to react to.


Current Code

Rookies game/Application class is used as a level switcher to put levelOne onto the stage.

package
{
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    [SWF(width="650", height="450", backgroundColor="#FFFFFF", frameRate="60")]

    public class RookiesGame extends Sprite
    {
        private var _levelOne:LevelOne;
        //public static var gameMute:Boolean = false;

        public function RookiesGame()
        {
            _levelOne = new LevelOne(stage);

            stage.addChild(_levelOne);
            stage.addEventListener("levelOneComplete",levelTwoSwitchHandler);
        }
        private function levelTwoSwitchHandler(event:Event):void
        {

        }
    }
}

Level One contains most of the code, and majority of the work.

package
{
    //import statements

    public class LevelOne extends Sprite
    {
        //Declare the variables to hold the game objects
        private var _character:Character = new Character();
        private var _background:Background = new Background();

        private var _box1:Box = new Box();
        //Other box vars    

                //A variable to store the reference to the stage from the application class
        private var _stage:Object;
        //Control System
        private var _bUp:Boolean = false;
        private var _bDown:Boolean = false;
        private var _bLeft:Boolean = false;
        private var _bRight:Boolean = false;

        public function LevelOne(stage:Object)
        {
            _stage = stage; 
            this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
        private function addedToStageHandler(event:Event):void
        {
            startGame();
            this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
        private function startGame():void
        {
            //Add them to stage. 
            addGameObjectToLevel(_background, 0, 0);

            addGameObjectToLevel(_box1, 300, 200);
            //Other boxes added to level

            //Add character 
            this.addChild(_character);
            _character.x = 300;
            _character.y = 50;
            _character.gotoAndStop(1);

            playGame(); 
        }
        private function playGame():void
        {   //EVENT LISTENERS////////////////////////
            _stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            _stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler); 
            this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        private function enterFrameHandler(event:Event):void
        {   
            _character.accelerationX = 0;
            _character.accelerationY = 0;
            _character.friction = 0.94;

            var _updown:Boolean=Boolean(!(_bUp==_bDown)); 
            var _leftright:Boolean=Boolean(!(_bLeft==_bRight));

            if (!_updown && !_leftright) 
            {   // not moving anywhere
                _character.gotoAndStop(1);
                _character.accelerationX = 0;
                _character.accelerationY = 0; 
                _character.friction = 0.94;

                _character.vy=0;
                _character.vx=0; 
            }
            else
            {
                if (_bUp) 
                {
                    _character.accelerationY = -0.5;
                    _character.gotoAndStop(2);
                } 
                else if (_bDown)
                {
                    _character.accelerationY = 0.5;
                    _character.gotoAndStop(3);
                } 
                if (_bLeft)
                {
                    _character.accelerationX = -0.5;
                    _character.gotoAndStop(4);
                } 
                else if (_bRight)
                {
                    _character.accelerationX = 0.5;
                    _character.gotoAndStop(5);
                }                           
            }
            //Apply friction
            _character.vx *= _character.friction; 
            _character.vy *= _character.friction;
            //Apply acceleration 
            _character.vx += _character.accelerationX; 
            _character.vy += _character.accelerationY;
            //Limit the speed
            if (_character.vx > _character.speedLimit)
            {
                _character.vx = _character.speedLimit;
            }
            if (_character.vx < -_character.speedLimit)
            {
                _character.vx = -_character.speedLimit;
            }
            if (_character.vy > _character.speedLimit)
            {
                _character.vy = _character.speedLimit;
            } 
            if (_character.vy < -_character.speedLimit)
            {
                _character.vy = -_character.speedLimit;
            }
            //Force the velocity to zero after it falls below 0.1
            if (Math.abs(_character.vx) < 0.1)
            {
                _character.vx = 0;
            }
            if (Math.abs(_character.vy) < 0.1)
            {
                _character.vy = 0;
            }
            //Move the character 
            _character.x += _character.vx;
            _character.y += _character.vy;
            checkStageBoundaries(_character);

            //Box Collisions
            Collision.block(_character,_box1);
            Other box collisions

        }
        private function checkStageBoundaries(gameObject:MovieClip):void
        {
            if (gameObject.x < 50)
            {
                gameObject.x = 50;
            }
            if (gameObject.y < 50)
            {
                gameObject.y = 50;
            }
            if (gameObject.x + gameObject.width > _stage.stageWidth - 50)
            {
                gameObject.x = _stage.stageWidth - gameObject.width - 50;
            }
            if (gameObject.y + gameObject.height > _stage.stageHeight - 50)
            {
                gameObject.y = _stage.stageHeight - gameObject.height - 50;
            }
        }

        public function replay():void
        {
            _stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            _stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpHandler); 
            this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
            startGame();
        }
        private function keyDownHandler(event:KeyboardEvent):void
        {
            if (event.keyCode == Keyboard.LEFT || event.keyCode == 65 )
            {
                _bLeft=true;                
            }
            else if (event.keyCode == Keyboard.RIGHT || event.keyCode == 68)
            {
                _bRight=true;               
            }
            else if (event.keyCode == Keyboard.UP || event.keyCode == 87 )
            {
                _bUp=true;              
            }
            else if (event.keyCode == Keyboard.DOWN || event.keyCode == 83)
            {
                _bDown=true;                
            }   
            if (event.keyCode == Keyboard.ENTER)
            {
                replay();
            }
        }
        private function keyUpHandler(event:KeyboardEvent):void
        {
            if (event.keyCode == Keyboard.LEFT || event.keyCode == Keyboard.RIGHT 
                || event.keyCode == 65 || event.keyCode == 68)
            {
                _bLeft=false;
                _bRight=false;
            } 
            else if (event.keyCode == Keyboard.DOWN || event.keyCode == Keyboard.UP 
                || event.keyCode == 87 || event.keyCode == 83 )
            {
                _bUp=false;
                _bDown=false;
            }
        }
        private function addGameObjectToLevel(gameObject:Sprite, xPos:int, yPos:int):void
        {
            this.addChild(gameObject);
            gameObject.x = xPos;
            gameObject.y = yPos;
        }   
    }
}

_character is an instance of the Character Class.

The SWF has five key frames, each with an animation inside, which plays when the four direction buttons are pressed, plus the red stationary animation when nothing is being pressed.

package
{
    import flash.display.MovieClip;
    import flash.display.DisplayObject

        [Embed(source="../swfs/characterResource.swf", symbol="Character")]
        public class Character extends MovieClip
        {
            //Public properties
            public var vx:Number = 0;
            public var vy:Number = 0;
            public var accelerationX:Number = 0; 
            public var accelerationY:Number = 0; 
            public var speedLimit:Number = 4; 
            public var friction:Number = 0.94;

            public function Character()
            {
            }
        }   
}

The Box and Background classes are the same, they just show the sprites. Note that the grid background is a single image. The game is not tile based..

The Collision Class. When _character collides with a box, it calls the Collision.block function.

package 
{
    import flash.display.Sprite;

    public class Collision
    {
        static public var collisionSide:String = ""; 

        public function Collision()
        {
        }
        static public function block(r1:Sprite, r2:Sprite):void
        {
            //Calculate the distance vector
            var vx:Number 
                = (r1.x + (r1.width / 2)) 
                - (r2.x + (r2.width / 2));

            var vy:Number 
                = (r1.y + (r1.height / 2)) 
                - (r2.y + (r2.height / 2));

            //Check whether vx 
            //is less than the combined half widths
            if(Math.abs(vx) < r1.width / 2 + r2.width / 2)
            {
                //A collision might be occurring! Check 
                //whether vy is less than the combined half heights
                if(Math.abs(vy) < r1.height / 2 + r2.height / 2)
                {
                    //A collision has ocurred! 
                    //Find out the size of the overlap on both the X and Y axes
                    var overlap_X:Number 
                    = r1.width / 2 
                        + r2.width / 2 
                        - Math.abs(vx);

                    var overlap_Y:Number 
                    = r1.height / 2 
                        + r2.height / 2 
                        - Math.abs(vy);

                    //The collision has occurred on the axis with the
                    //*smallest* amount of overlap. Let's figure out which
                    //axis that is

                    if(overlap_X >=  overlap_Y)
                    {
                        //The collision is happening on the X axis
                        //But on which side? _v0's vy can tell us 
                        if(vy > 0)
                        {
                            collisionSide = "Top";

                            //Move the rectangle out of the collision
                            r1.y = r1.y + overlap_Y;
                        }
                        else
                        {
                            collisionSide = "Bottom";

                            //Move the rectangle out of the collision
                            r1.y = r1.y - overlap_Y;
                        }
                    }
                    else
                    {
                        //The collision is happening on the Y axis
                        //But on which side? _v0's vx can tell us 
                        if(vx > 0)
                        {
                            collisionSide = "Left";

                            //Move the rectangle out of the collision
                            r1.x = r1.x + overlap_X;
                        }
                        else
                        {
                            collisionSide = "Right"; 

                            //Move the rectangle out of the collision
                            r1.x = r1.x - overlap_X;
                        }
                    }
                }
                else
                {
                    //No collision
                    collisionSide = "No collision";
                }
            }
            else
            {
                //No collision
                collisionSide = "No collision";
            }
        }
    }
}  

Any help would be much appreciated.

Im also asking a question about the jump/shudder the Movieclip does when crossing gaps in the maze. If any of that info helps you, or you're smart enough to know the solution to that too, the question is HERE

来源:https://stackoverflow.com/questions/22544533/as3-movie-clip-animations-undesirably-bob-up-and-down-playable-swf-include

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!