From 95a0aceaa105ab6c36785e101b91f01da0a2b3de Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 8 Oct 2015 16:12:31 -0700 Subject: [PATCH] Adds basic support for joints in sprite physics --- .../flutter_sprites/lib/physics_body.dart | 9 ++ .../flutter_sprites/lib/physics_joint.dart | 90 +++++++++++++++++++ .../flutter_sprites/lib/physics_node.dart | 7 ++ packages/flutter_sprites/lib/skysprites.dart | 1 + 4 files changed, 107 insertions(+) create mode 100644 packages/flutter_sprites/lib/physics_joint.dart diff --git a/packages/flutter_sprites/lib/physics_body.dart b/packages/flutter_sprites/lib/physics_body.dart index 178b1ac48c0..40ee242c0fc 100644 --- a/packages/flutter_sprites/lib/physics_body.dart +++ b/packages/flutter_sprites/lib/physics_body.dart @@ -230,6 +230,8 @@ class PhysicsBody { box2d.Body _body; + List _joints = []; + bool _attached = false; void applyForce(Offset force, Point worldPoint) { @@ -338,6 +340,13 @@ class PhysicsBody { _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 00000000000..cecdd5c581c --- /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 4510289d93b..69d74829f0d 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -83,6 +83,13 @@ class PhysicsNode extends Node { 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 ad662c65d00..6ffd26de3db 100644 --- a/packages/flutter_sprites/lib/skysprites.dart +++ b/packages/flutter_sprites/lib/skysprites.dart @@ -33,6 +33,7 @@ part 'node3d.dart'; 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';