mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
182 lines
4.5 KiB
Dart
182 lines
4.5 KiB
Dart
part of skysprites;
|
|
|
|
abstract class PhysicsJoint {
|
|
PhysicsJoint(this.bodyA, this.bodyB, this.breakingForce) {
|
|
bodyA._joints.add(this);
|
|
bodyB._joints.add(this);
|
|
}
|
|
|
|
final PhysicsBody bodyA;
|
|
final PhysicsBody bodyB;
|
|
final double breakingForce;
|
|
|
|
bool _active = true;
|
|
box2d.Joint _joint;
|
|
|
|
PhysicsNode _physicsNode;
|
|
|
|
void _completeCreation() {
|
|
if (bodyA._attached && bodyB._attached) {
|
|
_attach(bodyA._physicsNode);
|
|
}
|
|
}
|
|
|
|
void _attach(PhysicsNode physicsNode) {
|
|
if (_joint == null) {
|
|
_physicsNode = physicsNode;
|
|
_joint = _createB2Joint(physicsNode);
|
|
_physicsNode._joints.add(this);
|
|
}
|
|
}
|
|
|
|
void _detach() {
|
|
if (_joint != null && _active) {
|
|
_physicsNode.b2World.destroyJoint(_joint);
|
|
_joint = null;
|
|
_physicsNode._joints.remove(this);
|
|
}
|
|
_active = false;
|
|
}
|
|
|
|
box2d.Joint _createB2Joint(PhysicsNode physicsNode);
|
|
|
|
void destroy() {
|
|
_detach();
|
|
}
|
|
|
|
void _checkBreakingForce(double dt) {
|
|
if (breakingForce == null) return;
|
|
|
|
if (_joint != null && _active) {
|
|
Vector2 reactionForce = new Vector2.zero();
|
|
_joint.getReactionForce(1.0 / dt, reactionForce);
|
|
|
|
if (breakingForce * breakingForce < reactionForce.length2) {
|
|
// TODO: Add callback
|
|
|
|
destroy();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class PhysicsJointRevolute extends PhysicsJoint {
|
|
PhysicsJointRevolute(
|
|
PhysicsBody bodyA,
|
|
PhysicsBody bodyB,
|
|
this.worldAnchor, {
|
|
this.lowerAngle: 0.0,
|
|
this.upperAngle: 0.0,
|
|
this.enableLimit: false,
|
|
double breakingForce
|
|
}) : super(bodyA, bodyB, breakingForce) {
|
|
_completeCreation();
|
|
}
|
|
|
|
final Point worldAnchor;
|
|
final double lowerAngle;
|
|
final double upperAngle;
|
|
final bool enableLimit;
|
|
|
|
box2d.Joint _createB2Joint(PhysicsNode physicsNode) {
|
|
// Create Joint Definition
|
|
Vector2 vecAnchor = new Vector2(
|
|
worldAnchor.x / physicsNode.b2WorldToNodeConversionFactor,
|
|
worldAnchor.y / physicsNode.b2WorldToNodeConversionFactor
|
|
);
|
|
|
|
box2d.RevoluteJointDef b2Def = new box2d.RevoluteJointDef();
|
|
b2Def.initialize(bodyA._body, bodyB._body, vecAnchor);
|
|
b2Def.enableLimit = enableLimit;
|
|
b2Def.lowerAngle = lowerAngle;
|
|
b2Def.upperAngle = upperAngle;
|
|
|
|
// Create joint
|
|
return physicsNode.b2World.createJoint(b2Def);
|
|
}
|
|
}
|
|
|
|
class PhysicsJointPrismatic extends PhysicsJoint {
|
|
PhysicsJointPrismatic(
|
|
PhysicsBody bodyA,
|
|
PhysicsBody bodyB,
|
|
this.axis, {
|
|
double breakingForce
|
|
}
|
|
) : super(bodyA, bodyB, breakingForce) {
|
|
_completeCreation();
|
|
}
|
|
|
|
Offset axis;
|
|
|
|
box2d.Joint _createB2Joint(PhysicsNode physicsNode) {
|
|
box2d.PrismaticJointDef b2Def = new box2d.PrismaticJointDef();
|
|
b2Def.initialize(bodyA._body, bodyB._body, bodyA._body.position, new Vector2(axis.dx, axis.dy));
|
|
return physicsNode.b2World.createJoint(b2Def);
|
|
}
|
|
}
|
|
|
|
class PhysicsJointWeld extends PhysicsJoint {
|
|
PhysicsJointWeld(
|
|
PhysicsBody bodyA,
|
|
PhysicsBody bodyB, {
|
|
double breakingForce
|
|
}
|
|
) : super(bodyA, bodyB, breakingForce) {
|
|
_completeCreation();
|
|
}
|
|
|
|
box2d.Joint _createB2Joint(PhysicsNode physicsNode) {
|
|
box2d.WeldJointDef b2Def = new box2d.WeldJointDef();
|
|
Vector2 middle = new Vector2(
|
|
(bodyA._body.position.x + bodyB._body.position.x) / 2.0,
|
|
(bodyA._body.position.y + bodyB._body.position.y) / 2.0
|
|
);
|
|
b2Def.initialize(bodyA._body, bodyB._body, middle);
|
|
return physicsNode.b2World.createJoint(b2Def);
|
|
}
|
|
}
|
|
|
|
class PhysicsJointPulley extends PhysicsJoint {
|
|
PhysicsJointPulley(
|
|
PhysicsBody bodyA,
|
|
PhysicsBody bodyB,
|
|
this.groundAnchorA,
|
|
this.groundAnchorB,
|
|
this.anchorA,
|
|
this.anchorB,
|
|
this.ratio, {
|
|
double breakingForce
|
|
}
|
|
) : super(bodyA, bodyB, breakingForce) {
|
|
_completeCreation();
|
|
}
|
|
|
|
final Point groundAnchorA;
|
|
final Point groundAnchorB;
|
|
final Point anchorA;
|
|
final Point anchorB;
|
|
final double ratio;
|
|
|
|
box2d.Joint _createB2Joint(PhysicsNode physicsNode) {
|
|
box2d.PulleyJointDef b2Def = new box2d.PulleyJointDef();
|
|
b2Def.initialize(
|
|
bodyA._body,
|
|
bodyB._body,
|
|
_convertPosToVec(groundAnchorA, physicsNode),
|
|
_convertPosToVec(groundAnchorB, physicsNode),
|
|
_convertPosToVec(anchorA, physicsNode),
|
|
_convertPosToVec(anchorB, physicsNode),
|
|
ratio
|
|
);
|
|
return physicsNode.b2World.createJoint(b2Def);
|
|
}
|
|
}
|
|
|
|
Vector2 _convertPosToVec(Point pt, PhysicsNode physicsNode) {
|
|
return new Vector2(
|
|
pt.x / physicsNode.b2WorldToNodeConversionFactor,
|
|
pt.y / physicsNode.b2WorldToNodeConversionFactor
|
|
);
|
|
}
|