diff --git a/packages/flutter_sprites/lib/flutter_sprites.dart b/packages/flutter_sprites/lib/flutter_sprites.dart index 97b48b3d5d..41f6830113 100644 --- a/packages/flutter_sprites/lib/flutter_sprites.dart +++ b/packages/flutter_sprites/lib/flutter_sprites.dart @@ -34,6 +34,7 @@ part 'src/node3d.dart'; part 'src/node_with_size.dart'; part 'src/particle_system.dart'; part 'src/physics_body.dart'; +part 'src/physics_collision_groups.dart'; part 'src/physics_debug.dart'; part 'src/physics_group.dart'; part 'src/physics_joint.dart'; diff --git a/packages/flutter_sprites/lib/src/node.dart b/packages/flutter_sprites/lib/src/node.dart index a36cc7783f..b49707fed8 100644 --- a/packages/flutter_sprites/lib/src/node.dart +++ b/packages/flutter_sprites/lib/src/node.dart @@ -24,6 +24,7 @@ class Node { double _rotation = 0.0; Matrix4 _transformMatrix = new Matrix4.identity(); + Matrix4 _transformMatrixInverse; Matrix4 _transformMatrixNodeToBox; Matrix4 _transformMatrixBoxToNode; @@ -246,9 +247,7 @@ class Node { return position; } else if (physicsParent is PhysicsGroup) { // Transform the position - Matrix4 inverseTransform = new Matrix4.copy(physicsParent.transformMatrix); - inverseTransform.invert(); - Vector4 parentPos = inverseTransform.transform(new Vector4(position.x, position.y, 0.0, 1.0)); + Vector4 parentPos = physicsParent._inverseMatrix().transform(new Vector4(position.x, position.y, 0.0, 1.0)); Point newPos = new Point(parentPos.x, parentPos.y); return _positionToPhysics(newPos, physicsParent.parent); } else { @@ -531,6 +530,7 @@ class Node { /// changes that affects the matrix. void invalidateTransformMatrix() { _transformMatrix = null; + _transformMatrixInverse = null; _invalidateToBoxTransformMatrix(); } @@ -575,6 +575,14 @@ class Node { return _transformMatrixBoxToNode; } + Matrix4 _inverseMatrix() { + if (_transformMatrixInverse == null) { + _transformMatrixInverse = new Matrix4.copy(transformMatrix); + _transformMatrixInverse.invert(); + } + return _transformMatrixInverse; + } + /// Converts a point from the coordinate system of the [SpriteBox] to the local coordinate system of the node. /// /// This method is particularly useful when handling pointer events and need the pointers position in a local diff --git a/packages/flutter_sprites/lib/src/physics_body.dart b/packages/flutter_sprites/lib/src/physics_body.dart index 62e5df5400..7d91dda1ea 100644 --- a/packages/flutter_sprites/lib/src/physics_body.dart +++ b/packages/flutter_sprites/lib/src/physics_body.dart @@ -22,7 +22,9 @@ class PhysicsBody { bool fixedRotation: false, bool bullet: false, bool active: true, - this.gravityScale: 1.0 + this.gravityScale: 1.0, + collisionCategory: "Default", + collisionMask: null }) { this.density = density; this.friction = friction; @@ -38,6 +40,9 @@ class PhysicsBody { this.fixedRotation = fixedRotation; this.bullet = bullet; this.active = active; + + this.collisionCategory = collisionCategory; + this.collisionMask = collisionMask; } Vector2 _lastPosition; @@ -232,6 +237,46 @@ class PhysicsBody { double gravityScale; + Object _collisionCategory = null; + + Object get collisionCategory { + return _collisionCategory; + } + + set collisionCategory(Object collisionCategory) { + _collisionCategory = collisionCategory; + _updateFilter(); + } + + List _collisionMask = null; + + List get collisionMask => _collisionMask; + + set collisionMask(List collisionMask) { + _collisionMask = collisionMask; + _updateFilter(); + } + + box2d.Filter get _b2Filter { + print("_physicsNode: $_physicsNode groups: ${_physicsNode._collisionGroups}"); + box2d.Filter f = new box2d.Filter(); + f.categoryBits = _physicsNode._collisionGroups.getBitmaskForKeys([_collisionCategory]); + f.maskBits = _physicsNode._collisionGroups.getBitmaskForKeys(_collisionMask); + + print("Filter: $f category: ${f.categoryBits} mask: ${f.maskBits}"); + + return f; + } + + void _updateFilter() { + if (_body != null) { + box2d.Filter filter = _b2Filter; + for (box2d.Fixture fixture = _body.getFixtureList(); fixture != null; fixture = fixture.getNext()) { + fixture.setFilterData(filter); + } + } + } + PhysicsWorld _physicsNode; Node _node; @@ -296,6 +341,8 @@ class PhysicsBody { void _attach(PhysicsWorld physicsNode, Node node) { assert(_attached == false); + _physicsNode = physicsNode; + // Account for physics groups Point positionWorld = node._positionToPhysics(node.position, node.parent); double rotationWorld = node._rotationToPhysics(node.rotation, node.parent); @@ -333,7 +380,6 @@ class PhysicsBody { _body.userData = this; - _physicsNode = physicsNode; _node = node; _attached = true; @@ -353,6 +399,7 @@ class PhysicsBody { fixtureDef.restitution = restitution; fixtureDef.density = density; fixtureDef.isSensor = isSensor; + fixtureDef.filter = _b2Filter; // Get shapes List b2Shapes = []; diff --git a/packages/flutter_sprites/lib/src/physics_collision_groups.dart b/packages/flutter_sprites/lib/src/physics_collision_groups.dart new file mode 100644 index 0000000000..6c8a633705 --- /dev/null +++ b/packages/flutter_sprites/lib/src/physics_collision_groups.dart @@ -0,0 +1,40 @@ +part of flutter_sprites; + +class _PhysicsCollisionGroups { + + _PhysicsCollisionGroups() { + // Make sure there is a default entry in the groups + getBitmaskForKeys(["Default"]); + } + + Map keyLookup = {}; + + List getKeysForBitmask(int bitmask) { + List keys = []; + keyLookup.forEach((key, value) { + if (value & bitmask) { + keys.add(key); + } + }); + return key; + } + + int getBitmaskForKeys(List keys) { + if (keys == null) { + return 0xffff; + } + + int bitmask = 0; + + for (Object key in keys) { + int value = keyLookup[key]; + if (value == null) { + assert(keyLookup.length < 16); + value = 1 << keyLookup.length; + keyLookup[key] = value; + } + bitmask |= value; + } + return bitmask; + } +} diff --git a/packages/flutter_sprites/lib/src/physics_world.dart b/packages/flutter_sprites/lib/src/physics_world.dart index 6a792ca4c3..1472488245 100644 --- a/packages/flutter_sprites/lib/src/physics_world.dart +++ b/packages/flutter_sprites/lib/src/physics_world.dart @@ -39,6 +39,8 @@ class PhysicsWorld extends Node { _ContactHandler _contactHandler; + _PhysicsCollisionGroups _collisionGroups = new _PhysicsCollisionGroups(); + List _joints = []; List _bodiesScheduledForDestruction = [];