初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View File

@@ -0,0 +1,556 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('./CCPhysicsTypes').PTM_RATIO;
var ContactType = require('./CCPhysicsTypes').ContactType;
var pools = [];
// temp world manifold
var pointCache = [cc.v2(), cc.v2()];
var b2worldmanifold = new b2.WorldManifold();
/**
* @class WorldManifold
*/
var worldmanifold = {
/**
* !#en
* world contact point (point of intersection)
* !#zh
* 碰撞点集合
* @property {[Vec2]} points
*/
points: [],
/**
* !#en
* a negative value indicates overlap
* !#zh
* 一个负数,用于指明重叠的部分
*/
separations: [],
/**
* !#en
* world vector pointing from A to B
* !#zh
* 世界坐标系下由 A 指向 B 的向量
* @property {Vec2} normal
*/
normal: cc.v2()
};
/**
* !#en
* A manifold point is a contact point belonging to a contact manifold.
* It holds details related to the geometry and dynamics of the contact points.
* Note: the impulses are used for internal caching and may not
* provide reliable contact forces, especially for high speed collisions.
* !#zh
* ManifoldPoint 是接触信息中的接触点信息。它拥有关于几何和接触点的详细信息。
* 注意:信息中的冲量用于系统内部缓存,提供的接触力可能不是很准确,特别是高速移动中的碰撞信息。
* @class ManifoldPoint
*/
/**
* !#en
* The local point usage depends on the manifold type:
* -e_circles: the local center of circleB
* -e_faceA: the local center of circleB or the clip point of polygonB
* -e_faceB: the clip point of polygonA
* !#zh
* 本地坐标点的用途取决于 manifold 的类型
* - e_circles: circleB 的本地中心点
* - e_faceA: circleB 的本地中心点 或者是 polygonB 的截取点
* - e_faceB: polygonB 的截取点
* @property {Vec2} localPoint
*/
/**
* !#en
* Normal impulse.
* !#zh
* 法线冲量。
* @property {Number} normalImpulse
*/
/**
* !#en
* Tangent impulse.
* !#zh
* 切线冲量。
* @property {Number} tangentImpulse
*/
function ManifoldPoint () {
this.localPoint = cc.v2();
this.normalImpulse = 0;
this.tangentImpulse = 0;
}
var manifoldPointCache = [new ManifoldPoint(), new ManifoldPoint()];
var b2manifold = new b2.Manifold();
/**
* @class Manifold
*/
var manifold = {
/**
* !#en
* Manifold type : 0: e_circles, 1: e_faceA, 2: e_faceB
* !#zh
* Manifold 类型 : 0: e_circles, 1: e_faceA, 2: e_faceB
* @property {Number} type
*/
type: 0,
/**
* !#en
* The local point usage depends on the manifold type:
* -e_circles: the local center of circleA
* -e_faceA: the center of faceA
* -e_faceB: the center of faceB
* !#zh
* 用途取决于 manifold 类型
* -e_circles: circleA 的本地中心点
* -e_faceA: faceA 的本地中心点
* -e_faceB: faceB 的本地中心点
* @property {Vec2} localPoint
*/
localPoint: cc.v2(),
/**
* !#en
* -e_circles: not used
* -e_faceA: the normal on polygonA
* -e_faceB: the normal on polygonB
* !#zh
* -e_circles: 没被使用到
* -e_faceA: polygonA 的法向量
* -e_faceB: polygonB 的法向量
* @property {Vec2} localNormal
*/
localNormal: cc.v2(),
/**
* !#en
* the points of contact.
* !#zh
* 接触点信息。
* @property {[ManifoldPoint]} points
*/
points: []
};
/**
* !#en
* Contact impulses for reporting.
* !#zh
* 用于返回给回调的接触冲量。
* @class PhysicsImpulse
*/
var impulse = {
/**
* !#en
* Normal impulses.
* !#zh
* 法线方向的冲量
* @property normalImpulses
*/
normalImpulses: [],
/**
* !#en
* Tangent impulses
* !#zh
* 切线方向的冲量
* @property tangentImpulses
*/
tangentImpulses: []
};
/**
* !#en
* PhysicsContact will be generated during begin and end collision as a parameter of the collision callback.
* Note that contacts will be reused for speed up cpu time, so do not cache anything in the contact.
* !#zh
* 物理接触会在开始和结束碰撞之间生成,并作为参数传入到碰撞回调函数中。
* 注意:传入的物理接触会被系统进行重用,所以不要在使用中缓存里面的任何信息。
* @class PhysicsContact
*/
function PhysicsContact () {
}
PhysicsContact.prototype.init = function (b2contact) {
this.colliderA = b2contact.GetFixtureA().collider;
this.colliderB = b2contact.GetFixtureB().collider;
this.disabled = false;
this.disabledOnce = false;
this._impulse = null;
this._inverted = false;
this._b2contact = b2contact;
b2contact._contact = this;
};
PhysicsContact.prototype.reset = function () {
this.setTangentSpeed(0);
this.resetFriction();
this.resetRestitution();
this.colliderA = null;
this.colliderB = null;
this.disabled = false;
this._impulse = null;
this._b2contact._contact = null;
this._b2contact = null;
};
/**
* !#en
* Get the world manifold.
* !#zh
* 获取世界坐标系下的碰撞信息。
* @method getWorldManifold
* @return {WorldManifold}
*/
PhysicsContact.prototype.getWorldManifold = function () {
var points = worldmanifold.points;
var separations = worldmanifold.separations;
var normal = worldmanifold.normal;
this._b2contact.GetWorldManifold(b2worldmanifold);
var b2points = b2worldmanifold.points;
var b2separations = b2worldmanifold.separations;
var count = this._b2contact.GetManifold().pointCount;
points.length = separations.length = count;
for (var i = 0; i < count; i++) {
var p = pointCache[i];
p.x = b2points[i].x * PTM_RATIO;
p.y = b2points[i].y * PTM_RATIO;
points[i] = p;
separations[i] = b2separations[i] * PTM_RATIO;
}
normal.x = b2worldmanifold.normal.x;
normal.y = b2worldmanifold.normal.y;
if (this._inverted) {
normal.x *= -1;
normal.y *= -1;
}
return worldmanifold;
};
/**
* !#en
* Get the manifold.
* !#zh
* 获取本地(局部)坐标系下的碰撞信息。
* @method getManifold
* @return {Manifold}
*/
PhysicsContact.prototype.getManifold = function () {
var points = manifold.points;
var localNormal = manifold.localNormal;
var localPoint = manifold.localPoint;
var b2manifold = this._b2contact.GetManifold();
var b2points = b2manifold.points;
var count = points.length = b2manifold.pointCount;
for (var i = 0; i < count; i++) {
var p = manifoldPointCache[i];
var b2p = b2points[i];
p.localPoint.x = b2p.localPoint.x * PTM_RATIO;
p.localPoint.Y = b2p.localPoint.Y * PTM_RATIO;
p.normalImpulse = b2p.normalImpulse * PTM_RATIO;
p.tangentImpulse = b2p.tangentImpulse;
points[i] = p;
}
localPoint.x = b2manifold.localPoint.x * PTM_RATIO;
localPoint.y = b2manifold.localPoint.y * PTM_RATIO;
localNormal.x = b2manifold.localNormal.x;
localNormal.y = b2manifold.localNormal.y;
manifold.type = b2manifold.type;
if (this._inverted) {
localNormal.x *= -1;
localNormal.y *= -1;
}
return manifold;
};
/**
* !#en
* Get the impulses.
* Note: PhysicsImpulse can only used in onPostSolve callback.
* !#zh
* 获取冲量信息
* 注意:这个信息只有在 onPostSolve 回调中才能获取到
* @method getImpulse
* @return {PhysicsImpulse}
*/
PhysicsContact.prototype.getImpulse = function () {
var b2impulse = this._impulse;
if (!b2impulse) return null;
var normalImpulses = impulse.normalImpulses;
var tangentImpulses = impulse.tangentImpulses;
var count = b2impulse.count;
for (var i = 0; i < count; i++) {
normalImpulses[i] = b2impulse.normalImpulses[i] * PTM_RATIO;
tangentImpulses[i] = b2impulse.tangentImpulses[i];
}
tangentImpulses.length = normalImpulses.length = count;
return impulse;
};
PhysicsContact.prototype.emit = function (contactType) {
var func;
switch (contactType) {
case ContactType.BEGIN_CONTACT:
func = 'onBeginContact';
break;
case ContactType.END_CONTACT:
func = 'onEndContact';
break;
case ContactType.PRE_SOLVE:
func = 'onPreSolve';
break;
case ContactType.POST_SOLVE:
func = 'onPostSolve';
break;
}
var colliderA = this.colliderA;
var colliderB = this.colliderB;
var bodyA = colliderA.body;
var bodyB = colliderB.body;
var comps;
var i, l, comp;
if (bodyA.enabledContactListener) {
comps = bodyA.node._components;
this._inverted = false;
for (i = 0, l = comps.length; i < l; i++) {
comp = comps[i];
if (comp[func]) {
comp[func](this, colliderA, colliderB);
}
}
}
if (bodyB.enabledContactListener) {
comps = bodyB.node._components;
this._inverted = true;
for (i = 0, l = comps.length; i < l; i++) {
comp = comps[i];
if (comp[func]) {
comp[func](this, colliderB, colliderA);
}
}
}
if (this.disabled || this.disabledOnce) {
this.setEnabled(false);
this.disabledOnce = false;
}
};
PhysicsContact.get = function (b2contact) {
var c;
if (pools.length === 0) {
c = new cc.PhysicsContact();
}
else {
c = pools.pop();
}
c.init(b2contact);
return c;
};
PhysicsContact.put = function (b2contact) {
var c = b2contact._contact;
if (!c) return;
pools.push(c);
c.reset();
};
var _p = PhysicsContact.prototype;
/**
* !#en
* One of the collider that collided
* !#zh
* 发生碰撞的碰撞体之一
* @property {Collider} colliderA
*/
/**
* !#en
* One of the collider that collided
* !#zh
* 发生碰撞的碰撞体之一
* @property {Collider} colliderB
*/
/**
* !#en
* If set disabled to true, the contact will be ignored until contact end.
* If you just want to disabled contact for current time step or sub-step, please use disabledOnce.
* !#zh
* 如果 disabled 被设置为 true那么直到接触结束此接触都将被忽略。
* 如果只是希望在当前时间步或子步中忽略此接触,请使用 disabledOnce 。
* @property {Boolean} disabled
*/
/**
* !#en
* Disabled contact for current time step or sub-step.
* !#zh
* 在当前时间步或子步中忽略此接触。
* @property {Boolean} disabledOnce
*/
_p.setEnabled = function (value) {
this._b2contact.SetEnabled(value);
};
/**
* !#en
* Is this contact touching?
* !#zh
* 返回碰撞体是否已经接触到。
* @method isTouching
* @return {Boolean}
*/
_p.isTouching = function () {
return this._b2contact.IsTouching();
};
/**
* !#en
* Set the desired tangent speed for a conveyor belt behavior.
* !#zh
* 为传送带设置期望的切线速度
* @method setTangentSpeed
* @param {Number} tangentSpeed
*/
_p.setTangentSpeed = function (value) {
this._b2contact.SetTangentSpeed(value / PTM_RATIO);
};
/**
* !#en
* Get the desired tangent speed.
* !#zh
* 获取切线速度
* @method getTangentSpeed
* @return {Number}
*/
_p.getTangentSpeed = function () {
return this._b2contact.GetTangentSpeed() * PTM_RATIO;
};
/**
* !#en
* Override the default friction mixture. You can call this in onPreSolve callback.
* !#zh
* 覆盖默认的摩擦力系数。你可以在 onPreSolve 回调中调用此函数。
* @method setFriction
* @param {Number} friction
*/
_p.setFriction = function (value) {
this._b2contact.SetFriction(value);
};
/**
* !#en
* Get the friction.
* !#zh
* 获取当前摩擦力系数
* @method getFriction
* @return {Number}
*/
_p.getFriction = function () {
return this._b2contact.GetFriction();
};
/**
* !#en
* Reset the friction mixture to the default value.
* !#zh
* 重置摩擦力系数到默认值
* @method resetFriction
*/
_p.resetFriction = function () {
return this._b2contact.ResetFriction();
};
/**
* !#en
* Override the default restitution mixture. You can call this in onPreSolve callback.
* !#zh
* 覆盖默认的恢复系数。你可以在 onPreSolve 回调中调用此函数。
* @method setRestitution
* @param {Number} restitution
*/
_p.setRestitution = function (value) {
this._b2contact.SetRestitution(value);
};
/**
* !#en
* Get the restitution.
* !#zh
* 获取当前恢复系数
* @method getRestitution
* @return {Number}
*/
_p.getRestitution = function () {
return this._b2contact.GetRestitution();
};
/**
* !#en
* Reset the restitution mixture to the default value.
* !#zh
* 重置恢复系数到默认值
* @method resetRestitution
*/
_p.resetRestitution = function () {
return this._b2contact.ResetRestitution();
};
PhysicsContact.ContactType = ContactType;
cc.PhysicsContact = module.exports = PhysicsContact;

View File

@@ -0,0 +1,716 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
const PhysicsTypes = require('./CCPhysicsTypes');
const ContactType = PhysicsTypes.ContactType;
const BodyType = PhysicsTypes.BodyType;
const RayCastType = PhysicsTypes.RayCastType;
const DrawBits = PhysicsTypes.DrawBits;
const PTM_RATIO = PhysicsTypes.PTM_RATIO;
const ANGLE_TO_PHYSICS_ANGLE = PhysicsTypes.ANGLE_TO_PHYSICS_ANGLE;
const PHYSICS_ANGLE_TO_ANGLE = PhysicsTypes.PHYSICS_ANGLE_TO_ANGLE;
const convertToNodeRotation = require('./utils').convertToNodeRotation;
const DebugDraw = require('./platform/CCPhysicsDebugDraw');
var b2_aabb_tmp = new b2.AABB();
var b2_vec2_tmp1 = new b2.Vec2();
var b2_vec2_tmp2 = new b2.Vec2();
var vec2_tmp = cc.v2();
/**
* !#en
* Physics manager uses box2d as the inner physics system, and hide most box2d implement details(creating rigidbody, synchronize rigidbody info to node).
* You can visit some common box2d function through physics manager(hit testing, raycast, debug info).
* Physics manager distributes the collision information to each collision callback when collision is produced.
* Note: You need first enable the collision listener in the rigidbody.
* !#zh
* 物理系统将 box2d 作为内部物理系统,并且隐藏了大部分 box2d 实现细节(比如创建刚体,同步刚体信息到节点中等)。
* 你可以通过物理系统访问一些 box2d 常用的功能,比如点击测试,射线测试,设置测试信息等。
* 物理系统还管理碰撞信息的分发,她会在产生碰撞时,将碰撞信息分发到各个碰撞回调中。
* 注意:你需要先在刚体中开启碰撞接听才会产生相应的碰撞回调。<br>
* 支持的物理系统指定绘制信息事件,请参阅 {{#crossLink "PhysicsManager.DrawBits"}}{{/crossLink}}
* @class PhysicsManager
* @uses EventTarget
*/
var PhysicsManager = cc.Class({
mixins: [cc.EventTarget],
statics: {
DrawBits: DrawBits,
/**
* !#en
* The ratio transform between physics unit and pixel unit, generally is 32.
* !#zh
* 物理单位与像素单位互相转换的比率,一般是 32。
* @property {Number} PTM_RATIO
* @static
*/
PTM_RATIO: PTM_RATIO,
/**
* !#en
* The velocity iterations for the velocity constraint solver.
* !#zh
* 速度更新迭代数
* @property {Number} VELOCITY_ITERATIONS
* @default 10
* @static
*/
VELOCITY_ITERATIONS: 10,
/**
* !#en
* The position Iterations for the position constraint solver.
* !#zh
* 位置迭代更新数
* @property {Number} POSITION_ITERATIONS
* @default 10
* @static
*/
POSITION_ITERATIONS: 10,
/**
* !#en
* Specify the fixed time step.
* Need enabledAccumulator to make it work.
* !#zh
* 指定固定的物理更新间隔时间,需要开启 enabledAccumulator 才有效。
* @property {Number} FIXED_TIME_STEP
* @default 1/60
* @static
*/
FIXED_TIME_STEP: 1/60,
/**
* !#en
* Specify the max accumulator time.
* Need enabledAccumulator to make it work.
* !#zh
* 每次可用于更新物理系统的最大时间,需要开启 enabledAccumulator 才有效。
* @property {Number} MAX_ACCUMULATOR
* @default 1/5
* @static
*/
MAX_ACCUMULATOR: 1/5
},
ctor: function () {
this._debugDrawFlags = 0;
this._debugDrawer = null;
this._world = null;
this._bodies = [];
this._joints = [];
this._contactMap = {};
this._contactID = 0;
this._delayEvents = [];
this._accumulator = 0;
cc.director._scheduler && cc.director._scheduler.enableForTarget(this);
/**
* !#en
* If enabled accumulator, then will call step function with the fixed time step FIXED_TIME_STEP.
* And if the update dt is bigger than the time step, then will call step function several times.
* If disabled accumulator, then will call step function with a time step calculated with the frame rate.
* !#zh
* 如果开启此选项,那么将会以固定的间隔时间 FIXED_TIME_STEP 来更新物理引擎,如果一个 update 的间隔时间大于 FIXED_TIME_STEP则会对物理引擎进行多次更新。
* 如果关闭此选项,那么将会根据设定的 frame rate 计算出一个间隔时间来更新物理引擎。
* @property {Boolean} enabledAccumulator
* @default false
*/
this.enabledAccumulator = false;
},
pushDelayEvent: function (target, func, args) {
if (this._steping) {
this._delayEvents.push({
target: target,
func: func,
args: args
});
}
else {
target[func].apply(target, args);
}
},
update: function (dt) {
var world = this._world;
if (!world || !this.enabled) return;
this.emit('before-step');
this._steping = true;
var velocityIterations = PhysicsManager.VELOCITY_ITERATIONS;
var positionIterations = PhysicsManager.POSITION_ITERATIONS;
if (this.enabledAccumulator) {
this._accumulator += dt;
var FIXED_TIME_STEP = PhysicsManager.FIXED_TIME_STEP;
var MAX_ACCUMULATOR = PhysicsManager.MAX_ACCUMULATOR;
// max accumulator time to avoid spiral of death
if (this._accumulator > MAX_ACCUMULATOR) {
this._accumulator = MAX_ACCUMULATOR;
}
while (this._accumulator > FIXED_TIME_STEP) {
world.Step(FIXED_TIME_STEP, velocityIterations, positionIterations);
this._accumulator -= FIXED_TIME_STEP;
}
}
else {
var timeStep = 1/cc.game.config['frameRate'];
world.Step(timeStep, velocityIterations, positionIterations);
}
if (this.debugDrawFlags) {
this._checkDebugDrawValid();
this._debugDrawer.clear();
world.DrawDebugData();
}
this._steping = false;
var events = this._delayEvents;
for (var i = 0, l = events.length; i < l; i++) {
var event = events[i];
event.target[event.func].apply(event.target, event.args);
}
events.length = 0;
this._syncNode();
},
/**
* !#en
* Test which collider contains the given world point
* !#zh
* 获取包含给定世界坐标系点的碰撞体
* @method testPoint
* @param {Vec2} point - the world point
* @return {PhysicsCollider}
*/
testPoint: function (point) {
var x = b2_vec2_tmp1.x = point.x/PTM_RATIO;
var y = b2_vec2_tmp1.y = point.y/PTM_RATIO;
var d = 0.2/PTM_RATIO;
b2_aabb_tmp.lowerBound.x = x-d;
b2_aabb_tmp.lowerBound.y = y-d;
b2_aabb_tmp.upperBound.x = x+d;
b2_aabb_tmp.upperBound.y = y+d;
var callback = this._aabbQueryCallback;
callback.init(b2_vec2_tmp1);
this._world.QueryAABB(callback, b2_aabb_tmp);
var fixture = callback.getFixture();
if (fixture) {
return fixture.collider;
}
return null;
},
/**
* !#en
* Test which colliders intersect the given world rect
* !#zh
* 获取与给定世界坐标系矩形相交的碰撞体
* @method testAABB
* @param {Rect} rect - the world rect
* @return {[PhysicsCollider]}
*/
testAABB: function (rect) {
b2_aabb_tmp.lowerBound.x = rect.xMin/PTM_RATIO;
b2_aabb_tmp.lowerBound.y = rect.yMin/PTM_RATIO;
b2_aabb_tmp.upperBound.x = rect.xMax/PTM_RATIO;
b2_aabb_tmp.upperBound.y = rect.yMax/PTM_RATIO;
var callback = this._aabbQueryCallback;
callback.init();
this._world.QueryAABB(callback, b2_aabb_tmp);
var fixtures = callback.getFixtures();
var colliders = fixtures.map(function (fixture) {
return fixture.collider;
});
return colliders;
},
/**
* !#en
* Raycast the world for all colliders in the path of the ray.
* The raycast ignores colliders that contain the starting point.
* !#zh
* 检测哪些碰撞体在给定射线的路径上,射线检测将忽略包含起始点的碰撞体。
* @method rayCast
* @param {Vec2} p1 - start point of the raycast
* @param {Vec2} p2 - end point of the raycast
* @param {RayCastType} type - optional, default is RayCastType.Closest
* @return {[PhysicsRayCastResult]}
*/
rayCast: function (p1, p2, type) {
if (p1.equals(p2)) {
return [];
}
type = type || RayCastType.Closest;
b2_vec2_tmp1.x = p1.x/PTM_RATIO;
b2_vec2_tmp1.y = p1.y/PTM_RATIO;
b2_vec2_tmp2.x = p2.x/PTM_RATIO;
b2_vec2_tmp2.y = p2.y/PTM_RATIO;
var callback = this._raycastQueryCallback;
callback.init(type);
this._world.RayCast(callback, b2_vec2_tmp1, b2_vec2_tmp2);
var fixtures = callback.getFixtures();
if (fixtures.length > 0) {
var points = callback.getPoints();
var normals = callback.getNormals();
var fractions = callback.getFractions();
var results = [];
for (var i = 0, l = fixtures.length; i < l; i++) {
var fixture = fixtures[i];
var collider = fixture.collider;
if (type === RayCastType.AllClosest) {
var result = results.find(function(result) {
return result.collider === collider;
});
if (result) {
if (fractions[i] < result.fraction) {
result.fixtureIndex = collider._getFixtureIndex(fixture);
result.point.x = points[i].x*PTM_RATIO;
result.point.y = points[i].y*PTM_RATIO;
result.normal.x = normals[i].x;
result.normal.y = normals[i].y;
result.fraction = fractions[i];
}
continue;
}
}
results.push({
collider: collider,
fixtureIndex: collider._getFixtureIndex(fixture),
point: cc.v2(points[i].x*PTM_RATIO, points[i].y*PTM_RATIO),
normal: cc.v2(normals[i]),
fraction: fractions[i]
});
}
return results;
}
return [];
},
syncPosition: function () {
var bodies = this._bodies;
for (var i = 0; i < bodies.length; i++) {
bodies[i].syncPosition();
}
},
syncRotation: function () {
var bodies = this._bodies;
for (var i = 0; i < bodies.length; i++) {
bodies[i].syncRotation();
}
},
_registerContactFixture: function (fixture) {
this._contactListener.registerContactFixture(fixture);
},
_unregisterContactFixture: function (fixture) {
this._contactListener.unregisterContactFixture(fixture);
},
_addBody: function (body, bodyDef) {
var world = this._world;
var node = body.node;
if (!world || !node) return;
body._b2Body = world.CreateBody(bodyDef);
body._b2Body.body = body;
this._bodies.push(body);
},
_removeBody: function (body) {
var world = this._world;
if (!world) return;
body._b2Body.body = null;
world.DestroyBody(body._b2Body);
body._b2Body = null;
cc.js.array.remove(this._bodies, body);
},
_addJoint (joint, jointDef) {
let b2joint = this._world.CreateJoint(jointDef);
if (!b2joint) return;
b2joint._joint = joint;
joint._joint = b2joint;
this._joints.push(joint);
},
_removeJoint (joint) {
if (joint._isValid()) {
this._world.DestroyJoint(joint._joint);
}
if (joint._joint) {
joint._joint._joint = null;
}
cc.js.array.remove(this._joints, joint);
},
_initCallback: function () {
if (!this._world) {
cc.warn('Please init PhysicsManager first');
return;
}
if (this._contactListener) return;
var listener = new cc.PhysicsContactListener();
listener.setBeginContact(this._onBeginContact);
listener.setEndContact(this._onEndContact);
listener.setPreSolve(this._onPreSolve);
listener.setPostSolve(this._onPostSolve);
this._world.SetContactListener(listener);
this._contactListener = listener;
this._aabbQueryCallback = new cc.PhysicsAABBQueryCallback();
this._raycastQueryCallback = new cc.PhysicsRayCastCallback();
},
_init: function () {
this.enabled = true;
this.debugDrawFlags = DrawBits.e_shapeBit;
},
_getWorld: function () {
return this._world;
},
_syncNode: function () {
var bodies = this._bodies;
for (var i = 0, l = bodies.length; i < l; i++) {
var body = bodies[i];
var node = body.node;
var b2body = body._b2Body;
var pos = b2body.GetPosition();
vec2_tmp.x = pos.x * PTM_RATIO;
vec2_tmp.y = pos.y * PTM_RATIO;
var angle = b2body.GetAngle() * PHYSICS_ANGLE_TO_ANGLE;
// When node's parent is not scene, convert position and rotation.
if (node.parent.parent !== null) {
vec2_tmp = node.parent.convertToNodeSpaceAR( vec2_tmp );
angle = convertToNodeRotation( node.parent, angle );
}
let tempMask = node._eventMask;
node._eventMask = 0;
// sync position
node.position = vec2_tmp;
// sync rotation
node.angle = -angle;
node._eventMask = tempMask;
if (body.type === BodyType.Animated) {
body.resetVelocity();
}
}
},
_onBeginContact: function (b2contact) {
var c = cc.PhysicsContact.get(b2contact);
c.emit(ContactType.BEGIN_CONTACT);
},
_onEndContact: function (b2contact) {
var c = b2contact._contact;
if (!c) {
return;
}
c.emit(ContactType.END_CONTACT);
cc.PhysicsContact.put(b2contact);
},
_onPreSolve: function (b2contact) {
var c = b2contact._contact;
if (!c) {
return;
}
c.emit(ContactType.PRE_SOLVE);
},
_onPostSolve: function (b2contact, impulse) {
var c = b2contact._contact;
if (!c) {
return;
}
// impulse only survive during post sole callback
c._impulse = impulse;
c.emit(ContactType.POST_SOLVE);
c._impulse = null;
},
_checkDebugDrawValid () {
if (!this._debugDrawer || !this._debugDrawer.isValid) {
let node = new cc.Node('PHYSICS_MANAGER_DEBUG_DRAW');
node.zIndex = cc.macro.MAX_ZINDEX;
cc.game.addPersistRootNode(node);
this._debugDrawer = node.addComponent(cc.Graphics);
let debugDraw = new DebugDraw(this._debugDrawer);
debugDraw.SetFlags(this.debugDrawFlags);
this._world.SetDebugDraw(debugDraw);
}
}
});
/**
* !#en
* Enabled the physics manager?
* !#zh
* 指定是否启用物理系统?
* @property {Boolean} enabled
* @default false
*/
cc.js.getset(PhysicsManager.prototype, 'enabled',
function () {
return this._enabled;
},
function (value) {
if (CC_EDITOR) return;
if (value && !this._world) {
var world = new b2.World( new b2.Vec2(0, -10) );
world.SetAllowSleeping(true);
this._world = world;
this._initCallback();
}
this._enabled = value;
}
);
/**
* !#en
* Debug draw flags.
* !#zh
* 设置调试绘制标志
* @property {Number} debugDrawFlags
* @default 0
* @example
* // enable all debug draw info
* var Bits = cc.PhysicsManager.DrawBits;
* cc.director.getPhysicsManager().debugDrawFlags = Bits.e_aabbBit |
Bits.e_pairBit |
Bits.e_centerOfMassBit |
Bits.e_jointBit |
Bits.e_shapeBit;
* // disable debug draw info
* cc.director.getPhysicsManager().debugDrawFlags = 0;
*/
cc.js.getset(PhysicsManager.prototype, 'debugDrawFlags',
function () {
return this._debugDrawFlags;
},
function (value) {
if (CC_EDITOR) return;
if (value && !this._debugDrawFlags) {
if (this._debugDrawer && this._debugDrawer.node) this._debugDrawer.node.active = true;
}
else if (!value && this._debugDrawFlags) {
if (this._debugDrawer && this._debugDrawer.node) this._debugDrawer.node.active = false;
}
if (value) {
this._checkDebugDrawValid();
this._world.m_debugDraw.SetFlags(value);
}
this._debugDrawFlags = value;
if (value) {
this._checkDebugDrawValid();
this._world.m_debugDraw.SetFlags(value);
}
}
);
/**
* !#en
* The physics world gravity.
* !#zh
* 物理世界重力值
* @property {Vec2} gravity
*/
cc.js.getset(PhysicsManager.prototype, 'gravity',
function () {
if (this._world) {
var g = this._world.GetGravity();
return cc.v2(g.x*PTM_RATIO, g.y*PTM_RATIO);
}
return cc.v2();
},
function (value) {
if (this._world) {
this._world.SetGravity(new b2.Vec2(value.x/PTM_RATIO, value.y/PTM_RATIO));
}
}
);
cc.PhysicsManager = module.exports = PhysicsManager;
/**
* !#en
* The draw bits for drawing physics debug information.<br>
* example:<br>
* ```js
* cc.director.getPhysicsManager().debugDrawFlags =
* // cc.PhysicsManager.DrawBits.e_aabbBit |
* // cc.PhysicsManager.DrawBits.e_pairBit |
* // cc.PhysicsManager.DrawBits.e_centerOfMassBit |
* cc.PhysicsManager.DrawBits.e_jointBit |
* cc.PhysicsManager.DrawBits.e_shapeBit;
* ```
* !#zh
* 指定物理系统需要绘制哪些调试信息。<br>
* example:<br>
* ```js
* cc.director.getPhysicsManager().debugDrawFlags =
* // cc.PhysicsManager.DrawBits.e_aabbBit |
* // cc.PhysicsManager.DrawBits.e_pairBit |
* // cc.PhysicsManager.DrawBits.e_centerOfMassBit |
* cc.PhysicsManager.DrawBits.e_jointBit |
* cc.PhysicsManager.DrawBits.e_shapeBit;
* ```
* @enum PhysicsManager.DrawBits
* @static
*/
/**
* !#en
* Draw bounding boxes
* !#zh
* 绘制包围盒
* @property {Number} e_aabbBit
* @static
*/
/**
* !#en
* Draw joint connections
* !#zh
* 绘制关节链接信息
* @property {Number} e_jointBit
* @static
*/
/**
* !#en
* Draw shapes
* !#zh
* 绘制形状
* @property {Number} e_shapeBit
* @static
*/
/**
* @class PhysicsRayCastResult
*/
/**
* !#en
* The PhysicsCollider which intersects with the raycast
* !#zh
* 与射线相交的碰撞体
* @property {PhysicsCollider} collider
*/
/**
* !#en
* The intersection point
* !#zh
* 射线与碰撞体相交的点
* @property {Vec2} point
*/
/**
* !#en
* The normal vector at the point of intersection
* !#zh
* 射线与碰撞体相交的点的法向量
* @property {Vec2} normal
*/
/**
* !#en
* The fraction of the raycast path at the point of intersection
* !#zh
* 射线与碰撞体相交的点占射线长度的分数
* @property {Number} fraction
*/

View File

@@ -0,0 +1,134 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var ContactType = {
BEGIN_CONTACT: 'begin-contact',
END_CONTACT: 'end-contact',
PRE_SOLVE: 'pre-solve',
POST_SOLVE: 'post-solve'
};
/**
* !#en Enum for RigidBodyType.
* !#zh 刚体类型
* @enum RigidBodyType
*/
var BodyType = cc.Enum({
/**
* !#en
* zero mass, zero velocity, may be manually moved.
* !#zh
* 零质量,零速度,可以手动移动。
* @property {Number} Static
*/
Static: 0,
/**
* !#en
* zero mass, non-zero velocity set by user.
* !#zh
* 零质量,可以被设置速度。
* @property {Number} Kinematic
*/
Kinematic: 1,
/**
* !#en
* positive mass, non-zero velocity determined by forces.
* !#zh
* 有质量,可以设置速度,力等。
* @property {Number} Dynamic
*/
Dynamic: 2,
/**
* !#en
* An extension of Kinematic type, can be animated by Animation.
* !#zh
* Kinematic 类型的扩展,可以被动画控制动画效果。
* @property {Number} Animated
*/
Animated: 3
});
cc.RigidBodyType = BodyType;
/**
* !#en Enum for RayCastType.
* !#zh 射线检测类型
* @enum RayCastType
*/
var RayCastType = cc.Enum({
/**
* !#en
* Detects closest collider on the raycast path.
* !#zh
* 检测射线路径上最近的碰撞体
* @property {Number} Closest
*/
Closest: 0,
/**
* !#en
* Detects any collider on the raycast path.
* Once detects a collider, will stop the searching process.
* !#zh
* 检测射线路径上任意的碰撞体。
* 一旦检测到任何碰撞体,将立刻结束检测其他的碰撞体。
* @property {Number} Any
*/
Any: 1,
/**
* !#en
* Detects all colliders on the raycast path.
* One collider may return several collision points(because one collider may have several fixtures,
* one fixture will return one point, the point may inside collider), AllClosest will return the closest one.
* !#zh
* 检测射线路径上所有的碰撞体。
* 同一个碰撞体上有可能会返回多个碰撞点(因为一个碰撞体可能由多个夹具组成,每一个夹具会返回一个碰撞点,碰撞点有可能在碰撞体内部)AllClosest 删选同一个碰撞体上最近的哪一个碰撞点。
* @property {Number} AllClosest
*/
AllClosest: 2,
/**
* !#en
* Detects all colliders on the raycast path.
* One collider may return several collision points, All will return all these points.
* !#zh
* 检测射线路径上所有的碰撞体。
* 同一个碰撞体上有可能会返回多个碰撞点All 将返回所有这些碰撞点。
* @property {Number} All
*/
All: 3
});
cc.RayCastType = RayCastType;
module.exports = {
BodyType: BodyType,
ContactType: ContactType,
RayCastType: RayCastType,
DrawBits: b2.DrawFlags,
PTM_RATIO: 32,
ANGLE_TO_PHYSICS_ANGLE: -Math.PI / 180,
PHYSICS_ANGLE_TO_ANGLE: -180 / Math.PI,
};

View File

@@ -0,0 +1,344 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
// http://answers.unity3d.com/questions/977416/2d-polygon-convex-decomposition-code.html
/// <summary>
/// This class is took from the "FarseerUnity" physics engine, which uses Mark Bayazit's decomposition algorithm.
/// I also have to make it work with self-intersecting polygons, so I'll use another different algorithm to decompose a self-intersecting polygon into several simple polygons,
/// and then I would decompose each of them into convex polygons.
/// </summary>
//From phed rev 36
/// <summary>
/// Convex decomposition algorithm created by Mark Bayazit (http://mnbayazit.com/)
/// For more information about this algorithm, see http://mnbayazit.com/406/bayazit
/// </summary>
function At(i, vertices) {
var s = vertices.length;
return vertices[i < 0 ? s - (-i % s) : i % s];
}
function Copy(i, j, vertices) {
var p = [];
while (j < i) j += vertices.length;
//p.reserve(j - i + 1);
for (; i <= j; ++i)
{
p.push(At(i, vertices));
}
return p;
}
/// <summary>
/// Decompose the polygon into several smaller non-concave polygon.
/// If the polygon is already convex, it will return the original polygon, unless it is over Settings.MaxPolygonVertices.
/// Precondition: Counter Clockwise polygon
/// </summary>
/// <param name="vertices"></param>
/// <returns></returns>
function ConvexPartition(vertices) {
//We force it to CCW as it is a precondition in this algorithm.
ForceCounterClockWise (vertices);
var list = [];
var d, lowerDist, upperDist;
var p;
var lowerInt = cc.v2();
var upperInt = cc.v2(); // intersection points
var lowerIndex = 0, upperIndex = 0;
var lowerPoly, upperPoly;
for (var i = 0; i < vertices.length; ++i) {
if (Reflex(i, vertices)) {
lowerDist = upperDist = 10e7; // std::numeric_limits<qreal>::max();
for (var j = 0; j < vertices.length; ++j) {
// if line intersects with an edge
if (Left(At(i - 1, vertices), At(i, vertices), At(j, vertices)) &&
RightOn(At(i - 1, vertices), At(i, vertices), At(j - 1, vertices))) {
// find the povar of intersection
p = LineIntersect(At(i - 1, vertices), At(i, vertices), At(j, vertices),
At(j - 1, vertices));
if (Right(At(i + 1, vertices), At(i, vertices), p)) {
// make sure it's inside the poly
d = SquareDist(At(i, vertices), p);
if (d < lowerDist) {
// keep only the closest intersection
lowerDist = d;
lowerInt = p;
lowerIndex = j;
}
}
}
if (Left(At(i + 1, vertices), At(i, vertices), At(j + 1, vertices)) &&
RightOn(At(i + 1, vertices), At(i, vertices), At(j, vertices))) {
p = LineIntersect(At(i + 1, vertices), At(i, vertices), At(j, vertices),
At(j + 1, vertices));
if (Left(At(i - 1, vertices), At(i, vertices), p)) {
d = SquareDist(At(i, vertices), p);
if (d < upperDist) {
upperDist = d;
upperIndex = j;
upperInt = p;
}
}
}
}
// if there are no vertices to connect to, choose a povar in the middle
if (lowerIndex == (upperIndex + 1) % vertices.length) {
var sp = lowerInt.add(upperInt).div(2);
lowerPoly = Copy(i, upperIndex, vertices);
lowerPoly.push(sp);
upperPoly = Copy(lowerIndex, i, vertices);
upperPoly.push(sp);
}
else {
var highestScore = 0, bestIndex = lowerIndex;
while (upperIndex < lowerIndex) {
upperIndex += vertices.length;
}
for (var j = lowerIndex; j <= upperIndex; ++j) {
if (CanSee(i, j, vertices)) {
var score = 1 / (SquareDist(At(i, vertices), At(j, vertices)) + 1);
if (Reflex(j, vertices)) {
if (RightOn(At(j - 1, vertices), At(j, vertices), At(i, vertices)) &&
LeftOn(At(j + 1, vertices), At(j, vertices), At(i, vertices))) {
score += 3;
}
else {
score += 2;
}
}
else {
score += 1;
}
if (score > highestScore) {
bestIndex = j;
highestScore = score;
}
}
}
lowerPoly = Copy(i, bestIndex, vertices);
upperPoly = Copy(bestIndex, i, vertices);
}
list = list.concat( ConvexPartition(lowerPoly) );
list = list.concat( ConvexPartition(upperPoly) );
return list;
}
}
// polygon is already convex
list.push(vertices);
//Remove empty vertice collections
for (var i = list.length - 1; i >= 0; i--)
{
if (list[i].length == 0)
list.splice(i, 0);
}
return list;
}
function CanSee(i, j, vertices) {
if (Reflex(i, vertices)) {
if (LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices)) &&
RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices))) return false;
}
else {
if (RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices)) ||
LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices))) return false;
}
if (Reflex(j, vertices)) {
if (LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices)) &&
RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices))) return false;
}
else {
if (RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices)) ||
LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices))) return false;
}
for (var k = 0; k < vertices.length; ++k) {
if ((k + 1) % vertices.length == i || k == i || (k + 1) % vertices.length == j || k == j)
{
continue; // ignore incident edges
}
var intersectionPoint = cc.v2();
if (LineIntersect2(At(i, vertices), At(j, vertices), At(k, vertices), At(k + 1, vertices), intersectionPoint))
{
return false;
}
}
return true;
}
// precondition: ccw
function Reflex(i, vertices) {
return Right(i, vertices);
}
function Right(a, b, c) {
if (typeof c === 'undefined') {
var i = a, vertices = b;
a = At(i - 1, vertices);
b = At(i, vertices);
c = At(i + 1, vertices);
}
return Area(a, b, c) < 0;
}
function Left(a, b, c) {
return Area(a, b, c) > 0;
}
function LeftOn(a, b, c) {
return Area(a, b, c) >= 0;
}
function RightOn(a, b, c) {
return Area(a, b, c) <= 0;
}
function SquareDist(a, b) {
var dx = b.x - a.x;
var dy = b.y - a.y;
return dx * dx + dy * dy;
}
//forces counter clock wise order.
function ForceCounterClockWise(vertices) {
if (!IsCounterClockWise(vertices)) {
vertices.reverse();
}
}
function IsCounterClockWise(vertices) {
//We just return true for lines
if (vertices.length < 3)
return true;
return (GetSignedArea(vertices) > 0);
}
//gets the signed area.
function GetSignedArea(vertices) {
var i;
var area = 0;
for (i = 0; i < vertices.length; i++) {
var j = (i + 1) % vertices.length;
area += vertices[i].x * vertices[j].y;
area -= vertices[i].y * vertices[j].x;
}
area /= 2;
return area;
}
//From Mark Bayazit's convex decomposition algorithm
function LineIntersect(p1, p2, q1, q2) {
var i = cc.v2();
var a1 = p2.y - p1.y;
var b1 = p1.x - p2.x;
var c1 = a1 * p1.x + b1 * p1.y;
var a2 = q2.y - q1.y;
var b2 = q1.x - q2.x;
var c2 = a2 * q1.x + b2 * q1.y;
var det = a1 * b2 - a2 * b1;
if (!FloatEquals(det, 0)) {
// lines are not parallel
i.x = (b2 * c1 - b1 * c2) / det;
i.y = (a1 * c2 - a2 * c1) / det;
}
return i;
}
//from Eric Jordan's convex decomposition library, it checks if the lines a0->a1 and b0->b1 cross.
//if they do, intersectionPovar will be filled with the povar of crossing. Grazing lines should not return true.
function LineIntersect2(a0, a1, b0, b1, intersectionPoint) {
if (a0 == b0 || a0 == b1 || a1 == b0 || a1 == b1)
return false;
var x1 = a0.x;
var y1 = a0.y;
var x2 = a1.x;
var y2 = a1.y;
var x3 = b0.x;
var y3 = b0.y;
var x4 = b1.x;
var y4 = b1.y;
//AABB early exit
if (Math.max(x1, x2) < Math.min(x3, x4) || Math.max(x3, x4) < Math.min(x1, x2))
return false;
if (Math.max(y1, y2) < Math.min(y3, y4) || Math.max(y3, y4) < Math.min(y1, y2))
return false;
var ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3));
var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3));
var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
if (Math.abs(denom) < 10e-7) {
//Lines are too close to parallel to call
return false;
}
ua /= denom;
ub /= denom;
if ((0 < ua) && (ua < 1) && (0 < ub) && (ub < 1)) {
intersectionPoint.x = (x1 + ua * (x2 - x1));
intersectionPoint.y = (y1 + ua * (y2 - y1));
return true;
}
return false;
}
function FloatEquals(value1, value2) {
return Math.abs(value1 - value2) <= 10e-7;
}
//returns a positive number if c is to the left of the line going from a to b. Positive number if povar is left, negative if povar is right, and 0 if points are collinear.</returns>
function Area(a, b, c) {
return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y);
}
module.exports = {
ConvexPartition: ConvexPartition,
ForceCounterClockWise: ForceCounterClockWise,
IsCounterClockWise: IsCounterClockWise
};

View File

@@ -0,0 +1,934 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
const NodeEvent = require('../CCNode').EventType;
var PTM_RATIO = require('./CCPhysicsTypes').PTM_RATIO;
var ANGLE_TO_PHYSICS_ANGLE = require('./CCPhysicsTypes').ANGLE_TO_PHYSICS_ANGLE;
var PHYSICS_ANGLE_TO_ANGLE = require('./CCPhysicsTypes').PHYSICS_ANGLE_TO_ANGLE;
var getWorldRotation = require('./utils').getWorldRotation;
var BodyType = require('./CCPhysicsTypes').BodyType;
var tempb2Vec21 = new b2.Vec2();
var tempb2Vec22 = new b2.Vec2();
var VEC2_ZERO = cc.Vec2.ZERO;
/**
* @class RigidBody
* @extends Component
*/
var RigidBody = cc.Class({
name: 'cc.RigidBody',
extends: cc.Component,
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.physics/Rigid Body',
disallowMultiple: true
},
properties: {
_type: BodyType.Dynamic,
_allowSleep: true,
_gravityScale: 1,
_linearDamping: 0,
_angularDamping: 0,
_linearVelocity: cc.v2(0, 0),
_angularVelocity: 0,
_fixedRotation: false,
enabled: {
get: function () {
return this._enabled;
},
set: function () {
cc.warnID(8200);
},
visible: false,
override: true
},
/**
* !#en
* Should enabled contact listener?
* When a collision is trigger, the collision callback will only be called when enabled contact listener.
* !#zh
* 是否启用接触接听器。
* 当 collider 产生碰撞时,只有开启了接触接听器才会调用相应的回调函数
* @property {Boolean} enabledContactListener
* @default false
*/
enabledContactListener: {
default: false,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.enabledContactListener'
},
/**
* !#en
* Collision callback.
* Called when two collider begin to touch.
* !#zh
* 碰撞回调。
* 如果你的脚本中实现了这个函数,那么它将会在两个碰撞体开始接触时被调用。
* @method onBeginContact
* @param {PhysicsContact} contact - contact information
* @param {PhysicsCollider} selfCollider - the collider belong to this rigidbody
* @param {PhysicsCollider} otherCollider - the collider belong to another rigidbody
*/
/**
* !#en
* Collision callback.
* Called when two collider cease to touch.
* !#zh
* 碰撞回调。
* 如果你的脚本中实现了这个函数,那么它将会在两个碰撞体停止接触时被调用。
* @method onEndContact
* @param {PhysicsContact} contact - contact information
* @param {PhysicsCollider} selfCollider - the collider belong to this rigidbody
* @param {PhysicsCollider} otherCollider - the collider belong to another rigidbody
*/
/**
* !#en
* Collision callback.
* This is called when a contact is updated.
* This allows you to inspect a contact before it goes to the solver(e.g. disable contact).
* Note: this is called only for awake bodies.
* Note: this is called even when the number of contact points is zero.
* Note: this is not called for sensors.
* !#zh
* 碰撞回调。
* 如果你的脚本中实现了这个函数,那么它将会在接触更新时被调用。
* 你可以在接触被处理前根据他包含的信息作出相应的处理,比如将这个接触禁用掉。
* 注意:回调只会为醒着的刚体调用。
* 注意:接触点为零的时候也有可能被调用。
* 注意:感知体(sensor)的回调不会被调用。
* @method onPreSolve
* @param {PhysicsContact} contact - contact information
* @param {PhysicsCollider} selfCollider - the collider belong to this rigidbody
* @param {PhysicsCollider} otherCollider - the collider belong to another rigidbody
*/
/**
* !#en
* Collision callback.
* This is called after a contact is updated.
* You can get the impulses from the contact in this callback.
* !#zh
* 碰撞回调。
* 如果你的脚本中实现了这个函数,那么它将会在接触更新完后被调用。
* 你可以在这个回调中从接触信息中获取到冲量信息。
* @method onPostSolve
* @param {PhysicsContact} contact - contact information
* @param {PhysicsCollider} selfCollider - the collider belong to this rigidbody
* @param {PhysicsCollider} otherCollider - the collider belong to another rigidbody
*/
/**
* !#en
* Is this a fast moving body that should be prevented from tunneling through
* other moving bodies?
* Note :
* - All bodies are prevented from tunneling through kinematic and static bodies. This setting is only considered on dynamic bodies.
* - You should use this flag sparingly since it increases processing time.
* !#zh
* 这个刚体是否是一个快速移动的刚体,并且需要禁止穿过其他快速移动的刚体?
* 需要注意的是 :
* - 所有刚体都被禁止从 运动刚体 和 静态刚体 中穿过。此选项只关注于 动态刚体。
* - 应该尽量少的使用此选项,因为它会增加程序处理时间。
* @property {Boolean} bullet
* @default false
*/
bullet: {
default: false,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.bullet'
},
/**
* !#en
* Rigidbody type : Static, Kinematic, Dynamic or Animated.
* !#zh
* 刚体类型: Static, Kinematic, Dynamic or Animated.
* @property {RigidBodyType} type
* @default RigidBodyType.Dynamic
*/
type: {
type: BodyType,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.type',
get: function () {
return this._type;
},
set: function (value) {
this._type = value;
if (this._b2Body) {
if (value === BodyType.Animated) {
this._b2Body.SetType(BodyType.Kinematic);
}
else {
this._b2Body.SetType(value);
}
}
}
},
/**
* !#en
* Set this flag to false if this body should never fall asleep.
* Note that this increases CPU usage.
* !#zh
* 如果此刚体永远都不应该进入睡眠,那么设置这个属性为 false。
* 需要注意这将使 CPU 占用率提高。
* @property {Boolean} allowSleep
* @default true
*/
allowSleep: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.allowSleep',
get: function () {
if (this._b2Body) {
return this._b2Body.IsSleepingAllowed();
}
return this._allowSleep;
},
set: function (value) {
this._allowSleep = value;
if (this._b2Body) {
this._b2Body.SetSleepingAllowed(value);
}
}
},
/**
* !#en
* Scale the gravity applied to this body.
* !#zh
* 缩放应用在此刚体上的重力值
* @property {Number} gravityScale
* @default 1
*/
gravityScale: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.gravityScale',
get: function () {
return this._gravityScale;
},
set: function (value) {
this._gravityScale = value;
if (this._b2Body) {
this._b2Body.SetGravityScale(value);
}
}
},
/**
* !#en
* Linear damping is use to reduce the linear velocity.
* The damping parameter can be larger than 1, but the damping effect becomes sensitive to the
* time step when the damping parameter is large.
* !#zh
* Linear damping 用于衰减刚体的线性速度。衰减系数可以大于 1但是当衰减系数比较大的时候衰减的效果会变得比较敏感。
* @property {Number} linearDamping
* @default 0
*/
linearDamping: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.linearDamping',
get: function () {
return this._linearDamping;
},
set: function (value) {
this._linearDamping = value;
if (this._b2Body) {
this._b2Body.SetLinearDamping(this._linearDamping);
}
}
},
/**
* !#en
* Angular damping is use to reduce the angular velocity. The damping parameter
* can be larger than 1 but the damping effect becomes sensitive to the
* time step when the damping parameter is large.
* !#zh
* Angular damping 用于衰减刚体的角速度。衰减系数可以大于 1但是当衰减系数比较大的时候衰减的效果会变得比较敏感。
* @property {Number} angularDamping
* @default 0
*/
angularDamping: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.angularDamping',
get: function () {
return this._angularDamping;
},
set: function (value) {
this._angularDamping = value;
if (this._b2Body) {
this._b2Body.SetAngularDamping(value);
}
}
},
/**
* !#en
* The linear velocity of the body's origin in world co-ordinates.
* !#zh
* 刚体在世界坐标下的线性速度
* @property {Vec2} linearVelocity
* @default cc.v2(0,0)
*/
linearVelocity: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.linearVelocity',
type: cc.Vec2,
get: function () {
var lv = this._linearVelocity;
if (this._b2Body) {
var velocity = this._b2Body.GetLinearVelocity();
lv.x = velocity.x*PTM_RATIO;
lv.y = velocity.y*PTM_RATIO;
}
return lv;
},
set: function (value) {
this._linearVelocity = value;
var b2body = this._b2Body;
if (b2body) {
var temp = b2body.m_linearVelocity;
temp.Set(value.x/PTM_RATIO, value.y/PTM_RATIO);
b2body.SetLinearVelocity(temp);
}
}
},
/**
* !#en
* The angular velocity of the body.
* !#zh
* 刚体的角速度
* @property {Number} angularVelocity
* @default 0
*/
angularVelocity: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.angularVelocity',
get: function () {
if (this._b2Body) {
return this._b2Body.GetAngularVelocity() * PHYSICS_ANGLE_TO_ANGLE;
}
return this._angularVelocity;
},
set: function (value) {
this._angularVelocity = value;
if (this._b2Body) {
this._b2Body.SetAngularVelocity( value * ANGLE_TO_PHYSICS_ANGLE );
}
}
},
/**
* !#en
* Should this body be prevented from rotating?
* !#zh
* 是否禁止此刚体进行旋转
* @property {Boolean} fixedRotation
* @default false
*/
fixedRotation: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.fixedRotation',
get: function () {
return this._fixedRotation;
},
set: function (value) {
this._fixedRotation = value;
if (this._b2Body) {
this._b2Body.SetFixedRotation(value);
}
}
},
/**
* !#en
* Set the sleep state of the body. A sleeping body has very low CPU cost.(When the rigid body is hit, if the rigid body is in sleep state, it will be immediately awakened.)
* !#zh
* 设置刚体的睡眠状态。 睡眠的刚体具有非常低的 CPU 成本。(当刚体被碰撞到时,如果刚体处于睡眠状态,它会立即被唤醒)
* @property {Boolean} awake
* @default false
*/
awake: {
visible: false,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.awake',
get: function () {
return this._b2Body ? this._b2Body.IsAwake() : false;
},
set: function (value) {
if (this._b2Body) {
this._b2Body.SetAwake( value );
}
}
},
/**
* !#en
* Whether to wake up this rigid body during initialization
* !#zh
* 是否在初始化时唤醒此刚体
* @property {Boolean} awakeOnLoad
* @default true
*/
awakeOnLoad: {
default: true,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.awakeOnLoad',
animatable: false,
},
/**
* !#en
* Set the active state of the body. An inactive body is not
* simulated and cannot be collided with or woken up.
* If body is active, all fixtures will be added to the
* broad-phase.
* If body is inactive, all fixtures will be removed from
* the broad-phase and all contacts will be destroyed.
* Fixtures on an inactive body are implicitly inactive and will
* not participate in collisions, ray-casts, or queries.
* Joints connected to an inactive body are implicitly inactive.
* !#zh
* 设置刚体的激活状态。一个非激活状态下的刚体是不会被模拟和碰撞的,不管它是否处于睡眠状态下。
* 如果刚体处于激活状态下,所有夹具会被添加到 粗测阶段broad-phase
* 如果刚体处于非激活状态下,所有夹具会被从 粗测阶段broad-phase中移除。
* 在非激活状态下的夹具不会参与到碰撞,射线,或者查找中
* 链接到非激活状态下刚体的关节也是非激活的。
* @property {Boolean} active
* @default true
*/
active: {
visible: false,
get: function () {
return this._b2Body ? this._b2Body.IsActive() : false;
},
set: function (value) {
if (this._b2Body) {
this._b2Body.SetActive(value);
}
}
}
},
/**
* !#en
* Converts a given point in the world coordinate system to this rigid body's local coordinate system
* !#zh
* 将一个给定的世界坐标系下的点转换为刚体本地坐标系下的点
* @method getLocalPoint
* @param {Vec2} worldPoint - a point in world coordinates.
* @param {Vec2} out - optional, the receiving point
* @return {Vec2} the corresponding local point relative to the body's origin.
*/
getLocalPoint: function (worldPoint, out) {
out = out || cc.v2();
if (this._b2Body) {
tempb2Vec21.Set(worldPoint.x/PTM_RATIO, worldPoint.y/PTM_RATIO);
var pos = this._b2Body.GetLocalPoint(tempb2Vec21, out);
out.x = pos.x*PTM_RATIO;
out.y = pos.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Converts a given point in this rigid body's local coordinate system to the world coordinate system
* !#zh
* 将一个给定的刚体本地坐标系下的点转换为世界坐标系下的点
* @method getWorldPoint
* @param {Vec2} localPoint - a point in local coordinates.
* @param {Vec2} out - optional, the receiving point
* @return {Vec2} the same point expressed in world coordinates.
*/
getWorldPoint: function (localPoint, out) {
out = out || cc.v2();
if (this._b2Body) {
tempb2Vec21.Set(localPoint.x/PTM_RATIO, localPoint.y/PTM_RATIO);
var pos = this._b2Body.GetWorldPoint(tempb2Vec21, out);
out.x = pos.x*PTM_RATIO;
out.y = pos.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Converts a given vector in this rigid body's local coordinate system to the world coordinate system
* !#zh
* 将一个给定的刚体本地坐标系下的向量转换为世界坐标系下的向量
* @method getWorldVector
* @param {Vec2} localVector - a vector in world coordinates.
* @param {Vec2} out - optional, the receiving vector
* @return {Vec2} the same vector expressed in local coordinates.
*/
getWorldVector: function (localVector, out) {
out = out || cc.v2();
if (this._b2Body) {
tempb2Vec21.Set(localVector.x/PTM_RATIO, localVector.y/PTM_RATIO);
var vector = this._b2Body.GetWorldVector(tempb2Vec21, out);
out.x = vector.x*PTM_RATIO;
out.y = vector.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Converts a given vector in the world coordinate system to this rigid body's local coordinate system
* !#zh
* 将一个给定的世界坐标系下的向量转换为刚体本地坐标系下的向量
* @method getLocalVector
* @param {Vec2} worldVector - a vector in world coordinates.
* @param {Vec2} out - optional, the receiving vector
* @return {Vec2} the corresponding local vector relative to the body's origin.
*/
getLocalVector: function (worldVector, out) {
out = out || cc.v2();
if (this._b2Body) {
tempb2Vec21.Set(worldVector.x/PTM_RATIO, worldVector.y/PTM_RATIO);
var vector = this._b2Body.GetLocalVector(tempb2Vec21, out);
out.x = vector.x*PTM_RATIO;
out.y = vector.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Get the world body origin position.
* !#zh
* 获取刚体世界坐标系下的原点值
* @method getWorldPosition
* @param {Vec2} out - optional, the receiving point
* @return {Vec2} the world position of the body's origin.
*/
getWorldPosition: function (out) {
out = out || cc.v2();
if (this._b2Body) {
var pos = this._b2Body.GetPosition();
out.x = pos.x*PTM_RATIO;
out.y = pos.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Get the world body rotation angle.
* !#zh
* 获取刚体世界坐标系下的旋转值。
* @method getWorldRotation
* @return {Number} the current world rotation angle.
*/
getWorldRotation: function () {
if (this._b2Body) {
return this._b2Body.GetAngle() * PHYSICS_ANGLE_TO_ANGLE;
}
return 0;
},
/**
* !#en
* Get the local position of the center of mass.
* !#zh
* 获取刚体本地坐标系下的质心
* @method getLocalCenter
* @return {Vec2} the local position of the center of mass.
*/
getLocalCenter: function (out) {
out = out || cc.v2();
if (this._b2Body) {
var pos = this._b2Body.GetLocalCenter();
out.x = pos.x*PTM_RATIO;
out.y = pos.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Get the world position of the center of mass.
* !#zh
* 获取刚体世界坐标系下的质心
* @method getWorldCenter
* @return {Vec2} the world position of the center of mass.
*/
getWorldCenter: function (out) {
out = out || cc.v2();
if (this._b2Body) {
var pos = this._b2Body.GetWorldCenter();
out.x = pos.x*PTM_RATIO;
out.y = pos.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Get the world linear velocity of a world point attached to this body.
* !#zh
* 获取刚体上指定点的线性速度
* @method getLinearVelocityFromWorldPoint
* @param {Vec2} worldPoint - a point in world coordinates.
* @param {Vec2} out - optional, the receiving point
* @return {Vec2} the world velocity of a point.
*/
getLinearVelocityFromWorldPoint: function (worldPoint, out) {
out = out || cc.v2();
if (this._b2Body) {
tempb2Vec21.Set(worldPoint.x/PTM_RATIO, worldPoint.y/PTM_RATIO);
var velocity = this._b2Body.GetLinearVelocityFromWorldPoint(tempb2Vec21, out);
out.x = velocity.x*PTM_RATIO;
out.y = velocity.y*PTM_RATIO;
}
return out;
},
/**
* !#en
* Get total mass of the body.
* !#zh
* 获取刚体的质量。
* @method getMass
* @return {Number} the total mass of the body.
*/
getMass: function () {
return this._b2Body ? this._b2Body.GetMass() : 0;
},
/**
* !#en
* Get the rotational inertia of the body about the local origin.
* !#zh
* 获取刚体本地坐标系下原点的旋转惯性
* @method getInertia
* @return {Number} the rotational inertia, usually in kg-m^2.
*/
getInertia: function () {
return this._b2Body ? this._b2Body.GetInertia() * PTM_RATIO * PTM_RATIO : 0;
},
/**
* !#en
* Get all the joints connect to the rigidbody.
* !#zh
* 获取链接到此刚体的所有关节
* @method getJointList
* @return {[Joint]} the joint list.
*/
getJointList: function () {
if (!this._b2Body) return [];
var joints = [];
var list = this._b2Body.GetJointList();
if (!list) return [];
joints.push(list.joint._joint);
// find prev joint
var prev = list.prev;
while (prev) {
joints.push(prev.joint._joint);
prev = prev.prev;
}
// find next joint
var next = list.next;
while (next) {
joints.push(next.joint._joint);
next = next.next;
}
return joints;
},
/**
* !#en
* Apply a force at a world point. If the force is not
* applied at the center of mass, it will generate a torque and
* affect the angular velocity.
* !#zh
* 施加一个力到刚体上的一个点。如果力没有施加到刚体的质心上,还会产生一个扭矩并且影响到角速度。
* @method applyForce
* @param {Vec2} force - the world force vector.
* @param {Vec2} point - the world position.
* @param {Boolean} wake - also wake up the body.
*/
applyForce: function (force, point, wake) {
if (this._b2Body) {
tempb2Vec21.Set(force.x/PTM_RATIO, force.y/PTM_RATIO);
tempb2Vec22.Set(point.x/PTM_RATIO, point.y/PTM_RATIO);
this._b2Body.ApplyForce(tempb2Vec21, tempb2Vec22, wake);
}
},
/**
* !#en
* Apply a force to the center of mass.
* !#zh
* 施加一个力到刚体上的质心上。
* @method applyForceToCenter
* @param {Vec2} force - the world force vector.
* @param {Boolean} wake - also wake up the body.
*/
applyForceToCenter: function (force, wake) {
if (this._b2Body) {
tempb2Vec21.Set(force.x/PTM_RATIO, force.y/PTM_RATIO);
this._b2Body.ApplyForceToCenter(tempb2Vec21, wake);
}
},
/**
* !#en
* Apply a torque. This affects the angular velocity.
* !#zh
* 施加一个扭矩力,将影响刚体的角速度
* @method applyTorque
* @param {Number} torque - about the z-axis (out of the screen), usually in N-m.
* @param {Boolean} wake - also wake up the body
*/
applyTorque: function (torque, wake) {
if (this._b2Body) {
this._b2Body.ApplyTorque(torque/PTM_RATIO, wake);
}
},
/**
* !#en
* Apply a impulse at a world point, This immediately modifies the velocity.
* If the impulse is not applied at the center of mass, it will generate a torque and
* affect the angular velocity.
* !#zh
* 施加冲量到刚体上的一个点,将立即改变刚体的线性速度。
* 如果冲量施加到的点不是刚体的质心,那么将产生一个扭矩并影响刚体的角速度。
* @method applyLinearImpulse
* @param {Vec2} impulse - the world impulse vector, usually in N-seconds or kg-m/s.
* @param {Vec2} point - the world position
* @param {Boolean} wake - alse wake up the body
*/
applyLinearImpulse: function (impulse, point, wake) {
if (this._b2Body) {
tempb2Vec21.Set(impulse.x/PTM_RATIO, impulse.y/PTM_RATIO);
tempb2Vec22.Set(point.x/PTM_RATIO, point.y/PTM_RATIO);
this._b2Body.ApplyLinearImpulse(tempb2Vec21, tempb2Vec22, wake);
}
},
/**
* !#en
* Apply an angular impulse.
* !#zh
* 施加一个角速度冲量。
* @method applyAngularImpulse
* @param {Number} impulse - the angular impulse in units of kg*m*m/s
* @param {Boolean} wake - also wake up the body
*/
applyAngularImpulse: function (impulse, wake) {
if (this._b2Body) {
this._b2Body.ApplyAngularImpulse(impulse/PTM_RATIO/PTM_RATIO, wake);
}
},
/**
* !#en
* Synchronize node's world position to box2d rigidbody's position.
* If enableAnimated is true and rigidbody's type is Animated type,
* will set linear velocity instead of directly set rigidbody's position.
* !#zh
* 同步节点的世界坐标到 box2d 刚体的坐标上。
* 如果 enableAnimated 是 true并且刚体的类型是 Animated ,那么将设置刚体的线性速度来代替直接设置刚体的位置。
* @method syncPosition
* @param {Boolean} enableAnimated
*/
syncPosition: function (enableAnimated) {
var b2body = this._b2Body;
if (!b2body) return;
var pos = this.node.convertToWorldSpaceAR(VEC2_ZERO);
var temp;
if (this.type === BodyType.Animated) {
temp = b2body.GetLinearVelocity();
}
else {
temp = b2body.GetPosition();
}
temp.x = pos.x / PTM_RATIO;
temp.y = pos.y / PTM_RATIO;
if (this.type === BodyType.Animated && enableAnimated) {
var b2Pos = b2body.GetPosition();
var timeStep = cc.game.config['frameRate'];
temp.x = (temp.x - b2Pos.x)*timeStep;
temp.y = (temp.y - b2Pos.y)*timeStep;
b2body.SetAwake(true);
b2body.SetLinearVelocity(temp);
}
else {
b2body.SetTransformVec(temp, b2body.GetAngle());
}
},
/**
* !#en
* Synchronize node's world angle to box2d rigidbody's angle.
* If enableAnimated is true and rigidbody's type is Animated type,
* will set angular velocity instead of directly set rigidbody's angle.
* !#zh
* 同步节点的世界旋转角度值到 box2d 刚体的旋转值上。
* 如果 enableAnimated 是 true并且刚体的类型是 Animated ,那么将设置刚体的角速度来代替直接设置刚体的角度。
* @method syncRotation
* @param {Boolean} enableAnimated
*/
syncRotation: function (enableAnimated) {
var b2body = this._b2Body;
if (!b2body) return;
var rotation = ANGLE_TO_PHYSICS_ANGLE * getWorldRotation(this.node);
if (this.type === BodyType.Animated && enableAnimated) {
var b2Rotation = b2body.GetAngle();
var timeStep = cc.game.config['frameRate'];
b2body.SetAwake(true);
b2body.SetAngularVelocity((rotation - b2Rotation)*timeStep);
}
else {
b2body.SetTransformVec(b2body.GetPosition(), rotation);
}
},
resetVelocity: function () {
var b2body = this._b2Body;
if (!b2body) return;
var temp = b2body.m_linearVelocity;
temp.Set(0, 0);
b2body.SetLinearVelocity(temp);
b2body.SetAngularVelocity(0);
},
onEnable: function () {
this._init();
},
onDisable: function () {
this._destroy();
},
_registerNodeEvents: function () {
var node = this.node;
node.on(NodeEvent.POSITION_CHANGED, this._onNodePositionChanged, this);
node.on(NodeEvent.ROTATION_CHANGED, this._onNodeRotationChanged, this);
node.on(NodeEvent.SCALE_CHANGED, this._onNodeScaleChanged, this);
},
_unregisterNodeEvents: function () {
var node = this.node;
node.off(NodeEvent.POSITION_CHANGED, this._onNodePositionChanged, this);
node.off(NodeEvent.ROTATION_CHANGED, this._onNodeRotationChanged, this);
node.off(NodeEvent.SCALE_CHANGED, this._onNodeScaleChanged, this);
},
_onNodePositionChanged: function () {
this.syncPosition(true);
},
_onNodeRotationChanged: function (event) {
this.syncRotation(true);
},
_onNodeScaleChanged: function (event) {
if (this._b2Body) {
var colliders = this.getComponents(cc.PhysicsCollider);
for (var i = 0; i < colliders.length; i++) {
colliders[i].apply();
}
}
},
_init: function () {
cc.director.getPhysicsManager().pushDelayEvent(this, '__init', []);
},
_destroy: function () {
cc.director.getPhysicsManager().pushDelayEvent(this, '__destroy', []);
},
__init: function () {
if (this._inited) return;
this._registerNodeEvents();
var bodyDef = new b2.BodyDef();
if (this.type === BodyType.Animated) {
bodyDef.type = BodyType.Kinematic;
}
else {
bodyDef.type = this.type;
}
bodyDef.allowSleep = this.allowSleep;
bodyDef.gravityScale = this.gravityScale;
bodyDef.linearDamping = this.linearDamping;
bodyDef.angularDamping = this.angularDamping;
var linearVelocity = this.linearVelocity;
bodyDef.linearVelocity = new b2.Vec2(linearVelocity.x/PTM_RATIO, linearVelocity.y/PTM_RATIO);
bodyDef.angularVelocity = this.angularVelocity * ANGLE_TO_PHYSICS_ANGLE;
bodyDef.fixedRotation = this.fixedRotation;
bodyDef.bullet = this.bullet;
var node = this.node;
var pos = node.convertToWorldSpaceAR(VEC2_ZERO);
bodyDef.position = new b2.Vec2(pos.x / PTM_RATIO, pos.y / PTM_RATIO);
bodyDef.angle = -(Math.PI / 180) * getWorldRotation(node);
bodyDef.awake = this.awakeOnLoad;
cc.director.getPhysicsManager()._addBody(this, bodyDef);
this._inited = true;
},
__destroy: function () {
if (!this._inited) return;
cc.director.getPhysicsManager()._removeBody(this);
this._unregisterNodeEvents();
this._inited = false;
},
_getBody: function () {
return this._b2Body;
},
});
cc.RigidBody = module.exports = RigidBody;

View File

@@ -0,0 +1,13 @@
let box2d = require('../../../external/box2d/box2d');
window.b2 = {};
for (var key in box2d) {
if (key.indexOf('b2_') !== -1) {
continue;
}
let newKey = key.replace('b2', '');
b2[newKey] = box2d[key];
}
b2.maxPolygonVertices = 8;

View File

@@ -0,0 +1,58 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
/**
* @class PhysicsBoxCollider
* @extends PhysicsCollider
* @uses Collider.Box
*/
var PhysicsBoxCollider = cc.Class({
name: 'cc.PhysicsBoxCollider',
extends: cc.PhysicsCollider,
mixins: [cc.Collider.Box],
editor: {
menu: CC_EDITOR && 'i18n:MAIN_MENU.component.physics/Collider/Box',
requireComponent: cc.RigidBody
},
_createShape: function (scale) {
var scaleX = Math.abs(scale.x);
var scaleY = Math.abs(scale.y);
var width = this.size.width/2/PTM_RATIO * scaleX;
var height = this.size.height/2/PTM_RATIO * scaleY;
var offsetX = this.offset.x/PTM_RATIO *scaleX;
var offsetY = this.offset.y/PTM_RATIO *scaleY;
var shape = new b2.PolygonShape();
shape.SetAsBox(width, height, new b2.Vec2(offsetX, offsetY), 0);
return shape;
}
});
cc.PhysicsBoxCollider = module.exports = PhysicsBoxCollider;

View File

@@ -0,0 +1,103 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
/**
* @class PhysicsChainCollider
* @extends PolygonCollider
*/
var PhysicsChainCollider = cc.Class({
name: 'cc.PhysicsChainCollider',
extends: cc.PhysicsCollider,
editor: {
menu: CC_EDITOR && 'i18n:MAIN_MENU.component.physics/Collider/Chain',
inspector: CC_EDITOR && 'packages://inspector/inspectors/comps/physics/points-base-collider.js',
requireComponent: cc.RigidBody
},
properties: {
/**
* !#en Whether the chain is loop
* !#zh 链条是否首尾相连
* @property loop
* @type {Boolean}
*/
loop: false,
/**
* !#en Chain points
* !#zh 链条顶点数组
* @property points
* @type {Vec2[]}
*/
points: {
default: function () {
return [cc.v2(-50, 0), cc.v2(50, 0)];
},
type: [cc.Vec2]
},
threshold: {
default: 1,
serializable: false,
visible: false
},
},
_createShape: function (scale) {
var shape = new b2.ChainShape();
var points = this.points;
var vertices = [];
for (var i = 0; i < points.length; i++) {
var p = points[i];
vertices.push( new b2.Vec2(p.x/PTM_RATIO*scale.x, p.y/PTM_RATIO*scale.y) );
}
if (this.loop) {
shape.CreateLoop(vertices, vertices.length);
}
else {
shape.CreateChain(vertices, vertices.length);
}
return shape;
},
resetInEditor: CC_EDITOR && function (didResetToDefault) {
if (didResetToDefault) {
this.resetPointsByContour();
}
},
resetPointsByContour: CC_EDITOR && function () {
var PhysicsUtils = Editor.require('scene://utils/physics');
PhysicsUtils.resetPoints(this, {threshold: this.threshold, loop: this.loop});
}
});
cc.PhysicsChainCollider = module.exports = PhysicsChainCollider;

View File

@@ -0,0 +1,58 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
/**
* @class PhysicsCircleCollider
* @extends PhysicsCollider
* @uses Collider.Circle
*/
var PhysicsCircleCollider = cc.Class({
name: 'cc.PhysicsCircleCollider',
extends: cc.PhysicsCollider,
mixins: [cc.Collider.Circle],
editor: {
menu: CC_EDITOR && 'i18n:MAIN_MENU.component.physics/Collider/Circle',
requireComponent: cc.RigidBody
},
_createShape: function (scale) {
var scaleX = Math.abs(scale.x);
var scaleY = Math.abs(scale.y);
var offsetX = this.offset.x/PTM_RATIO * scaleX;
var offsetY = this.offset.y/PTM_RATIO * scaleY;
var shape = new b2.CircleShape();
shape.m_radius = this.radius / PTM_RATIO * scaleX;
shape.m_p = new b2.Vec2(offsetX, offsetY);
return shape;
}
});
cc.PhysicsCircleCollider = module.exports = PhysicsCircleCollider;

View File

@@ -0,0 +1,305 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var getWorldScale = require('../utils').getWorldScale;
var b2_aabb_tmp = new b2.AABB();
/**
* @class PhysicsCollider
* @extends Collider
*/
var PhysicsCollider = cc.Class({
name: 'cc.PhysicsCollider',
extends: cc.Collider,
ctor: function () {
this._fixtures = [];
this._shapes = [];
this._inited = false;
this._rect = cc.rect();
},
properties: {
_density: 1.0,
_sensor: false,
_friction: 0.2,
_restitution: 0,
/**
* !#en
* The density.
* !#zh
* 密度
* @property {Number} density
* @default 1
*/
density: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.density',
get: function () {
return this._density;
},
set: function (value) {
this._density = value;
}
},
/**
* !#en
* A sensor collider collects contact information but never generates a collision response
* !#zh
* 一个传感器类型的碰撞体会产生碰撞回调,但是不会发生物理碰撞效果。
* @property {Boolean} sensor
* @default false
*/
sensor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.sensor',
get: function () {
return this._sensor;
},
set: function (value) {
this._sensor = value;
}
},
/**
* !#en
* The friction coefficient, usually in the range [0,1].
* !#zh
* 摩擦系数,取值一般在 [0, 1] 之间
* @property {Number} friction
* @default 0.2
*/
friction: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.friction',
get: function () {
return this._friction;
},
set: function (value) {
this._friction = value;
}
},
/**
* !#en
* The restitution (elasticity) usually in the range [0,1].
* !#zh
* 弹性系数,取值一般在 [0, 1]之间
* @property {Number} restitution
* @default 0
*/
restitution: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.restitution',
get: function () {
return this._restitution;
},
set: function (value) {
this._restitution = value;
}
},
/**
* !#en
* Physics collider will find the rigidbody component on the node and set to this property.
* !#zh
* 碰撞体会在初始化时查找节点上是否存在刚体,如果查找成功则赋值到这个属性上。
* @property {RigidBody} body
* @default null
*/
body: {
default: null,
type: cc.RigidBody,
visible: false
}
},
onDisable: function () {
this._destroy();
},
onEnable: function () {
this._init();
},
start: function () {
this._init();
},
_getFixtureIndex: function (fixture) {
return this._fixtures.indexOf(fixture);
},
_init: function () {
cc.director.getPhysicsManager().pushDelayEvent(this, '__init', []);
},
_destroy: function () {
cc.director.getPhysicsManager().pushDelayEvent(this, '__destroy', []);
},
__init: function () {
if (this._inited) return;
var body = this.body || this.getComponent(cc.RigidBody);
if (!body) return;
var innerBody = body._getBody();
if (!innerBody) return;
var node = body.node;
var scale = getWorldScale(node);
this._scale = scale;
var shapes = scale.x === 0 && scale.y === 0 ? [] : this._createShape(scale);
if (!(shapes instanceof Array)) {
shapes = [shapes];
}
var categoryBits = 1 << node.groupIndex;
var maskBits = 0;
var bits = cc.game.collisionMatrix[node.groupIndex];
for (let i = 0; i < bits.length; i++) {
if (!bits[i]) continue;
maskBits |= 1 << i;
}
var filter = {
categoryBits: categoryBits,
maskBits: maskBits,
groupIndex: 0
};
var manager = cc.director.getPhysicsManager();
for (let i = 0; i < shapes.length; i++) {
var shape = shapes[i];
var fixDef = new b2.FixtureDef();
fixDef.density = this.density;
fixDef.isSensor = this.sensor;
fixDef.friction = this.friction;
fixDef.restitution = this.restitution;
fixDef.shape = shape;
fixDef.filter = filter;
var fixture = innerBody.CreateFixture(fixDef);
fixture.collider = this;
if (body.enabledContactListener) {
manager._registerContactFixture(fixture);
}
this._shapes.push(shape);
this._fixtures.push(fixture);
}
this.body = body;
this._inited = true;
},
__destroy: function () {
if (!this._inited) return;
var fixtures = this._fixtures;
var body = this.body._getBody();
var manager = cc.director.getPhysicsManager();
for (var i = fixtures.length-1; i >=0 ; i--) {
var fixture = fixtures[i];
fixture.collider = null;
manager._unregisterContactFixture(fixture);
if (body) {
body.DestroyFixture(fixture);
}
}
this.body = null;
this._fixtures.length = 0;
this._shapes.length = 0;
this._inited = false;
},
_createShape: function () {
},
/**
* !#en
* Apply current changes to collider, this will regenerate inner box2d fixtures.
* !#zh
* 应用当前 collider 中的修改,调用此函数会重新生成内部 box2d 的夹具。
* @method apply
*/
apply: function () {
this._destroy();
this._init();
},
/**
* !#en
* Get the world aabb of the collider
* !#zh
* 获取碰撞体的世界坐标系下的包围盒
* @method getAABB
*/
getAABB: function () {
var MAX = 10e6;
var minX = MAX, minY = MAX;
var maxX = -MAX, maxY = -MAX;
var xf = this.body._getBody().GetTransform();
var fixtures = this._fixtures;
for (var i = 0; i < fixtures.length; i++) {
var shape = fixtures[i].GetShape();
var count = shape.GetChildCount();
for(var j = 0; j < count; j++){
shape.ComputeAABB(b2_aabb_tmp, xf, j);
if (b2_aabb_tmp.lowerBound.x < minX) minX = b2_aabb_tmp.lowerBound.x;
if (b2_aabb_tmp.lowerBound.y < minY) minY = b2_aabb_tmp.lowerBound.y;
if (b2_aabb_tmp.upperBound.x > maxX) maxX = b2_aabb_tmp.upperBound.x;
if (b2_aabb_tmp.upperBound.y > maxY) maxY = b2_aabb_tmp.upperBound.y;
}
}
minX *= PTM_RATIO;
minY *= PTM_RATIO;
maxX *= PTM_RATIO;
maxY *= PTM_RATIO;
var r = this._rect;
r.x = minX;
r.y = minY;
r.width = maxX - minX;
r.height = maxY - minY;
return r;
}
});
cc.PhysicsCollider = module.exports = PhysicsCollider;

View File

@@ -0,0 +1,101 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var PolygonSeparator = require('../CCPolygonSeparator');
/**
* @class PhysicsPolygonCollider
* @extends PhysicsCollider
* @uses Collider.Polygon
*/
var PhysicsPolygonCollider = cc.Class({
name: 'cc.PhysicsPolygonCollider',
extends: cc.PhysicsCollider,
mixins: [cc.Collider.Polygon],
editor: {
menu: CC_EDITOR && 'i18n:MAIN_MENU.component.physics/Collider/Polygon',
inspector: CC_EDITOR && 'packages://inspector/inspectors/comps/physics/points-base-collider.js',
requireComponent: cc.RigidBody
},
_createShape: function (scale) {
var shapes = [];
var points = this.points;
// check if last point equal to first point
if (points.length > 0 && points[0].equals(points[points.length - 1])) {
points.length -= 1;
}
var polys = PolygonSeparator.ConvexPartition(points);
var offset = this.offset;
for (var i = 0; i < polys.length; i++) {
var poly = polys[i];
var shape = null, vertices = [];
var firstVertice = null;
for (var j = 0, l = poly.length; j < l; j++) {
if (!shape) {
shape = new b2.PolygonShape();
}
var p = poly[j];
var x = (p.x + offset.x)/PTM_RATIO*scale.x;
var y = (p.y + offset.y)/PTM_RATIO*scale.y;
var v = new b2.Vec2(x, y);
vertices.push( v );
if (!firstVertice) {
firstVertice = v;
}
if (vertices.length === b2.maxPolygonVertices) {
shape.Set(vertices, vertices.length);
shapes.push(shape);
shape = null;
if (j < l - 1) {
vertices = [firstVertice, vertices[vertices.length - 1]];
}
}
}
if (shape) {
shape.Set(vertices, vertices.length);
shapes.push(shape);
}
}
return shapes;
}
});
cc.PhysicsPolygonCollider = module.exports = PhysicsPolygonCollider;

View File

@@ -0,0 +1,49 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
require('./box2d-adapter');
require('./CCPhysicsManager');
require('./CCRigidBody');
require('./CCPhysicsContact');
require('./collider/CCPhysicsCollider');
require('./collider/CCPhysicsChainCollider');
require('./collider/CCPhysicsCircleCollider');
require('./collider/CCPhysicsBoxCollider');
require('./collider/CCPhysicsPolygonCollider');
require('./joint/CCJoint');
require('./joint/CCDistanceJoint');
require('./joint/CCRevoluteJoint');
require('./joint/CCMouseJoint');
require('./joint/CCMotorJoint');
require('./joint/CCPrismaticJoint');
require('./joint/CCWeldJoint');
require('./joint/CCWheelJoint');
require('./joint/CCRopeJoint');
require('./platform/CCPhysicsContactListner');
require('./platform/CCPhysicsAABBQueryCallback');
require('./platform/CCPhysicsRayCastCallback');

View File

@@ -0,0 +1,128 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
/**
* !#en
* A distance joint constrains two points on two bodies
* to remain at a fixed distance from each other. You can view
* this as a massless, rigid rod.
* !#zh
* 距离关节通过一个固定的长度来约束关节链接的两个刚体。你可以将它想象成一个无质量,坚固的木棍。
* @class DistanceJoint
* @extends Joint
*/
var DistanceJoint = cc.Class({
name: 'cc.DistanceJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.physics/Joint/Distance',
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
},
properties: {
_distance: 1,
_frequency: 0,
_dampingRatio: 0,
/**
* !#en
* The distance separating the two ends of the joint.
* !#zh
* 关节两端的距离
* @property {Number} distance
* @default 1
*/
distance: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.distance',
get: function () {
return this._distance;
},
set: function (value) {
this._distance = value;
if (this._joint) {
this._joint.SetLength(value);
}
}
},
/**
* !#en
* The spring frequency.
* !#zh
* 弹性系数。
* @property {Number} frequency
* @default 0
*/
frequency: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.frequency',
get: function () {
return this._frequency;
},
set: function (value) {
this._frequency = value;
if (this._joint) {
this._joint.SetFrequency(value);
}
}
},
/**
* !#en
* The damping ratio.
* !#zh
* 阻尼,表示关节变形后,恢复到初始状态受到的阻力。
* @property {Number} dampingRatio
*/
dampingRatio: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.dampingRatio',
get: function () {
return this._dampingRatio;
},
set: function (value) {
this._dampingRatio = value;
if (this._joint) {
this._joint.SetDampingRatio(value);
}
}
}
},
_createJointDef: function () {
var def = new b2.DistanceJointDef();
def.localAnchorA = new b2.Vec2(this.anchor.x/PTM_RATIO, this.anchor.y/PTM_RATIO);
def.localAnchorB = new b2.Vec2(this.connectedAnchor.x/PTM_RATIO, this.connectedAnchor.y/PTM_RATIO);
def.length = this.distance/PTM_RATIO;
def.dampingRatio = this.dampingRatio;
def.frequencyHz = this.frequency;
return def;
}
});
cc.DistanceJoint = module.exports = DistanceJoint;

View File

@@ -0,0 +1,233 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
/**
* !#en
* Base class for joints to connect rigidbody.
* !#zh
* 关节类的基类
* @class Joint
* @extends Component
*/
var Joint = cc.Class({
name: 'cc.Joint',
extends: cc.Component,
editor: {
requireComponent: cc.RigidBody
},
properties: {
/**
* !#en
* The anchor of the rigidbody.
* !#zh
* 刚体的锚点。
* @property {Vec2} anchor
* @default cc.v2(0, 0)
*/
anchor: {
default: cc.v2(0, 0),
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.anchor'
},
/**
* !#en
* The anchor of the connected rigidbody.
* !#zh
* 关节另一端刚体的锚点。
* @property {Vec2} connectedAnchor
* @default cc.v2(0, 0)
*/
connectedAnchor: {
default: cc.v2(0, 0),
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.connectedAnchor'
},
/**
* !#en
* The rigidbody to which the other end of the joint is attached.
* !#zh
* 关节另一端链接的刚体
* @property {RigidBody} connectedBody
* @default null
*/
connectedBody: {
default: null,
type: cc.RigidBody,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.connectedBody'
},
/**
* !#en
* Should the two rigid bodies connected with this joint collide with each other?
* !#zh
* 链接到关节上的两个刚体是否应该相互碰撞?
* @property {Boolean} collideConnected
* @default false
*/
collideConnected: {
default: false,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.collideConnected'
}
},
onDisable: function () {
this._destroy();
},
onEnable: function () {
this._init();
},
// need init after body and connected body init
start: function () {
this._init();
},
/**
* !#en
* Apply current changes to joint, this will regenerate inner box2d joint.
* !#zh
* 应用当前关节中的修改,调用此函数会重新生成内部 box2d 的关节。
* @method apply
*/
apply: function () {
this._destroy();
this._init();
},
/**
* !#en
* Get the anchor point on rigidbody in world coordinates.
* !#zh
* 获取刚体世界坐标系下的锚点。
* @method getWorldAnchor
* @return {Vec2}
*/
getWorldAnchor: function () {
if (this._joint) {
var anchor = this._joint.GetAnchorA();
return cc.v2(anchor.x * PTM_RATIO, anchor.y * PTM_RATIO);
}
return cc.Vec2.ZERO;
},
/**
* !#en
* Get the anchor point on connected rigidbody in world coordinates.
* !#zh
* 获取链接刚体世界坐标系下的锚点。
* @method getWorldConnectedAnchor
* @return {Vec2}
*/
getWorldConnectedAnchor: function () {
if (this._joint) {
var anchor = this._joint.GetAnchorB();
return cc.v2(anchor.x * PTM_RATIO, anchor.y * PTM_RATIO);
}
return cc.Vec2.ZERO;
},
/**
* !#en
* Gets the reaction force of the joint.
* !#zh
* 获取关节的反作用力。
* @method getReactionForce
* @param {Number} timeStep - The time to calculate the reaction force for.
* @return {Vec2}
*/
getReactionForce: function (timeStep) {
var out = cc.v2();
if (this._joint) {
return this._joint.GetReactionForce(timeStep, out);
}
return out;
},
/**
* !#en
* Gets the reaction torque of the joint.
* !#zh
* 获取关节的反扭矩。
* @method getReactionTorque
* @param {Number} timeStep - The time to calculate the reaction torque for.
* @return {Number}
*/
getReactionTorque: function (timeStep) {
if (this._joint) {
return this._joint.GetReactionTorque(timeStep);
}
return 0;
},
_init: function () {
cc.director.getPhysicsManager().pushDelayEvent(this, '__init', []);
},
_destroy: function () {
cc.director.getPhysicsManager().pushDelayEvent(this, '__destroy', []);
},
__init: function () {
if (this._inited) return;
this.body = this.getComponent(cc.RigidBody);
if (this._isValid()) {
var def = this._createJointDef();
if (!def) return;
def.bodyA = this.body._getBody();
def.bodyB = this.connectedBody._getBody();
def.collideConnected = this.collideConnected;
cc.director.getPhysicsManager()._addJoint(this, def);
this._inited = true;
}
},
__destroy: function () {
if (!this._inited) return;
cc.director.getPhysicsManager()._removeJoint(this);
this._joint = null;
this._inited = false;
},
_createJointDef: function () {
return null;
},
_isValid: function () {
return this.body && this.body._getBody() &&
this.connectedBody && this.connectedBody._getBody();
}
});
cc.Joint = module.exports = Joint;

View File

@@ -0,0 +1,205 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var ANGLE_TO_PHYSICS_ANGLE = require('../CCPhysicsTypes').ANGLE_TO_PHYSICS_ANGLE;
/**
* !#en
* A motor joint is used to control the relative motion
* between two bodies. A typical usage is to control the movement
* of a dynamic body with respect to the ground.
* !#zh
* 马达关节被用来控制两个刚体间的相对运动。
* 一个典型的例子是用来控制一个动态刚体相对于地面的运动。
* @class MotorJoint
* @extends Joint
*/
var MotorJoint = cc.Class({
name: 'cc.MotorJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.physics/Joint/Motor',
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
},
properties: {
_linearOffset: cc.v2(0, 0),
_angularOffset: 0,
_maxForce: 1,
_maxTorque: 1,
_correctionFactor: 0.3,
/**
* !#en
* The anchor of the rigidbody.
* !#zh
* 刚体的锚点。
* @property {Vec2} anchor
* @default cc.v2(0, 0)
*/
anchor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.anchor',
default: cc.v2(0, 0),
override: true,
visible: false
},
/**
* !#en
* The anchor of the connected rigidbody.
* !#zh
* 关节另一端刚体的锚点。
* @property {Vec2} connectedAnchor
* @default cc.v2(0, 0)
*/
connectedAnchor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.connectedAnchor',
default: cc.v2(0, 0),
override: true,
visible: false
},
/**
* !#en
* The linear offset from connected rigidbody to rigidbody.
* !#zh
* 关节另一端的刚体相对于起始端刚体的位置偏移量
* @property {Vec2} linearOffset
* @default cc.v2(0,0)
*/
linearOffset: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.linearOffset',
get: function () {
return this._linearOffset;
},
set: function (value) {
this._linearOffset = value;
if (this._joint) {
this._joint.SetLinearOffset( new b2.Vec2(value.x/PTM_RATIO, value.y/PTM_RATIO) );
}
}
},
/**
* !#en
* The angular offset from connected rigidbody to rigidbody.
* !#zh
* 关节另一端的刚体相对于起始端刚体的角度偏移量
* @property {Number} angularOffset
* @default 0
*/
angularOffset: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.angularOffset',
get: function () {
return this._angularOffset;
},
set: function (value) {
this._angularOffset = value;
if (this._joint) {
this._joint.SetAngularOffset(value);
}
}
},
/**
* !#en
* The maximum force can be applied to rigidbody.
* !#zh
* 可以应用于刚体的最大的力值
* @property {Number} maxForce
* @default 1
*/
maxForce: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxForce',
get: function () {
return this._maxForce;
},
set: function (value) {
this._maxForce = value;
if (this._joint) {
this._joint.SetMaxForce(value);
}
}
},
/**
* !#en
* The maximum torque can be applied to rigidbody.
* !#zh
* 可以应用于刚体的最大扭矩值
* @property {Number} maxTorque
* @default 1
*/
maxTorque: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxTorque',
get: function () {
return this._maxTorque;
},
set: function (value) {
this._maxTorque = value;
if (this._joint) {
this._joint.SetMaxTorque(value);
}
}
},
/**
* !#en
* The position correction factor in the range [0,1].
* !#zh
* 位置矫正系数,范围为 [0, 1]
* @property {Number} correctionFactor
* @default 0.3
*/
correctionFactor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.correctionFactor',
get: function () {
return this._correctionFactor;
},
set: function (value) {
this._correctionFactor = value;
if (this._joint) {
this._joint.SetCorrectionFactor(value);
}
}
},
},
_createJointDef: function () {
var def = new b2.MotorJointDef();
def.linearOffset = new b2.Vec2(this.linearOffset.x/PTM_RATIO, this.linearOffset.y/PTM_RATIO);
def.angularOffset = this.angularOffset * ANGLE_TO_PHYSICS_ANGLE;
def.maxForce = this.maxForce;
def.maxTorque = this.maxTorque;
def.correctionFactor = this.correctionFactor;
return def;
}
});
cc.MotorJoint = module.exports = MotorJoint;

View File

@@ -0,0 +1,278 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var tempB2Vec2 = new b2.Vec2();
/**
* !#en
* A mouse joint is used to make a point on a body track a
* specified world point. This a soft constraint with a maximum
* force. This allows the constraint to stretch and without
* applying huge forces.
* Mouse Joint will auto register the touch event with the mouse region node,
* and move the choosed rigidbody in touch move event.
* Note : generally mouse joint only used in test bed.
* !#zh
* 鼠标关节用于使刚体上的一个点追踪一个指定的世界坐标系下的位置。
* 鼠标关节可以指定一个最大的力来施加一个柔和的约束。
* 鼠标关节会自动使用 mouse region 节点来注册鼠标事件,并且在触摸移动事件中移动选中的刚体。
* 注意:一般鼠标关节只在测试环境中使用。
* @class MouseJoint
* @extends Joint
*/
var MouseJoint = cc.Class({
name: 'cc.MouseJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
menu: 'i18n:MAIN_MENU.component.physics/Joint/Mouse',
},
properties: {
_target: 1,
_frequency: 5,
_dampingRatio: 0.7,
_maxForce: 0,
connectedBody: {
default: null,
type: cc.RigidBody,
visible: false,
override: true
},
collideConnected: {
default: true,
visible: false,
override: true
},
/**
* !#en
* The anchor of the rigidbody.
* !#zh
* 刚体的锚点。
* @property {Vec2} anchor
* @default cc.v2(0, 0)
*/
anchor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.anchor',
default: cc.v2(0, 0),
override: true,
visible: false
},
/**
* !#en
* The anchor of the connected rigidbody.
* !#zh
* 关节另一端刚体的锚点。
* @property {Vec2} connectedAnchor
* @default cc.v2(0, 0)
*/
connectedAnchor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.connectedAnchor',
default: cc.v2(0, 0),
override: true,
visible: false
},
/**
* !#en
* The node used to register touch evnet.
* If this is null, it will be the joint's node.
* !#zh
* 用于注册触摸事件的节点。
* 如果没有设置这个值,那么将会使用关节的节点来注册事件。
* @property {Node} mouseRegion
* @default null
*/
mouseRegion: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.mouseRegion',
default: null,
type: cc.Node
},
/**
* !#en
* The target point.
* The mouse joint will move choosed rigidbody to target point.
* !#zh
* 目标点,鼠标关节将会移动选中的刚体到指定的目标点
* @property {Vec2} target
*/
target: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.target',
visible: false,
get: function () {
return this._target;
},
set: function (value) {
this._target = value;
if (this._joint) {
tempB2Vec2.x = value.x/PTM_RATIO;
tempB2Vec2.y = value.y/PTM_RATIO;
this._joint.SetTarget(tempB2Vec2);
}
}
},
/**
* !#en
* The spring frequency.
* !#zh
* 弹簧系数。
* @property {Number} frequency
* @default 0
*/
frequency: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.frequency',
get: function () {
return this._frequency;
},
set: function (value) {
this._frequency = value;
if (this._joint) {
this._joint.SetFrequency(value);
}
}
},
/**
* !#en
* The damping ratio.
* !#zh
* 阻尼,表示关节变形后,恢复到初始状态受到的阻力。
* @property {Number} dampingRatio
* @property 0
*/
dampingRatio: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.dampingRatio',
get: function () {
return this._dampingRatio;
},
set: function (value) {
this._dampingRatio = value;
if (this._joint) {
this._joint.SetDampingRatio(value);
}
}
},
/**
* !#en
* The maximum force
* !#zh
* 最大阻力值
* @property {Number} maxForce
* @default 1
*/
maxForce: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxForce',
visible: false,
get: function () {
return this._maxForce;
},
set: function (value) {
this._maxForce = value;
if (this._joint) {
this._joint.SetMaxForce(value);
}
}
},
},
onLoad: function () {
var mouseRegion = this.mouseRegion || this.node;
mouseRegion.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan, this);
mouseRegion.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
mouseRegion.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
mouseRegion.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
},
onEnable: function () {
},
start: function () {
},
onTouchBegan: function (event) {
var manager = cc.director.getPhysicsManager();
var target = this._pressPoint = event.touch.getLocation();
if (cc.Camera && cc.Camera.main) {
target = cc.Camera.main.getScreenToWorldPoint(target);
}
var collider = manager.testPoint( target );
if (!collider) return;
var body = this.connectedBody = collider.body;
body.awake = true;
this.maxForce = 1000 * this.connectedBody.getMass();
this.target = target;
this._init();
},
onTouchMove: function (event) {
this._pressPoint = event.touch.getLocation();
},
onTouchEnd: function (event) {
this._destroy();
this._pressPoint = null;
},
_createJointDef: function () {
var def = new b2.MouseJointDef();
tempB2Vec2.x = this.target.x/PTM_RATIO;
tempB2Vec2.y = this.target.y/PTM_RATIO;
def.target = tempB2Vec2;
def.maxForce = this.maxForce;
def.dampingRatio = this.dampingRatio;
def.frequencyHz = this.frequency;
return def;
},
update: function () {
if (!this._pressPoint || !this._isValid()) {
return;
}
var camera = cc.Camera.findCamera(this.node);
if (camera) {
this.target = camera.getScreenToWorldPoint(this._pressPoint);
}
else {
this.target = this._pressPoint;
}
}
});
cc.MouseJoint = module.exports = MouseJoint;

View File

@@ -0,0 +1,192 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var ANGLE_TO_PHYSICS_ANGLE = require('../CCPhysicsTypes').ANGLE_TO_PHYSICS_ANGLE;
/**
* !#en
* A prismatic joint. This joint provides one degree of freedom: translation
* along an axis fixed in rigidbody. Relative rotation is prevented. You can
* use a joint limit to restrict the range of motion and a joint motor to
* drive the motion or to model joint friction.
* !#zh
* 移动关节指定了只能在一个方向上移动刚体。
* 你可以开启关节限制来设置刚体运行移动的间距,也可以开启马达来使用关节马达驱动刚体的运行。
* @class PrismaticJoint
* @extends Joint
*/
var PrismaticJoint = cc.Class({
name: 'cc.PrismaticJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
menu: 'i18n:MAIN_MENU.component.physics/Joint/PrismaticJoint',
},
properties: {
/**
* !#en
* The local joint axis relative to rigidbody.
* !#zh
* 指定刚体可以移动的方向。
* @property {Vec2} localAxisA
* @default cc.v2(1, 0)
*/
localAxisA: {
default: cc.v2(1, 0),
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.localAxisA'
},
/**
* !#en
* The reference angle.
* !#zh
* 相对角度
* @property {Number} referenceAngle
* @default 0
*/
referenceAngle: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.referenceAngle'
},
/**
* !#en
* Enable joint distance limit?
* !#zh
* 是否开启关节的距离限制?
* @property {Boolean} enableLimit
* @default false
*/
enableLimit: {
default: false,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.enableLimit'
},
/**
* !#en
* Enable joint motor?
* !#zh
* 是否开启关节马达?
* @property {Boolean} enableMotor
* @default false
*/
enableMotor: {
default: false,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.enableMotor'
},
/**
* !#en
* The lower joint limit.
* !#zh
* 刚体能够移动的最小值
* @property {Number} lowerLimit
* @default 0
*/
lowerLimit: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.lowerLimit'
},
/**
* !#en
* The upper joint limit.
* !#zh
* 刚体能够移动的最大值
* @property {Number} upperLimit
* @default 0
*/
upperLimit: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.upperLimit'
},
_maxMotorForce: 0,
_motorSpeed: 0,
/**
* !#en
* The maxium force can be applied to rigidbody to rearch the target motor speed.
* !#zh
* 可以施加到刚体的最大力。
* @property {Number} maxMotorForce
* @default 0
*/
maxMotorForce: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxMotorForce',
get: function () {
return this._maxMotorForce;
},
set: function (value) {
this._maxMotorForce = value;
if (this._joint) {
this._joint.SetMaxMotorForce(value);
}
}
},
/**
* !#en
* The expected motor speed.
* !#zh
* 期望的马达速度。
* @property {Number} motorSpeed
* @default 0
*/
motorSpeed: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.motorSpeed',
get: function () {
return this._motorSpeed;
},
set: function (value) {
this._motorSpeed = value;
if (this._joint) {
this._joint.SetMotorSpeed(value);
}
}
},
},
_createJointDef: function () {
var def = new b2.PrismaticJointDef();
def.localAnchorA = new b2.Vec2(this.anchor.x/PTM_RATIO, this.anchor.y/PTM_RATIO);
def.localAnchorB = new b2.Vec2(this.connectedAnchor.x/PTM_RATIO, this.connectedAnchor.y/PTM_RATIO);
def.localAxisA = new b2.Vec2(this.localAxisA.x, this.localAxisA.y);
def.referenceAngle = this.referenceAngle * ANGLE_TO_PHYSICS_ANGLE;
def.enableLimit = this.enableLimit;
def.lowerTranslation = this.lowerLimit/PTM_RATIO;
def.upperTranslation = this.upperLimit/PTM_RATIO;
def.enableMotor = this.enableMotor;
def.maxMotorForce = this.maxMotorForce;
def.motorSpeed = this.motorSpeed;
return def;
}
});
cc.PrismaticJoint = module.exports = PrismaticJoint;

View File

@@ -0,0 +1,235 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var ANGLE_TO_PHYSICS_ANGLE = require('../CCPhysicsTypes').ANGLE_TO_PHYSICS_ANGLE;
var PHYSICS_ANGLE_TO_ANGLE = require('../CCPhysicsTypes').PHYSICS_ANGLE_TO_ANGLE;
/**
* !#en
* A revolute joint constrains two bodies to share a common point while they
* are free to rotate about the point. The relative rotation about the shared
* point is the joint angle. You can limit the relative rotation with
* a joint limit that specifies a lower and upper angle. You can use a motor
* to drive the relative rotation about the shared point. A maximum motor torque
* is provided so that infinite forces are not generated.
* !#zh
* 旋转关节可以约束两个刚体围绕一个点来进行旋转。
* 你可以通过开启关节限制来限制旋转的最大角度和最小角度。
* 你可以通过开启马达来施加一个扭矩力来驱动这两个刚体在这一点上的相对速度。
* @class RevoluteJoint
* @extends Joint
*/
var RevoluteJoint = cc.Class({
name: 'cc.RevoluteJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.physics/Joint/Revolute',
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
},
properties: {
_maxMotorTorque: 0,
_motorSpeed: 0,
_enableLimit: false,
_enableMotor: false,
/**
* !#en
* The reference angle.
* An angle between bodies considered to be zero for the joint angle.
* !#zh
* 相对角度。
* 两个物体之间角度为零时可以看作相等于关节角度
* @property {Number} referenceAngle
* @default 0
*/
referenceAngle: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.referenceAngle',
},
/**
* !#en
* The lower angle.
* !#zh
* 角度的最低限制。
* @property {Number} lowerAngle
* @default 0
*/
lowerAngle: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.lowerAngle'
},
/**
* !#en
* The upper angle.
* !#zh
* 角度的最高限制。
* @property {Number} upperAngle
* @default 0
*/
upperAngle: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.upperAngle'
},
/**
* !#en
* The maxium torque can be applied to rigidbody to rearch the target motor speed.
* !#zh
* 可以施加到刚体的最大扭矩。
* @property {Number} maxMotorTorque
* @default 0
*/
maxMotorTorque: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxMotorTorque',
get: function () {
return this._maxMotorTorque;
},
set: function (value) {
this._maxMotorTorque = value;
if (this._joint) {
this._joint.SetMaxMotorTorque(value);
}
}
},
/**
* !#en
* The expected motor speed.
* !#zh
* 期望的马达速度。
* @property {Number} motorSpeed
* @default 0
*/
motorSpeed: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.motorSpeed',
get: function () {
return this._motorSpeed;
},
set: function (value) {
this._motorSpeed = value;
if (this._joint) {
this._joint.SetMotorSpeed(value * ANGLE_TO_PHYSICS_ANGLE);
}
}
},
/**
* !#en
* Enable joint limit?
* !#zh
* 是否开启关节的限制?
* @property {Boolean} enableLimit
* @default false
*/
enableLimit: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.enableLimit',
get: function () {
return this._enableLimit;
},
set: function (value) {
this._enableLimit = value;
if (this._joint) {
this._joint.EnableLimit(value);
}
}
},
/**
* !#en
* Enable joint motor?
* !#zh
* 是否开启关节马达?
* @property {Boolean} enableMotor
* @default false
*/
enableMotor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.enableMotor',
get: function () {
return this._enableMotor;
},
set: function (value) {
this._enableMotor = value;
if (this._joint) {
this._joint.EnableMotor(value);
}
}
}
},
/**
* !#en
* Get the joint angle.
* !#zh
* 获取关节角度。
* @method getJointAngle
* @return {Number}
*/
getJointAngle: function () {
if (this._joint) {
return this._joint.GetJointAngle() * PHYSICS_ANGLE_TO_ANGLE;
}
return 0;
},
/**
* !#en
* Set the max and min limit angle.
* !#zh
* 设置关节的角度最大和最小角度。
* @param {Number} lower
* @param {Number} upper
*/
setLimits (lower, upper) {
if (this._joint) {
return this._joint.SetLimits(lower * ANGLE_TO_PHYSICS_ANGLE, upper * ANGLE_TO_PHYSICS_ANGLE);
}
},
_createJointDef: function () {
var def = new b2.RevoluteJointDef();
def.localAnchorA = new b2.Vec2(this.anchor.x/PTM_RATIO, this.anchor.y/PTM_RATIO);
def.localAnchorB = new b2.Vec2(this.connectedAnchor.x/PTM_RATIO, this.connectedAnchor.y/PTM_RATIO);
// cocos degree 0 is to right, and box2d degree 0 is to up.
def.lowerAngle = this.upperAngle* ANGLE_TO_PHYSICS_ANGLE;
def.upperAngle = this.lowerAngle* ANGLE_TO_PHYSICS_ANGLE;
def.maxMotorTorque = this.maxMotorTorque;
def.motorSpeed = this.motorSpeed * ANGLE_TO_PHYSICS_ANGLE;
def.enableLimit = this.enableLimit;
def.enableMotor = this.enableMotor;
def.referenceAngle = this.referenceAngle * ANGLE_TO_PHYSICS_ANGLE;
return def;
}
});
cc.RevoluteJoint = module.exports = RevoluteJoint;

View File

@@ -0,0 +1,86 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
/**
* !#en
* A rope joint enforces a maximum distance between two points
* on two bodies. It has no other effect.
* Warning: if you attempt to change the maximum length during
* the simulation you will get some non-physical behavior.
* !#zh
* 绳子关节只指定两个刚体间的最大距离,没有其他的效果。
* 注意:如果你试图动态修改关节的长度,这有可能会得到一些意外的效果。
* @class RopeJoint
* @extends Joint
*/
var RopeJoint = cc.Class({
name: 'cc.RopeJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
menu: 'i18n:MAIN_MENU.component.physics/Joint/Rope',
},
properties: {
_maxLength: 1,
/**
* !#en
* The max length.
* !#zh
* 最大长度。
* @property {Number} maxLength
* @default 1
*/
maxLength: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxLength',
get: function () {
return this._maxLength;
},
set: function (value) {
this._maxLength = value;
if (this._joint) {
this._joint.SetMaxLength(value);
}
}
},
},
_createJointDef: function () {
var def = new b2.RopeJointDef();
def.localAnchorA = new b2.Vec2(this.anchor.x/PTM_RATIO, this.anchor.y/PTM_RATIO);
def.localAnchorB = new b2.Vec2(this.connectedAnchor.x/PTM_RATIO, this.connectedAnchor.y/PTM_RATIO);
def.maxLength = this.maxLength/PTM_RATIO;
return def;
}
});
cc.RopeJoint = module.exports = RopeJoint;

View File

@@ -0,0 +1,122 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var ANGLE_TO_PHYSICS_ANGLE = require('../CCPhysicsTypes').ANGLE_TO_PHYSICS_ANGLE;
/**
* !#en
* A weld joint essentially glues two bodies together. A weld joint may
* distort somewhat because the island constraint solver is approximate.
* !#zh
* 熔接关节相当于将两个刚体粘在了一起。
* 熔接关节可能会使某些东西失真,因为约束求解器算出的都是近似值。
* @class WeldJoint
* @extends Joint
*/
var WeldJoint = cc.Class({
name: 'cc.WeldJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
menu: 'i18n:MAIN_MENU.component.physics/Joint/Weld',
},
properties: {
/**
* !#en
* The reference angle.
* !#zh
* 相对角度。
* @property {Number} referenceAngle
* @default 0
*/
referenceAngle: {
default: 0,
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.referenceAngle'
},
_frequency: 0,
_dampingRatio: 0,
/**
* !#en
* The frequency.
* !#zh
* 弹性系数。
* @property {Number} frequency
* @default 0
*/
frequency: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.frequency',
get: function () {
return this._frequency;
},
set: function (value) {
this._frequency = value;
if (this._joint) {
this._joint.SetFrequency(value);
}
}
},
/**
* !#en
* The damping ratio.
* !#zh
* 阻尼,表示关节变形后,恢复到初始状态受到的阻力。
* @property {Number} dampingRatio
* @default 0
*/
dampingRatio: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.dampingRatio',
get: function () {
return this._dampingRatio;
},
set: function (value) {
this._dampingRatio = value;
if (this._joint) {
this._joint.SetDampingRatio(value);
}
}
}
},
_createJointDef: function () {
var def = new b2.WeldJointDef();
def.localAnchorA = new b2.Vec2(this.anchor.x/PTM_RATIO, this.anchor.y/PTM_RATIO);
def.localAnchorB = new b2.Vec2(this.connectedAnchor.x/PTM_RATIO, this.connectedAnchor.y/PTM_RATIO);
def.referenceAngle = this.referenceAngle * ANGLE_TO_PHYSICS_ANGLE;
def.frequencyHz = this.frequency;
def.dampingRatio = this.dampingRatio;
return def;
}
});
cc.WeldJoint = module.exports = WeldJoint;

View File

@@ -0,0 +1,197 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
var PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
var ANGLE_TO_PHYSICS_ANGLE = require('../CCPhysicsTypes').ANGLE_TO_PHYSICS_ANGLE;
/**
* !#en
* A wheel joint. This joint provides two degrees of freedom: translation
* along an axis fixed in bodyA and rotation in the plane. You can use a joint motor to drive
* the rotation or to model rotational friction.
* This joint is designed for vehicle suspensions.
* !#zh
* 轮子关节提供两个维度的自由度:旋转和沿着指定方向上位置的移动。
* 你可以通过开启关节马达来使用马达驱动刚体的旋转。
* 轮组关节是专门为机动车类型设计的。
* @class WheelJoint
* @extends Joint
*/
var WheelJoint = cc.Class({
name: 'cc.WheelJoint',
extends: cc.Joint,
editor: CC_EDITOR && {
inspector: 'packages://inspector/inspectors/comps/physics/joint.js',
menu: 'i18n:MAIN_MENU.component.physics/Joint/Wheel',
},
properties: {
_maxMotorTorque: 0,
_motorSpeed: 0,
_enableMotor: false,
_frequency: 2,
_dampingRatio: 0.7,
/**
* !#en
* The local joint axis relative to rigidbody.
* !#zh
* 指定刚体可以移动的方向。
* @property {Vec2} localAxisA
* @default cc.v2(1, 0)
*/
localAxisA: {
default: cc.v2(1, 0),
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.localAxisA'
},
/**
* !#en
* The maxium torque can be applied to rigidbody to rearch the target motor speed.
* !#zh
* 可以施加到刚体的最大扭矩。
* @property {Number} maxMotorTorque
* @default 0
*/
maxMotorTorque: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.maxMotorTorque',
get: function () {
return this._maxMotorTorque;
},
set: function (value) {
this._maxMotorTorque = value;
if (this._joint) {
this._joint.SetMaxMotorTorque(value);
}
}
},
/**
* !#en
* The expected motor speed.
* !#zh
* 期望的马达速度。
* @property {Number} motorSpeed
* @default 0
*/
motorSpeed: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.motorSpeed',
get: function () {
return this._motorSpeed;
},
set: function (value) {
this._motorSpeed = value;
if (this._joint) {
this._joint.SetMotorSpeed(value * ANGLE_TO_PHYSICS_ANGLE);
}
}
},
/**
* !#en
* Enable joint motor?
* !#zh
* 是否开启关节马达?
* @property {Boolean} enableMotor
* @default false
*/
enableMotor: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.enableMotor',
get: function () {
return this._enableMotor;
},
set: function (value) {
this._enableMotor = value;
if (this._joint) {
this._joint.EnableMotor(value);
}
}
},
/**
* !#en
* The spring frequency.
* !#zh
* 弹性系数。
* @property {Number} frequency
* @default 0
*/
frequency: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.frequency',
get: function () {
return this._frequency;
},
set: function (value) {
this._frequency = value;
if (this._joint) {
this._joint.SetSpringFrequencyHz(value);
}
}
},
/**
* !#en
* The damping ratio.
* !#zh
* 阻尼,表示关节变形后,恢复到初始状态受到的阻力。
* @property {Number} dampingRatio
* @default 0
*/
dampingRatio: {
tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.dampingRatio',
get: function () {
return this._dampingRatio;
},
set: function (value) {
this._dampingRatio = value;
if (this._joint) {
this._joint.SetDampingRatio(value);
}
}
}
},
_createJointDef: function () {
var def = new b2.WheelJointDef();
def.localAnchorA = new b2.Vec2(this.anchor.x/PTM_RATIO, this.anchor.y/PTM_RATIO);
def.localAnchorB = new b2.Vec2(this.connectedAnchor.x/PTM_RATIO, this.connectedAnchor.y/PTM_RATIO);
def.localAxisA = new b2.Vec2(this.localAxisA.x, this.localAxisA.y);
def.maxMotorTorque = this.maxMotorTorque;
def.motorSpeed = this.motorSpeed * ANGLE_TO_PHYSICS_ANGLE;
def.enableMotor = this.enableMotor;
def.dampingRatio = this.dampingRatio;
def.frequencyHz = this.frequency;
return def;
}
});
cc.WheelJoint = module.exports = WheelJoint;

View File

@@ -0,0 +1,74 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
const BodyType = require('../CCPhysicsTypes').BodyType;
function PhysicsAABBQueryCallback () {
this._point = new b2.Vec2();
this._isPoint = false;
this._fixtures = [];
}
PhysicsAABBQueryCallback.prototype.init = function (point) {
if (point) {
this._isPoint = true;
this._point.x = point.x;
this._point.y = point.y;
}
else {
this._isPoint = false;
}
this._fixtures.length = 0;
};
PhysicsAABBQueryCallback.prototype.ReportFixture = function (fixture) {
var body = fixture.GetBody();
if (body.GetType() === BodyType.Dynamic) {
if (this._isPoint) {
if (fixture.TestPoint(this._point)) {
this._fixtures.push(fixture);
// We are done, terminate the query.
return false;
}
}
else {
this._fixtures.push(fixture);
}
}
// True to continue the query, false to terminate the query.
return true;
};
PhysicsAABBQueryCallback.prototype.getFixture = function () {
return this._fixtures[0];
};
PhysicsAABBQueryCallback.prototype.getFixtures = function () {
return this._fixtures;
};
cc.PhysicsAABBQueryCallback = module.exports = PhysicsAABBQueryCallback;

View File

@@ -0,0 +1,89 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
function PhysicsContactListener () {
this._contactFixtures = [];
}
PhysicsContactListener.prototype.setBeginContact = function (cb) {
this._BeginContact = cb;
};
PhysicsContactListener.prototype.setEndContact = function (cb) {
this._EndContact = cb;
};
PhysicsContactListener.prototype.setPreSolve = function (cb) {
this._PreSolve = cb;
};
PhysicsContactListener.prototype.setPostSolve = function (cb) {
this._PostSolve = cb;
};
PhysicsContactListener.prototype.BeginContact = function (contact) {
if (!this._BeginContact) return;
var fixtureA = contact.GetFixtureA();
var fixtureB = contact.GetFixtureB();
var fixtures = this._contactFixtures;
contact._shouldReport = false;
if (fixtures.indexOf(fixtureA) !== -1 || fixtures.indexOf(fixtureB) !== -1) {
contact._shouldReport = true; // for quick check whether this contact should report
this._BeginContact(contact);
}
};
PhysicsContactListener.prototype.EndContact = function (contact) {
if (this._EndContact && contact._shouldReport) {
contact._shouldReport = false;
this._EndContact(contact);
}
};
PhysicsContactListener.prototype.PreSolve = function (contact, oldManifold) {
if (this._PreSolve && contact._shouldReport) {
this._PreSolve(contact, oldManifold);
}
};
PhysicsContactListener.prototype.PostSolve = function (contact, impulse) {
if (this._PostSolve && contact._shouldReport) {
this._PostSolve(contact, impulse);
}
};
PhysicsContactListener.prototype.registerContactFixture = function (fixture) {
this._contactFixtures.push(fixture);
};
PhysicsContactListener.prototype.unregisterContactFixture = function (fixture) {
cc.js.array.remove(this._contactFixtures, fixture);
};
cc.PhysicsContactListener = module.exports = PhysicsContactListener;

View File

@@ -0,0 +1,166 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
const PTM_RATIO = require('../CCPhysicsTypes').PTM_RATIO;
let _tmp_vec2 = cc.v2();
let GREEN_COLOR = cc.Color.GREEN;
let RED_COLOR = cc.Color.RED;
function PhysicsDebugDraw (drawer) {
b2.Draw.call(this);
this._drawer = drawer;
this._xf = this._dxf = new b2.Transform();
}
cc.js.extend(PhysicsDebugDraw, b2.Draw);
cc.js.mixin(PhysicsDebugDraw.prototype, {
_DrawPolygon (vertices, vertexCount) {
var drawer = this._drawer;
for (var i=0; i<vertexCount; i++) {
b2.Transform.MulXV(this._xf, vertices[i], _tmp_vec2);
let x = _tmp_vec2.x * PTM_RATIO,
y = _tmp_vec2.y * PTM_RATIO;
if (i === 0)
drawer.moveTo(x, y);
else {
drawer.lineTo(x, y);
}
}
drawer.close();
},
DrawPolygon (vertices, vertexCount, color) {
this._applyStrokeColor(color);
this._DrawPolygon(vertices, vertexCount);
this._drawer.stroke();
},
DrawSolidPolygon (vertices, vertexCount, color) {
this._applyFillColor(color);
this._DrawPolygon(vertices, vertexCount);
this._drawer.fill();
this._drawer.stroke();
},
_DrawCircle (center, radius) {
let p = this._xf.p;
this._drawer.circle((center.x + p.x) * PTM_RATIO, (center.y + p.y) * PTM_RATIO, radius * PTM_RATIO);
},
DrawCircle (center, radius, color) {
this._applyStrokeColor(color);
this._DrawCircle(center, radius);
this._drawer.stroke();
},
DrawSolidCircle (center, radius, axis, color) {
this._applyFillColor(color);
this._DrawCircle(center, radius);
this._drawer.fill();
},
DrawSegment (p1, p2, color) {
var drawer = this._drawer;
if (p1.x === p2.x && p1.y === p2.y) {
this._applyFillColor(color);
this._DrawCircle(p1, 2/PTM_RATIO);
drawer.fill();
return;
}
this._applyStrokeColor(color);
b2.Transform.MulXV(this._xf, p1, _tmp_vec2);
drawer.moveTo(_tmp_vec2.x * PTM_RATIO, _tmp_vec2.y * PTM_RATIO);
b2.Transform.MulXV(this._xf, p2, _tmp_vec2);
drawer.lineTo(_tmp_vec2.x * PTM_RATIO, _tmp_vec2.y * PTM_RATIO);
drawer.stroke();
},
DrawTransform (xf) {
var drawer = this._drawer;
drawer.strokeColor = RED_COLOR;
_tmp_vec2.x = _tmp_vec2.y = 0;
b2.Transform.MulXV(xf, _tmp_vec2, _tmp_vec2);
drawer.moveTo(_tmp_vec2.x * PTM_RATIO, _tmp_vec2.y * PTM_RATIO);
_tmp_vec2.x = 1; _tmp_vec2.y = 0;
b2.Transform.MulXV(xf, _tmp_vec2, _tmp_vec2);
drawer.lineTo(_tmp_vec2.x * PTM_RATIO, _tmp_vec2.y * PTM_RATIO);
drawer.stroke();
drawer.strokeColor = GREEN_COLOR;
_tmp_vec2.x = _tmp_vec2.y = 0;
b2.Transform.MulXV(xf, _tmp_vec2, _tmp_vec2);
drawer.moveTo(_tmp_vec2.x * PTM_RATIO, _tmp_vec2.y * PTM_RATIO);
_tmp_vec2.x = 0; _tmp_vec2.y = 1;
b2.Transform.MulXV(xf, _tmp_vec2, _tmp_vec2);
drawer.lineTo(_tmp_vec2.x * PTM_RATIO, _tmp_vec2.y * PTM_RATIO);
drawer.stroke();
},
DrawPoint (center, radius, color) {
},
_applyStrokeColor (color) {
let strokeColor = this._drawer.strokeColor;
strokeColor.r = color.r*255;
strokeColor.g = color.g*255;
strokeColor.b = color.b*255;
strokeColor.a = 150;
this._drawer.strokeColor = strokeColor;
},
_applyFillColor (color) {
let fillColor = this._drawer.fillColor;
fillColor.r = color.r*255;
fillColor.g = color.g*255;
fillColor.b = color.b*255;
fillColor.a = 150;
this._drawer.fillColor = fillColor;
},
PushTransform (xf) {
this._xf = xf;
},
PopTransform () {
this._xf = this._dxf;
}
});
module.exports = PhysicsDebugDraw;

View File

@@ -0,0 +1,84 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
function PhysicsRayCastCallback () {
this._type = 0;
this._fixtures = [];
this._points = [];
this._normals = [];
this._fractions = [];
}
PhysicsRayCastCallback.prototype.init = function (type) {
this._type = type;
this._fixtures.length = 0;
this._points.length = 0;
this._normals.length = 0;
this._fractions.length = 0;
};
PhysicsRayCastCallback.prototype.ReportFixture = function (fixture, point, normal, fraction) {
if (this._type === 0) { // closest
this._fixtures[0] = fixture;
this._points[0] = point;
this._normals[0] = normal;
this._fractions[0] = fraction;
return fraction;
}
this._fixtures.push(fixture);
this._points.push(cc.v2(point));
this._normals.push(cc.v2(normal));
this._fractions.push(fraction);
if (this._type === 1) { // any
return 0;
}
else if (this._type >= 2) { // all
return 1;
}
return fraction;
};
PhysicsRayCastCallback.prototype.getFixtures = function () {
return this._fixtures;
};
PhysicsRayCastCallback.prototype.getPoints = function () {
return this._points;
};
PhysicsRayCastCallback.prototype.getNormals = function () {
return this._normals;
};
PhysicsRayCastCallback.prototype.getFractions = function () {
return this._fractions;
};
cc.PhysicsRayCastCallback = module.exports = PhysicsRayCastCallback;

View File

@@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
function getWorldRotation (node) {
var rot = node.angle;
var parent = node.parent;
while(parent.parent){
rot += parent.angle;
parent = parent.parent;
}
return -rot;
}
function getWorldScale (node) {
var scaleX = node.scaleX;
var scaleY = node.scaleY;
var parent = node.parent;
while(parent.parent){
scaleX *= parent.scaleX;
scaleY *= parent.scaleY;
parent = parent.parent;
}
return cc.v2(scaleX, scaleY);
}
function convertToNodeRotation (node, rotation) {
rotation -= -node.angle;
var parent = node.parent;
while(parent.parent){
rotation -= -parent.angle;
parent = parent.parent;
}
return rotation;
}
module.exports = {
getWorldRotation: getWorldRotation,
getWorldScale: getWorldScale,
convertToNodeRotation: convertToNodeRotation
};