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

来源:互联网 发布:怎么接网站美工外包 编辑:程序博客网 时间:2024/04/30 16:55
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 源码链接
原创粉丝点击