Adds basic support for joints in sprite physics
diff --git a/packages/flutter_sprites/lib/physics_body.dart b/packages/flutter_sprites/lib/physics_body.dart index 178b1ac..40ee242 100644 --- a/packages/flutter_sprites/lib/physics_body.dart +++ b/packages/flutter_sprites/lib/physics_body.dart
@@ -230,6 +230,8 @@ box2d.Body _body; + List<PhysicsJoint> _joints = []; + bool _attached = false; void applyForce(Offset force, Point worldPoint) { @@ -338,6 +340,13 @@ _node = node; _attached = true; + + // Attach any joints + for (PhysicsJoint joint in _joints) { + if (joint.bodyA._attached && joint.bodyB._attached) { + joint._attach(physicsNode); + } + } } void _detach() {
diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart new file mode 100644 index 0000000..cecdd5c --- /dev/null +++ b/packages/flutter_sprites/lib/physics_joint.dart
@@ -0,0 +1,90 @@ +part of skysprites; + +abstract class PhysicsJoint { + PhysicsJoint(this.bodyA, this.bodyB) { + bodyA._joints.add(this); + bodyB._joints.add(this); + + if (bodyA._attached && bodyB._attached) { + _attach(bodyA._physicsNode); + } + } + + PhysicsBody bodyA; + PhysicsBody bodyB; + + bool _active = true; + box2d.Joint _joint; + + PhysicsNode _physicsNode; + + void _attach(PhysicsNode physicsNode) { + if (_joint == null) { + _physicsNode = physicsNode; + _joint = _createB2Joint(physicsNode); + } + } + + void _detach() { + if (_joint != null && _active) { + _physicsNode.b2World.destroyJoint(_joint); + _joint = null; + } + _active = false; + } + + box2d.Joint _createB2Joint(PhysicsNode physicsNode); +} + +class PhysicsJointRevolute extends PhysicsJoint { + PhysicsJointRevolute( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.anchorWorld, { + double lowerAngle: 0.0, + double upperAngle: 0.0, + bool enableLimit: false + }) : super(bodyA, bodyB) { + this.lowerAngle = lowerAngle; + this.upperAngle = upperAngle; + this.enableLimit = enableLimit; + } + + Point anchorWorld; + double lowerAngle; + double upperAngle; + bool enableLimit; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + // Create Joint Definition + Vector2 vecAnchor = new Vector2( + anchorWorld.x / physicsNode.b2WorldToNodeConversionFactor, + anchorWorld.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 PhysicsJointWeld extends PhysicsJoint { + PhysicsJointWeld( + PhysicsBody bodyA, + PhysicsBody bodyB) : super(bodyA, bodyB); + + 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); + } +}
diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index 4510289..69d7482 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart
@@ -83,6 +83,13 @@ void _removeBodiesScheduledForDestruction() { for (box2d.Body b2Body in _bodiesScheduledForDestruction) { + // Destroy any joints before destroying the body + PhysicsBody body = b2Body.userData; + for (PhysicsJoint joint in body._joints) { + joint._detach(); + } + + // Destroy the body b2World.destroyBody(b2Body); } _bodiesScheduledForDestruction.clear();
diff --git a/packages/flutter_sprites/lib/skysprites.dart b/packages/flutter_sprites/lib/skysprites.dart index ad662c6..6ffd26d 100644 --- a/packages/flutter_sprites/lib/skysprites.dart +++ b/packages/flutter_sprites/lib/skysprites.dart
@@ -33,6 +33,7 @@ part 'node_with_size.dart'; part 'particle_system.dart'; part 'physics_body.dart'; +part 'physics_joint.dart'; part 'physics_node.dart'; part 'physics_shape.dart'; part 'sound.dart';