现在的位置: 首页 > 综合 > 正文

AS菜鸟之路【物理运动一竖直上抛】

2013年09月10日 ⁄ 综合 ⁄ 共 3739字 ⁄ 字号 评论关闭
Forward:

自从写AS3 之后,常常告诫自己要多记录学习历程,却久未实践,如今一晃半年已过,万分惭愧。
现在就把之前写的一些游戏中用到的物理运动效果,一步步的经历整理记录下把。
这篇首先实现一个简单的小球竖直上抛运动的过程,附上源代码。


Code:
主要代码分为两大部分,1. 小球的抽象定义及实现;2. 主场景对小球的控制。
1.1:[ 小球接口 ]。为了凸显半桶水的面向对象编程思想,决定先为运动的小球定义一个通用的接口
package physical.entity
{

    /**
     * 小球实体接口, 定义小球的基本行为
     *
     * @author    Jian
     * @date    2012-11-13
     */
    public interface IBall
    {
        /**
         * 定义小球外形
         */
        function initView():void

        /**
         * 定义运动逻辑
         */
        function move():void

    }
}
接口很简单,initView() 方法负责小球的渲染,可以在具体实现类中编写其表现形式;move() 方法将会被主窗口每帧调用,小球的实现类将会通过此方法来进行轨迹运算,每帧改变坐标来实现模拟运动。

1.2:[ 小球实现基类 Ball.as ] 编写一个小球的基类,作为小球的基本逻辑封装实现,详见代码中注释:
package physical.entity
{
    import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.utils.getTimer;

    /**
     *
     * 有运动轨迹的小球父类定义
     *
     * @author    Jian
     * @date    2012-10-24
     */
    public class Ball extends Sprite implements IBall
    {


        /**
         * 记录当前小球运动状态, 用以控制运动逻辑
         */
        protected var _state:int=-1;

        /**
         * 记录小球出现的时间戳, 供运动参数的计算
         */
        protected var _startTime:int;

        /**
         * 垂直方向上的加速度, 因这里模拟的是竖直上抛运动, 故可将其看做重力加速度的抽象, 单位为 : px/秒
         */
        protected var _gravity:Number=300;


        /**
         * @param $appearX 出生点 X坐标
         * @param $appearY 出生点Y坐标
         * @param $speedY 构造时赋予的垂直方向速度初始值
         * @param $parent 父显示容器
         */
        public function Ball($parent:DisplayObjectContainer=null)
        {
            initView();
            if ($parent)
            {
                $parent.addChild(this);
            }
        }

        /**
         * 实时更新小球运动轨迹
         */
        public function move():void
        {
        }

        /**
         * 定义小球的显示样式, 此处以一个红色小圆做例子, 具体到实际应用中可换成图片或者 MovieClip
         */
        public function initView():void
        {
            graphics.beginFill(0xff8888);
            graphics.drawCircle(0, 0, 10);
            graphics.endFill();
        }
    }
}
1.3: [ 竖直上抛小球 ]展示完本人拙劣的面向对象编程之后,开始进入正题。因为这次要做的是一个竖直上抛运动的模拟,因此实现一个竖直上抛的小球类,自然是继承自上面的小球基类:
package physical.entity
{
    import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.utils.getTimer;

    /**
     *
     * 有运动轨迹的小球父类定义
     *
     * @author    Jian
     * @date    2012-10-24
     */
    public class VerticalBall extends Ball
    {

        /**
         * 上升状态
         */
        public static const UP:int=1;

        /**
         * 下落状态
         */
        public static const DOWN:int=2;

        /**
         * 停止状态
         */
        public static const STOP:int=3;


        /**
         * 垂直方向的初始速度
         */
        protected var _speedY:Number;

        /**
         * 初始Y坐标
         */
        protected var _appearY:Number;

        /**
         * @param $appearX 出生点 X坐标
         * @param $appearY 出生点Y坐标
         * @param $speedY 构造时赋予的垂直方向速度初始值, 竖直初速度会影响上升的至高点值
         * @param $parent 父显示容器
         */
        public function VerticalBall($appearX:int, $appearY:int, $speedY:Number, $parent:DisplayObjectContainer=null)
        {
            super($parent);
            x=$appearX;
            y=_appearY=$appearY;
            _speedY=$speedY;
            _startTime=getTimer();
            _state=UP;
        }


        override public function move():void
        {
            var t:Number=(getTimer() - _startTime) / 1000; // 经过的时间, 单位为秒

            switch (_state)
            {

                case UP:
                {
                    /* 上升运动逻辑分支 */
                    y=_appearY - (_speedY * t - _gravity * t * t / 2); // 上升距离: vt-1/2 * g * t*t;
                    if (_speedY - _gravity * t <= 0)
                    {
                        // 已经减速到0, 即达到了竖直上抛的至高点, 此时小球结束竖直上升的匀减速运动, 即将开始竖直下落的匀加速运动
                        _appearY=y; // 更新起始位置为至高点
                        _startTime=getTimer(); // 更新起始时间
                        _state=DOWN; // 改变小球状态, 使其进入下落运动轨迹逻辑分支
                    }

                    break;
                }
                case DOWN:
                {
                    /* 下落运动逻辑分支 */

                    y=_appearY + _gravity * t * t / 2; // 下落距离: 1/2 * g *t*t
                    if (_gravity * t >= _speedY)
                    {
                        // 停止条件为速度从0重新加速到上升其实的初速度
                        _state=STOP;
                    }
                    break;
                }
                default:
                {
                    break;
                }
            }
        }

    }
}
2:[主场景类]小球实现完了,接着是编写主窗口来呈现小球的运动,在这里做个最简单的交互,每次点击舞台即创建一个数值上抛运动的小球:

package physical.vertical.up
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;

    import physical.entity.Ball;
    import physical.entity.IBall;
    import physical.entity.VerticalBall;

    /**
     * 用以演示的主场景窗口
     *
     * @author    Jian
     * @date    2012-10-29
     */
    [SWF(width="1000", height="600", frameRate="25")]
    public class VerticalUpView extends Sprite
    {

        /**
         * 持有一个小球实例
         */
        private var _ball:Ball;

        public function VerticalUpView()
        {
            addEventListener(Event.ADDED_TO_STAGE, __onAddToStage);
        }

        protected function __onAddToStage(event:Event):void
        {
            stage.addEventListener(MouseEvent.CLICK, __onMouseClick);
            stage.addEventListener(Event.ENTER_FRAME, __onEnterFrame);
        }

        /**
         * 主场景帧事件, 用以驱动场景内小球的运动行为
         */
        protected function __onEnterFrame(event:Event):void
        {
            if (!_ball)
                return;

            _ball.move();
        }

        /**
         * 点击一次舞台, 实例化一个小球, 小球开始模拟竖直上抛运动
         */
        protected function __onMouseClick(event:MouseEvent):void
        {
            if (_ball && _ball.parent)
            {
                _ball.parent.removeChild(_ball);
                _ball=null;
            }

            _ball=new VerticalBall(mouseX, mouseY, 400, this);

        }
    }
}



Conclusion:

说是模拟竖直上抛运动,但是在下落运动中,到达地面并没有模拟弹起,而是直接停止。
根据状态来区分运动轨迹太繁琐,且既不利于扩展。
下一篇中将会模拟弹起的运动。
在资源里有本部分的可执行源码。入口为 VerticalUpView.as 源码链接

抱歉!评论已关闭.