zoukankan      html  css  js  c++  java
  • 让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity【转】

    对于大部分游戏来说,允许玩家控制游戏对象,是个非常基本的特性。而到目前为止,在学到的Box2D技巧中,创建了刚体之后,我们只能眼睁睁的看着它自由落体。我想,你肯定迫不及待的想“占有”它了,别急,今天我们就来学习一下,如何让刚体听我们的。

    Box2D中控制一个刚体,让它乖乖的听我们的话,有三种方法:ApplyForce、ApplyImpulse和 SetLinearVelocity。它们都是b2Body类的公共方法,而且它们都接收一个b2Vec2类型向量参数。关于向量的知识,请参考我之前发 的文章"【游戏基础】向量基础".

    1.力,循序渐进——ApplyForce

    顾名思义,ApplyForce方法会在刚体上施加一个力。学过物理力学的同学都知道,F=ma,有了力F就有了加速度a,有了加速度,物体就会有速度,就会慢慢动起来。(但是不会立马动起来,因为力不会直接影响速度)。

    举个简单的例子,小明推一个静止的箱子,箱子不会立马飞出去,而是慢慢的、越来越快的动起来(减速也一样)。

    2.速度,叠加——ApplyImpulse

    与ApplyForce不同,ApplyImpulse不会产生力,而是直接影响刚体的速度。通过ApplyImpulse方法添加的速度会与刚体原有的速度叠加,产生新的速度。

    3.一触即发——SetLinearVelocity

    setLinearVelocity与ApplyImpulse一样,直接影响刚体的速度。不一样的是,setLinearVelocity添加的 速度会覆盖刚体原有的速度。不过,在SetLinearVelocity方法不会自动唤醒sleeping的刚体,所以在调用该方法之前,记得将刚体 body.wakeUp()一下。

    在下面的实例的右上角,任意选择其中一种方法,交替按下键盘左右方向键,查看三种方法的区别。

    关于三个方法的用法,源代码中已经有详细的备注,我就不再解释了:

    package
    {
        import com.bit101.components.Panel;
        import com.bit101.components.RadioButton;
        import com.bit101.components.Window;
    
        import Box2D.Common.Math.b2Vec2;
        import Box2D.Dynamics.b2Body;
        import Box2D.Dynamics.b2World;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.KeyboardEvent;
        import flash.ui.Keyboard;
    
        /**
         * http://www.ladeng6666.com
         * @author ladeng6666
         */
        public class Main extends Sprite
        {
            //创建世界的基本元素
            private var world:b2World;
            private var debugSprite:Sprite;
            private var body:b2Body;
    
            private var vector:b2Vec2 = new b2Vec2();
            private var currentMethod:String = "ApplyForce";
    
            public function Main()
            {
                world=LDEasyBox2D.createWorld();
                debugSprite=LDEasyBox2D.createDebug(world);
                addChild(debugSprite);
    
                setWrapWalls();
    
                //创建矩形刚体
                body = LDEasyBox2D.createBox(world, stage.stageWidth / 2, 0, 30, 30);
                //侦听事件
                addEventListener(Event.ENTER_FRAME, loop);
                stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);
                stage.addEventListener(KeyboardEvent.KEY_UP, onStageKeyUp);
    
                setUI();
            }
    
            private function setWrapWalls():void
            {
                //创建左边的墙
                LDEasyBox2D.createBox(world, 0, stage.stageHeight / 2, 10, stage.stageHeight, true);
                //创建右边的墙
                LDEasyBox2D.createBox(world, stage.stageWidth, stage.stageHeight / 2, 10, stage.stageHeight, true);
                //创建地面,
                LDEasyBox2D.createBox(world,stage.stageWidth/2,stage.stageHeight,stage.stageWidth,10,true);
            }
    
            private function onStageKeyUp(e:KeyboardEvent):void
            {
                //清除速度或力
                vector.SetZero();
            }
    
            private function onStageKeyDown(ke:KeyboardEvent):void
            {
                switch (ke.keyCode) {
                    case Keyboard.LEFT:
                        vector.x = -15;
                        break;
                    case Keyboard.RIGHT:
                        vector.x = 15;
                        break;
                }
                trace(currentMethod);
                switch (currentMethod) {
                    case "ApplyForce":
                        //在刚体上施加vector压力。
                        //body.GetWorldCenter()方法用来获取刚体的重心
                        body.ApplyForce(vector, body.GetWorldCenter());
                        break;
                    case "ApplyImpulse":
                        //为刚体添加速度
                        body.ApplyImpulse(vector, body.GetWorldCenter());
                        break;
                    case "SetLinearVelocity":
                        //唤醒刚体
                        body.WakeUp();
                        //设置刚体的线性速度
                        body.SetLinearVelocity(vector);
                        break;
                }            
    
            }
    
            private function loop(e:Event):void
            {
                world.Step(1 / 30, 10);
            }
    
            //下面的方法用来创建UI
            private function setUI():void
            {
                var panel:Panel = new Panel(stage, 400, 10);
                panel.width = 100;
                panel.height = 60;
                var radio1:RadioButton = new RadioButton(panel, 5, 5, "ApplyForce", true,onRadioChange);
                var radio2:RadioButton = new RadioButton(panel, 5, 25, "ApplyImpulse", false,onRadioChange);
                var radio3:RadioButton = new RadioButton(panel, 5, 45, "SetLinearVelocity", false,onRadioChange);
            }
            //侦听UI中的radio按钮变更事件
            private function onRadioChange(e:Event):void {
                currentMethod = e.target.label;
            }
        }
    
    }
    
  • 相关阅读:
    SQL Server中使用convert进行日期转换
    杂记
    sqlserver表分区与调优与行列转换
    HttpModule的认识与深入理解及MVC运行机制
    再谈委托
    ASP.NET forms凭据设置和跳转的几种方法
    IOS学习网址
    Activator.CreateInstance 方法 (Type) 的用法
    update多表更新的2种方式
    SQL自定义函数split分隔字符串
  • 原文地址:https://www.cnblogs.com/lxiang/p/2683220.html
Copyright © 2011-2022 走看看