- Creator 版本:2.2.0
cocoscreator 2.2.0 使用更新box2d api,消除报错
参考:根据1.5测试版写的简易浮力控制
http://www.iforce2d.net/b2dtut/buoyancy
buoyancy修正版.rar (108.7 KB)
11赞
大佬你好,我想让漂浮的物体,露出水面的面积更多,应该改哪里呢?
import GameManager from “./GameManager”;
const { ccclass, property } = cc._decorator;
@ccclass
export default class BuoyancyLiquid extends cc.Component {
@property({ tooltip: "密度" })
private density: number = 1;
@property({ tooltip: "角速度阻力" })
private angularDrag: number = 1;
@property({ tooltip: "线速度阻力" })
private linearDrag: number = 1;
private inFluid = [];
private gravity: cc.Vec2 = null;
private fluidBody: any = null;
onLoad() {
GameManager.Physical_Manager();
GameManager.Physical_Controller(true);
// GameManager.Physical_DebugModel(1);
this.gravity = cc.v2(GameManager.Physical_Manager().gravity.x, -GameManager.Physical_Manager().gravity.y);
};
start() {
this.createFluid();
}
// called every frame, uncomment this function to activate update callback
update(dt) {
for (let i = 0, l = this.inFluid.length; i < l; i++) {
this.applyBuoyancy(this.inFluid[i]);
}
};
createFluid() {
let body: cc.RigidBody = this.node.getComponent(cc.RigidBody);
body.type = 0;
body.enabledContactListener = true;
let polygonCollider = this.node.getComponent(cc.PhysicsPolygonCollider);
// let w = this.node.width / 2;
// let h = this.node.height / 2;
// polygonCollider.points = [cc.v2(-w, -h), cc.v2(w, -h), cc.v2(w, h), cc.v2(-w, h)];
polygonCollider.sensor = true;
polygonCollider.density = this.density;
polygonCollider.apply();
this.fluidBody = body["_b2Body"];
};
findIntersectionAreaAndCentroid(body) {
let fixtureB = body.m_fixtureList;
if (!fixtureB || fixtureB.GetType() !== 2) {
return;
}
let centroid = cc.v2(0, 0);
let area = 0;
let mass = 0;
while (fixtureB) {
let outputList = this.getVertices(this.fluidBody);
let clipPolygon = this.getVertices(body);
let cp1 = clipPolygon[clipPolygon.length - 1];
for (let j = 0; j < clipPolygon.length; j++) {
let cp2 = clipPolygon[j];
let inputList = outputList;
outputList = [];
let s = inputList[inputList.length - 1]; //last on the input list
for (let i = 0; i < inputList.length; i++) {
let e = inputList[i];
if (this.inside(cp1, cp2, e)) {
if (!this.inside(cp1, cp2, s)) {
outputList.push(this.intersection(cp1, cp2, s, e));
}
outputList.push(e);
}
else if (this.inside(cp1, cp2, s)) {
outputList.push(this.intersection(cp1, cp2, s, e));
}
s = e;
}
cp1 = cp2;
}
let ac = this.computeAC(outputList);
let density = fixtureB.GetDensity();
mass += ac[0] * density;
area += ac[0];
//centroid.addSelf(ac[1].mul(density));
centroid.x += ac[1].x * density;
centroid.y += ac[1].y * density;
fixtureB = fixtureB.GetNext();
}
centroid.mulSelf(1 / mass);
return [area, centroid];
};
onBeginContact(contact, selfCollider, otherCollider) {
let bodyB = otherCollider.body._b2Body;
this.inFluid.push(bodyB);
contact.disabled = true;
};
onEndContact(contact, selfCollider, otherCollider) {
let bodyB = otherCollider.body._b2Body;
let index = this.inFluid.indexOf(bodyB);
this.inFluid.splice(index, 1);
contact.disabled = true;
};
applyBuoyancy(body) {
let AC: Array<any> = this.findIntersectionAreaAndCentroid(body);//get the area and centroid
if (AC[0] !== 0) {
let mass = AC[0] * this.density;
let centroid = AC[1];
let buoyancyForce = cc.v2(mass * this.gravity.x, mass * this.gravity.y);
body.ApplyForce(buoyancyForce, centroid);
let body_vw = cc.v2();
let fluidBody_vw = cc.v2();
body.GetLinearVelocityFromWorldPoint(centroid, body_vw);
this.fluidBody.GetLinearVelocityFromWorldPoint(centroid, fluidBody_vw);
let velDir = body_vw.sub(fluidBody_vw);
let dragMag = this.density * this.linearDrag * mass;
let dragForce = velDir.mul(-dragMag);
body.ApplyForce(dragForce, centroid);
let torque = -body.GetInertia() / body.GetMass() * mass * body.GetAngularVelocity() * this.angularDrag;
body.ApplyTorque(torque);
}
};
getVertices(body) {
let shape = body.m_fixtureList.m_shape;
let vertices = [];
for (let i = 0; i < shape.m_count; i++) {
let pos = cc.v2(shape.m_vertices[i].x, shape.m_vertices[i].y);
let pos_w = cc.v2();
body.GetWorldPoint(pos, pos_w);
vertices.push(pos_w);
}
return vertices;
};
inside(cp1, cp2, p) {
return (cp2.x - cp1.x) * (p.y - cp1.y) > (cp2.y - cp1.y) * (p.x - cp1.x);
}
intersection(cp1, cp2, s, e) {
let dc = cc.v2(cp1.x - cp2.x, cp1.y - cp2.y);
let dp = cc.v2(s.x - e.x, s.y - e.y);
let n1 = cp1.x * cp2.y - cp1.y * cp2.x;
let n2 = s.x * e.y - s.y * e.x;
let n3 = (dc.x * dp.y - dc.y * dp.x);
return cc.v2((n1 * dp.x - n2 * dc.x) / n3, (n1 * dp.y - n2 * dc.y) / n3);
}
computeAC(vs): Array<any> {
let count = vs.length;
let c = cc.v2(0, 0);
let area = 0.0;
let p1X = 0.0;
let p1Y = 0.0;
let inv3 = 1.0 / 3.0;
for (let i = 0; i < count; ++i) {
let p2 = vs[i];
let p3 = i + 1 < count ? vs[i + 1] : vs[0];
let e1X = p2.x - p1X;
let e1Y = p2.y - p1Y;
let e2X = p3.x - p1X;
let e2Y = p3.y - p1Y;
let D = (e1X * e2Y - e1Y * e2X);
let triangleArea = 0.5 * D; area += triangleArea;
c.x += triangleArea * inv3 * (p1X + p2.x + p3.x);
c.y += triangleArea * inv3 * (p1Y + p2.y + p3.y);
}
return [area, c];
}
}
修改密度,或者修改漂浮物的重力值和密度试一试
总感觉以后用的上
mark 一下
感谢大佬分享
感谢大佬分享,干货呀
mark
·····
这个感觉很硬
如果是圆的物体。大佬要怎么做呢?