[Box2D]让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity

时间:2021-09-16 20:05:13

出自:http://bbs.9ria.com/thread-135588-1-1.html


对于大部分游戏来说,允许玩家控制游戏对象,是个非常基本的特性。而到目前为止,在学到的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()一下。

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

[Box2D]让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity 

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

  1. package
  2. {
  3.     import com.bit101.components.Panel;
  4.     import com.bit101.components.RadioButton;
  5.     import com.bit101.components.Window;

  6.     import Box2D.Common.Math.b2Vec2;
  7.     import Box2D.Dynamics.b2Body;
  8.     import Box2D.Dynamics.b2World;
  9.     import flash.display.Sprite;
  10.     import flash.events.Event;
  11.     import flash.events.KeyboardEvent;
  12.     import flash.ui.Keyboard;

  13.     /**
  14.      * http://www.ladeng6666.com
  15.      * @author ladeng6666
  16.      */
  17.     public class Main extends Sprite
  18.     {
  19.         //创建世界的基本元素
  20.         private var world:b2World;
  21.         private var debugSprite:Sprite;
  22.         private var body:b2Body;

  23.         private var vector:b2Vec2 = new b2Vec2();
  24.         private var currentMethod:String = "ApplyForce";

  25.         public function Main()
  26.         {
  27.             world=LDEasyBox2D.createWorld();
  28.             debugSprite=LDEasyBox2D.createDebug(world);
  29.             addChild(debugSprite);

  30.             setWrapWalls();

  31.             //创建矩形刚体
  32.             body = LDEasyBox2D.createBox(world, stage.stageWidth / 2, 0, 30, 30);
  33.             //侦听事件
  34.             addEventListener(Event.ENTER_FRAME, loop);
  35.             stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);
  36.             stage.addEventListener(KeyboardEvent.KEY_UP, onStageKeyUp);

  37.             setUI();
  38.         }

  39.         private function setWrapWalls():void
  40.         {
  41.             //创建左边的墙
  42.             LDEasyBox2D.createBox(world, 0, stage.stageHeight / 2, 10, stage.stageHeight, true);
  43.             //创建右边的墙
  44.             LDEasyBox2D.createBox(world, stage.stageWidth, stage.stageHeight / 2, 10, stage.stageHeight, true);
  45.             //创建地面,
  46.             LDEasyBox2D.createBox(world,stage.stageWidth/2,stage.stageHeight,stage.stageWidth,10,true);
  47.         }

  48.         private function onStageKeyUp(e:KeyboardEvent):void
  49.         {
  50.             //清除速度或力
  51.             vector.SetZero();
  52.         }

  53.         private function onStageKeyDown(ke:KeyboardEvent):void
  54.         {
  55.             switch (ke.keyCode) {
  56.                 case Keyboard.LEFT:
  57.                     vector.x = -15;
  58.                     break;
  59.                 case Keyboard.RIGHT:
  60.                     vector.x = 15;
  61.                     break;
  62.             }
  63.             trace(currentMethod);
  64.             switch (currentMethod) {
  65.                 case "ApplyForce":
  66.                     //在刚体上施加vector压力。
  67.                     //body.GetWorldCenter()方法用来获取刚体的重心
  68.                     body.ApplyForce(vector, body.GetWorldCenter());
  69.                     break;
  70.                 case "ApplyImpulse":
  71.                     //为刚体添加速度
  72.                     body.ApplyImpulse(vector, body.GetWorldCenter());
  73.                     break;
  74.                 case "SetLinearVelocity":
  75.                     //唤醒刚体
  76.                     body.WakeUp();
  77.                     //设置刚体的线性速度
  78.                     body.SetLinearVelocity(vector);
  79.                     break;
  80.             }            

  81.         }

  82.         private function loop(e:Event):void
  83.         {
  84.             world.Step(1 / 30, 10);
  85.         }

  86.         //下面的方法用来创建UI
  87.         private function setUI():void
  88.         {
  89.             var panel:Panel = new Panel(stage, 400, 10);
  90.             panel.width = 100;
  91.             panel.height = 60;
  92.             var radio1:RadioButton = new RadioButton(panel, 5, 5, "ApplyForce", true,onRadioChange);
  93.             var radio2:RadioButton = new RadioButton(panel, 5, 25, "ApplyImpulse", false,onRadioChange);
  94.             var radio3:RadioButton = new RadioButton(panel, 5, 45, "SetLinearVelocity", false,onRadioChange);
  95.         }
  96.         //侦听UI中的radio按钮变更事件
  97.         private function onRadioChange(e:Event):void {
  98.             currentMethod = e.target.label;
  99.         }
  100.     }

  101. }
复制代码