让刚体听我的——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; } } }
联系作者
最近正在看box2d,看到您的博客,实在是太高兴了。
等您讲完box2d,能再讲将away3d不。
真的在准备学习away3d,应该会的
期待away3d 。。。 螺柱加油
请问 速度的叠加是向量的叠加吗?
是的,关于向量的知识,我们在isSensor创建感应区域里讲到过
为什么我用 SetZero 这个按键盘松开的时候物体还是做加速运动呢
力也是不叠加的,对吧
学习了,刚接触Box2D还是一头雾水。
想请教拉灯老师,能不能使用声音波形快照或声音通道来影响刚体的重力,就是说用声音使刚体运动。
可以的,只要将声音的数据转换成数值,就可以作为作用力来影响刚体运动
谢谢,我试试看
呵呵!能随声音跳动了,但有点乱可能是帧频的问题,有时间再弄弄。
你说的乱指的是刚体发生漂移的现象吗?那个应该跟帧频没有关系的
是没有实现根据形状分配重力,我发源文件请你给看看改改行吗?行的话晚些发网盘传给你。
上传了源文件百度盘,有时间给看看;解开我注释掉的文档类97行测试,可能更容易看出问题:
http://pan.baidu.com/s/1o6wn1yE
可以,发我邮箱吧,ladeng6666@163.com
你好!已发邮伯。
已经在邮件里回复你了,注意查收!
主要问题是你没有应用文中的三个函数,而是直接更新了贴图