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;
            }
        }
    
    }
    
  • 相关阅读:
    java.lang.NoSuchMethodError
    asm相关内容想下载(包括 jar 包)
    Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/Type
    用Navicat连接mysql报错:2003-Can't connect to MySql server on '10.100.0.109'(10039)
    The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
    The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .class files
    交通测速方式
    卡口和电子警察的区别
    Myeclipse连接Mysql数据库时报错:Error while performing database login with the pro driver:unable
    在window上安装mysql
  • 原文地址:https://www.cnblogs.com/lxiang/p/2683220.html
Copyright © 2011-2022 走看看