p2 钢体
钢体可以控制沿x方向移动,沿y方向移动, 不旋转等. fixedX, fixedY, fixedRotaion 1)addBody和removeBody:
World类中的addBody()和removeBody()分别用来上P2世界添加和删除刚体。所有创建好的刚体,必须通过addBody()添加到P2世界中,才可以进行碰撞模拟:
var body:p2.Body({mass:1, position:[1,1]});
this.world.addBody(body);
当物体被子弹击中,或超出屏幕范围时,需要删除刚体,可以通过removeBody()将其从P2世界中删除,同时还可以避免不必要的计算。示例代码:
this.world.removeBody(bodyToRemove);
2)addShape和removeShape:
Body类中的addShape()和removeShape()分别用来向刚体中添加和删除形状。使用addShape():
var shape:p2.Rectangle=new p2.Rectangle(100,50);
var body:p2.Body=new p2.Body({mass:1, position:[1,1]);
body.addShape(shape);
其实,addShape()中还有其他参数,构造函数为:
function addShape(shape:p2.Shape, offset:number, angle:number)
其中参数除了被添加的形状shape,还有两个参数,offset为形状相对于坐标原点的偏移量,angle为形状的角度,这两个参数都是相对于刚体本地坐标系而言,即会随刚体的变化而变化。
可以通过removeShape()方法将指定的形状从刚体中删除。
形状的添加或删除,并不会改变刚体的重心坐标,因此可用来模拟不倒翁效果。
3)adjustCenterOfMass:
调整重心位置。刚体中增加或移去形状后,重心并不会自动改变,可以使用adjustCenterOf Mass()方法,使刚体重心重新回到中心位置。这个方法不带任何参数,也没有返回值。
4)applyForce:
作用力可以让刚体状态改变,通过applyForce()方法,可以在指定点worldPoint对刚体施加一个作用力,形成一个加速度或扭力,改变刚体的线速度或角速度。构造函数为:
function applyForce(force:number[], worldPoint:number[])
其中,force是要施加的作用力,这是一个二维向量; worldPoint是一个全局坐标点,表示force在刚体上的作用点,当此点不在刚体重心位置时,刚体角度也会发生变换。
5)applyImpulse:
如果要瞬间改变刚体的状态,如子弹弹出膛效果,需要使用applyImpulse()对其施加冲量,使刚体的速度和角速度瞬间发生变化。
function applyImpulse(impulse:number[], relativePoint:number[])
其中,impulse为要施加的冲量,冲量有大小和方向,是一个二维向量; relativePoint是一个本地坐标点,表示冲量的作用点,当作用点不在刚体中心时刚体角度也会发生变化。
6)sleep和wakeup:
Body的sleep()方法强制使刚体进入睡眠状态,此时除了sleepState处于Body.SLEEPING状态外,刚体的速度、角速度、受到的作用力、扭力等都会全部清零。
function sleep(){
this.sleepState=Body.SLEEPING;
this.angularVelocity=0;
this.angularForce=0;
vec2.set(this.velocity, 0, 0);
vec2.set(this.force, 0, 0);
this.emit(Body.sleepEvent);
};
刚体进入睡眠状态后,通过调用wakeup()方法,可以将刚体强制唤醒,但仅仅是将sleepState设置为Body.AWAKE,睡眠状态前的速度、角度等属性不会恢复:
function wakeup(){
var s=this.sleepState;
this.sleepState=Body.AWAKE;
this.idleTime=0;
if(s!==Body.AWAKE){
this.emit(Body.wakeUpEvent);
}
}
可以使用sleep()方法实现类似冰冻效果。
7)emit、on、off、has:
P2物理引擎中,通过EventEmitter类实现事件派发机制,并通过emit()、on()、off()、has()方法分别实现派发、监听、取消监听,以及检测是否包含指定事件功能。
⑴emit():派发自定义事件,事件类型使用任意字符串表示:
function emit(event:Object)
其中,event为要派发的自定义事件,是一个Object类型,用于包含任何需要通过事件传递的信息。在自定义事件时,event对象至少要包含名为type的字符串属性值,表示事件名称:
body.emit({type:"movingUp"});
⑵on():监听对应的自定义函数
监听到事件对象,将作为参数传递给事件监听函数,示例代码为:
var onMyEvent=function(event){
console.log("onMyEvent is fired, because I am moving up.");
};
body.on("movingUp", onMyEvent);
on()方法的参数是字符串类型的事件名称,并在事件触发时调用一个处理函数。
⑶off():取消监听
当不需要监听某个事件时,将事件名称和事件监听函数作为参数传递给off()方法,就可以取消监听。示例代码:
body.off("movingUp", onMyEvent);
⑷has():检查对象是否包含指定的事件监听
Body类因为继承了EventEmitter类,所以也拥有上面4个方法。通过这些方法,可以方便地对刚体的某些特定状态进行监听,如睡眠或苏醒。Body类内置了睡眠和苏醒事件:
·sleepEvent:当刚体进入睡眠状态时派发该事件,对应事件名称为sleep,监听使用body. on("sleep", onMyEvent);
·wakeupEvent:当刚体从睡眠状态恢复至苏醒状态时,派发wakeupEvent事件,事件名为wake,监听使用body.on("wake", onMyEvent);
·sleepyEvent:当刚体进入瞌睡状态时,派发该事件。Body有一个sleepSpeedLimit属性,当刚体的速度小于sleepSpeedLimit值时就进入瞌睡状态;如果该状态持续时间超过body. sleepTimeLimit,则刚体进入睡眠状态。sleepyEvent对应的事件名为sleepy,监听使用body. on("sleepy", onMyEvent);
除了上述内置事件,还可以自定义事件,比如在step()方法中持续判断body.velocity.y是否小于0,来检测刚体向上运动,派发自定义moveUp事件:
public loop():void{
this.world.step(60/1000);
this.debugDraw.drawDebug();
if(this.bodyRef.velocity[1]<0){
this.bodyRef.emit({type:"myEvent"});
}
}
8)fromPolygon:
fromPolygon用于将多边形分解成一个个小的形状,然后组合成完整的多边形。
function fromPolygon(path:number[][], [options]):boolean
其中,path保存了多边形顶点数组,options为可选属性,定义多边形分解的相关设置。
options包括的选项有:
·optimalDecomp=false:是否进行最佳分解,默认false,开启该选项会降低计算速度
·skipSimpleCheck=false:是否进行顶点交叉的判断,如果确定不存在交叉点可设为true
·removeCollinearPoints=false:是否剔除共线顶点,false表示不剔除
如果多边形创建成功返回true,否则返回false。导致创建失败有几种原因,比如创建的形状中有空洞、顶点和边之间有交叉。可以编程将鼠标光标移动的轨迹中的点作为多边形的顶点。也就是随手创建刚体。
9)hitTest:
用于实现指定坐标点与刚体的碰撞检测,并将检测到的碰撞刚体保存到数组中返回。
function hitTest(worldPoint:number[][], bodies:Body[], precision:number):Body[]
其中,worldPoint为要检测的坐标点,是一个全局坐标点;bodies为要检测的刚体清单,可以将需要检测的刚体保存到bodies数组中,实现有针对性的碰撞检测。如果要对所有的刚体进行检测,可以直接设置该参数为world.bodies,即:hitTest(worldPoint, world.bodies);
参数precision为检测精度,默认为0,取值越大检测精度越高,计算效率会降低,一般使用默认值,对尺寸极小的物体,如particle和line需要设置。方法的返回值为保存了与worldPoint发生碰撞所有刚体的数组。
hitTest()最常用用于检测鼠标光标点击、拖曳效果。P2中没有鼠标光标事件,可以通过hitTest()来判断鼠标点是否与刚体发生碰撞,然后调整刚体的position至鼠标位置,实现对刚体的拖曳。为了便于拖曳,在鼠标点击时通过sleep()方法将刚体设为睡眠状态,使其不受重力影响,可以精确地随鼠标光标移动,当拖曳完成弹起时再使用wakeUp()方法重新唤醒刚体,恢复重力的作用。
10)getAABB:
获取刚体的最小包围盒AABB(Axis Align Bounding Box),最小包围盒AABB是指包围形状的最小矩形框。可以通过设置刚体的isDrawAABB=true,以显示出刚体的AABB。AABB对象将矩形对象的左下角和右下角坐标分别保存在属性lowerBound和upperBound中。
11)getArea:
获取刚体的当前所有形状的面积总和。
12)setDensity:
设置刚体的密度,结构为:
function setDensity(density:number)
其中,density为要设置的密度,是取值大于0的数值。
实际上,P2中的刚体并没有密度属性,当调用setDensity()方法后,Body会根据刚体当前的面积area计算出对应的质量并保存在mass属性中。
13)overlaps:
检测当前刚体与指定刚体是否有重叠,并返回检测结果,结构为:
function overlaps(body:Body):boolean
其中,body为要检测的目标刚体。如果刚体之间有重叠则返回true,否则返回false。
目标刚体与被检测刚体需添加到world中,才能确保overlaps()的正常运行。通常并不需要使用overlaps()进行重叠检测,因为P2在实施碰撞检测和模拟时已经完成了这些内容,只有当刚体不进行碰撞模拟时才需要使用overlaps()。比如在界面中放置一个物体,当此位置已经存在物体时不能放置。
14)toWorldFrame和toLocalFrame:
toWorldFrame()是将刚体本地坐标系统中的坐标点转换成全局坐标点,toLocalFrame()是将全局坐标点转换成刚体本地坐标系统中的坐标点。通过这两个方法,可以实现本地坐标和全局坐标之间的转换。
function toWorldFrame(out:number[], localPoint:number[]):void
function toLocalFrame(out:number[],worldPoint:number[]):void
其中,out为转换后的本地坐标或全局坐标,将保存在该属性对应的变量中; localPoint为要转换的本地坐标;worldPoint为要转换的全局坐标。
15)raycast:
射线投射技术用于实现线段与形状的碰撞检测,通常用来模拟人物的视野、距离探测等。实现射线投射,要先从起点from到终点to构建一条射线ray,然后检测与该线段发生碰撞的刚体,并保存在一个RaycastResult对象中。raycast结构为:
function raycast(result:RaycastResult, ray:Ray)
其中,result是保存了碰撞刚体、碰撞点、碰撞距离等信息的一个RaycastResult对象;ray是用于检测的射线,是一个Ray类,包含起点from、终点to等属性。使用射线投射,需要用到Ray类和RaycastResult类。
①Ray类:
Ray类的构造函数为:
function Ray([options])
其中,options参数是一个Object对象,初始化Ray对象时,可以保持options缺省,然后再通过Ray属性进行设置。Options对象中包含一些参数:
·from:number[]:线段的起点,一个二维向量
·to:number[]:线段的终点,一个二维向量
·mode:number:射线的碰撞检测模式,取值为3个常量,分别为Ray.ALL、Ray.CLOSEST、Ray.ANY。Ray.ALL模式下,raycast()函数会检测所有与射线ray发生碰撞的刚体;Ray.CLOSEST模式下,返回检测到的碰撞刚体中距离起点from最近的刚体;Ray.ANY模式下,当ray检测到第1个碰撞刚体时会立刻停止检测并返回该刚体,这时的第1个刚体与创建时的顺序有关。
·callback:Function:回调函数,当raycast()检测到碰撞刚体后会立即调用回调函数,该属性只适用于rayCastAll()
·collisionMask:number:与collisionGroup配合使用,对检测刚体进行筛选
·collisionGroup:number:与collisionMask配合使用,对检测刚体进行筛选,只有满足条件的刚体才参与碰撞检测,检测条件为:
(this.collisionGroup&body.collisionMask)&&(body.collisionGroup&this.collisionMask)==true
·skipBackface:是否忽略射线ray反方向与刚体的碰撞点,值为false时只检测正方向
·checkCollisionResponse:配合Body中的collisionResponse属性,如果刚体的属性collisionResponse和checkCollisionResponse同时为true,则不对该刚体进行检测。
·direction:射线方向,可以缺省,取决于from和to属性
·length:射线从起点from到终点to的间距
②RaycastResult类:
RaycastResult类用于保存射线与刚体的碰撞信息,包括几个属性:
·body:当前碰撞检测中,与射线ray发生碰撞的刚体
·shape:当前碰撞刚体中,与射线ray发生重叠的形状
·fraction:射线起点from到碰撞点之间的距离distance与射线长度length的比例
·normal:垂直于射线碰撞边的法向量,只读属性,默认-1
RaycastResult类还有一些方法:
·hasHit():是否检测到与射线ray发生碰撞的刚体,当检测到时返回true
·getHitDistance():当检测到与射线发生碰撞的刚体时,碰撞点与射线起点from间的距离
function getHitDistance(ray:Ray):number
·getHitPoint():获取碰撞点位置,返回结果是一个全局坐标点
此方法的结构为function getHitPoint(out:number[], ray:Ray):void
其中,out为用于保存碰撞点坐标的二维向量,ray为当前进行碰撞检测的射线。
·stop():用于立即停止碰撞检测
因为raycast()方法中的RaycastResult会重复使用,所以回调函数中获取到的是最后一次碰撞检测信息。
p2 钢体的更多相关文章
- Rigidbody钢体移动时抖动问题
Rigidbody移动时抖动问题 撞墙抖动 Unity中物体移动有非常多的方式: 比如: transform.position += dir*speed*Time.deltaTime; transfo ...
- p2 休眠模式
如有错误,忘请指出. 才入手p2.p2有全局休眠模式,和钢体体眠模式.钢体能控制 body.allowSleep world.NO_SLEEPING 不允许休眠world.BODY_SLEEPING ...
- p2 入门
心里一片空白,要弄个p2的demo出来... 先了解下p2的概念吧 P2只是一个算法库,以刚体为对象模型,模拟并输出物理碰撞.运动结果.这个过程通过持续调用world中的step()方法来实现 p2的 ...
- 微信小游戏egret开发包括p2引擎小结
用egret + p2 做一个类似投球的小游戏,坑大致如下: 1.p2引擎与egret坐标不同注意转换,横坐标没什么,纵坐标egret.y = stageHeight - body.position[ ...
- c语言程序设计案例教程(第2版)笔记(三)—变量、结构体
零散知识点: 变量 :C语言中,每个变量必须先定义后引用.所谓变量存在是指系统为这个变量分配一块存储空间,此时对变量的操作,就是对变量所对应的存储空间中存放的数据进行操作.人们将变量占据 ...
- APDU
# APDU # 定义:APDU(ApplicationProtocolDataUnit--应用协议数据单元).协议数据单元PDU(ProtocolDataUnit)是指对等层次之间传递的数据单位.协 ...
- Linux设备驱动工程师之路——内核链表的使用【转】
本文转载自:http://blog.csdn.net/forever_key/article/details/6798685 Linux设备驱动工程师之路——内核链表的使用 K-Style 转载请注明 ...
- 私人C#笔记
coust 定义常量 string是密封类,所以不能继承它 namespace默认是按照文件夹的结构命名的,如(System.文件夹.子文件夹),而且namespace是可以手动改的 Arra ...
- Unity3D常用代码集合
1.基本碰撞检测代码 function OnCollisionEnter(theCollision : Collision){ if(theCollision.gameObject.n ...
随机推荐
- windows server dump文件
1. mini dump: ***** 需要包含 dbghelp.dll 库 ****mini_dump.h文件: // reference:https://msdn.microsoft.com/zh ...
- 总结安装matlab踩到的坑
个人安装matlab3次,每次都遇到不同的安装问题,现在将遇到的问题总结下来,以供参考. 本次安装MATLAB的步骤参考的博文 https://blog.csdn.net/u012313335/art ...
- spark执行命令 监控执行命令
#!/bin/bash #/usr/hdp/current/flume-server/bin/flume-ng agent -c conf/ -f /usr/hdp/current/flume-ser ...
- 基于FPGA的DDS设计(二)
在DDS设计中,如果相位累加器每个时钟周期累加1,就会输出频率为195.313KHz的波形.如果每个时钟周期累加2,就会输出频率为2*195.313KHz的波形·······,如果每两个时钟周期累加1 ...
- Oracle入门第一天(上)——简介与安装
一.Oracle介绍 Oracle 公司是全球最大的信息管理软件及服务供应商,成立于1977年 Oracle 公司因其复杂的关系数据库产品而闻名.Oracle的关系数据库是世界第一个支持SQL语言的 ...
- 20155204 2016-2017-2《Java程序设计》课程总结
20155204 2016-2017-2<Java程序设计>课程总结 目录 作业链接汇总 作业总结 实验报告链接汇总 代码托管链接 课堂项目实践 学习经验 问卷调查 链接二维码 (按顺序) ...
- java Hibernate UUID代码
package mypack; import java.io.Serializable; import java.net.InetAddress; /** * 唯一主键生成办法.从Hibernate中 ...
- [agc011F]Train Service Planning-[线段树优化dp+神秘思考题]
Description 传送门 Solution 请围观lhx大佬的博客(大佬写的太好了我都没有写的动力了em) Code #include<iostream> #include<c ...
- 1018: [SHOI2008]堵塞的交通traffic
1018: [SHOI2008]堵塞的交通traffic 链接 分析: 用线段树维护区间的四个端点的联通情况,然后查询的时候,把所有覆盖到的区间合并起来即可. 六种情况左上到右上(左边到右边的情况)… ...
- sqoop 数据迁移
sqoop 数据迁移 1 概述 sqoop是apache旗下一款“Hadoop和关系数据库服务器之间传送数据”的工具. 导入数据:MySQL,Oracle导入数据到Hadoop的HDFS.HIVE.H ...