P2:小众、易上手的、物理引擎 Life is but a span.
前端的同学都用什么物理引擎开发项目呢?我给大家推荐一款小众引擎——P2。易上手、结构轻是我选择P2的原因。尤其是Egret官方嵌入了P2,让我在使用Egret的时候效率倍增!
p2.js是stefan——一个瑞士的杀马特开发出来的,然后由拉登大叔集成到Egret中。拉登大叔的原话是:“在JavaScript物理引擎中,P2的执行效率要比Box2D等引擎要高。”。
一句话概括P2是什么: 回答:基于Javascript编写、HTML5、2D、物理引擎。
流程:世界->形状->刚体->渲染贴图->更新
-
世界:P2的入口。
//创建世界 private createWorld(): void { var wrd:p2.World = new p2.World(); wrd.gravity = [0,-10];//重力 this.world = wrd; }
-
形状:做碰撞检测的外形。请跳到页尾查看属性。
//创建矩形 var boxShape: p2.Box = new p2.Box({ width: shapeWidth / factor,height: shapeWidth / factor });//传入矩形宽高
-
刚体:碰撞对象的原型。shape必须添加在body上,才能物理模拟。
//创建刚体: private createBody(): void { var boxBody: p2.Body = new p2.Body({ mass: bodyMass,position: [x ,y ] });//传入刚体质量和坐标 boxBody.addShape(boxShape); boxBody.velocity = [velocityX,velocityY];//初始化刚体速度 this.world.addBody(boxBody); }
-
渲染:p2本身不具备渲染功能,必须借助如Canvas、Cocos2dx、Egret等渲染引擎,通过绘制或贴图来渲染物理模拟结果。
//使用P2DebugDraw调试视图 private createDebug(): void { var sprite: egret.Sprite = new egret.Sprite(); this.addChild(sprite); this.debugDraw = new p2DebugDraw(this.world,sprite); }
-
在帧频事件loop()中更新p2世界。
private loop(): void { this.world.step(60 / 1000);//更新频率 }
进阶篇,在虚拟世界里脑洞大开:
碰撞才有火花,当两个刚体碰撞在一起时,会有什么化学反应发生?P2里有很多类,模拟不同的物理活动。具体方法请跳到页尾,点开传送门。
- LockConstraint 锁定约束
作用:两物体叠加锁定。
用途:玩过愤怒的小鸟吧,鼠标拉紧小鸟,再放手就发射成功了。这里鼠标跟小鸟的锁定就可以用LockConstraint解决。
- DistanceConstraint 距离约束
作用:物体间的引力和互斥。
用途:神奇的引力看不见摸不到,可以模拟磁铁的强大功能;更完美的是玻璃珠串成的门帘,一根一根的晃动特效。
- RevoluteConstraint 旋转约束
作用:物体可以绕着所设置的锚点作旋转运动。
用途:公主的旋转木马不行,但是旋转风车的功能绝对能实现。
- PrismaticConstraint 活塞约束或者移动约束
作用:物体只能在单一方向作运动。
用途:复古的时钟钟摆,或者不倒翁。
- LinearSpring 线性弹簧
作用:物体之间弹性规律运动。
用途:软绵绵的弹簧床。
说一说我遇到的坑:
-
不同的坐标系问题?
P2原点是屏幕左下角:向右为X正,向上为Y正。重力默认值[0,-9.78],即地心引力向下。 在Egret的舞台中,原点是屏幕左上角。p2DebugDraw是基于Egret写出来的,却没有根据Egret的习惯把坐标调整到左上角。 我直接说结论吧:蒙圈的我在Egret中用p2DebugDraw调试,发现重力向上,所有东西都惊悚的飘起来。
-
当你射箭到箭靶上的时候,我想要的效果是箭头刚刚好粘在上面而不是全都扎进去!
产品妹子的要求是丝毫不差,我自坦然应对。 碰撞检测的精度是引擎写死的,刚体的大小也是调节好的,我只能去改变贴图的大小尺寸啦。Egret的锚点用的是绝对坐标,比较坑,需要手动调节贴图的锚点和缩放,剩下的只是体力活的问题。
-
还是射箭的问题
如果不想干体力活,那就去挑战极限吧——DIY碰撞检测。 P2的碰撞检测用的是AABB包围盒,或者说大部分的引擎用的都是这种方法。 AABB是离散碰撞检测,优点是:方法简单,速度快;缺点是:子弹穿透到盾牌里,才能检测出来。如果子弹速度无敌快,说不定子弹已经穿透盾牌飞走了。 连续碰撞检测法可以完美解决这个问题。连续的优点是:任意两个时刻,都可以返回第一碰撞点的位置和法线;缺点是:手机会卡死,开销太大! 一句话概括:AABB包围盒仅适用于精度不高的游戏中。如果需求精确的子弹穿透问题,这种离散碰撞检测算法将不再适用。
-
中文资料太少!
如果无法翻墙,想查阅中文资料简直太难了!方法名需要猜,类名需要猜,版本控制好乱,想找几个例子更是难上加难。 这才是P2最大的坑!
我手头的P2资料:
常用属性:
- angle :角度。
- angularVelocity :角速度。
- position :坐标。
- damping :速度阻尼。刚体在线性速度方向上受到的阻力。
- force :作用力。刚体在线性速度方向上收到的扭力。
- velocity :速度。
- type :刚体类型。Dynamic、Kinematic或Static
- mass :刚体质量。
常用形状:
- Capsule:胶囊形状。
- Circle:标准圆型。
- HeightFeild:地面形状。这种形状由一组y坐标组成,用来模拟高低不平的地面,如Tiny wing中的地面。
- Line:线段形状,用来创建高度为1个像素,长度为length的线段。
- Particle:粒子形状。粒子形状的尺寸均为零,没有质量和惯性。
- Plane:平面形状。
- Rectangle:矩形。
- convex:自定义的形状。
blog comments powered by Disqus