Commit 0ef9da85 authored by Viktor Lidholt's avatar Viktor Lidholt

Merge pull request #1672 from vlidholt/master

Makes sprite physics bodies scalable
parents 47c854b8 6f9fe7b1
......@@ -55,6 +55,7 @@ class TestBed extends NodeWithSize {
_obstacle = new Sprite(_spriteSheet["ship.png"]);
_obstacle.position = new Point(512.0, 800.0);
_obstacle.size = new Size(64.0, 64.0);
_obstacle.scale = 2.0;
_obstacle.physicsBody = new PhysicsBody(
new PhysicsShapeCircle(Point.origin, 32.0),
type: PhysicsBodyType.static,
......@@ -71,6 +72,12 @@ class TestBed extends NodeWithSize {
]);
_obstacle.actions.run(new ActionRepeatForever(seq));
seq = new ActionSequence([
new ActionTween((a) => _obstacle.scale = a, 1.0, 2.0, 2.0, easeInOut),
new ActionTween((a) => _obstacle.scale = a, 2.0, 1.0, 2.0, easeInOut)
]);
_obstacle.actions.run(new ActionRepeatForever(seq));
addChild(_physicsNode);
userInteractionEnabled = true;
......
......@@ -251,6 +251,12 @@ class Node {
void set scale(double scale) {
assert(scale != null);
if (_physicsBody != null && parent is PhysicsNode) {
PhysicsNode physicsNode = parent;
physicsNode._updateScale(this.physicsBody, scale);
}
_scaleX = _scaleY = scale;
invalidateTransformMatrix();
}
......@@ -262,6 +268,8 @@ class Node {
void set scaleX(double scaleX) {
assert(scaleX != null);
assert(physicsBody == null);
_scaleX = scaleX;
invalidateTransformMatrix();
}
......@@ -273,6 +281,8 @@ class Node {
void set scaleY(double scaleY) {
assert(scaleY != null);
assert(physicsBody == null);
_scaleY = scaleY;
invalidateTransformMatrix();
}
......
......@@ -45,6 +45,8 @@ class PhysicsBody {
Vector2 _targetPosition;
double _targetAngle;
double _scale;
Object tag;
final PhysicsShape shape;
......@@ -294,6 +296,9 @@ class PhysicsBody {
void _attach(PhysicsNode physicsNode, Node node) {
assert(_attached == false);
// Update scale
_scale = node.scale;
// Create BodyDef
box2d.BodyDef bodyDef = new box2d.BodyDef();
bodyDef.linearVelocity = new Vector2(linearVelocity.dx, linearVelocity.dy);
......@@ -318,6 +323,24 @@ class PhysicsBody {
// Create Body
_body = physicsNode.b2World.createBody(bodyDef);
_createFixtures(physicsNode);
_body.userData = this;
_physicsNode = physicsNode;
_node = node;
_attached = true;
// Attach any joints
for (PhysicsJoint joint in _joints) {
if (joint.bodyA._attached && joint.bodyB._attached) {
joint._attach(physicsNode);
}
}
}
void _createFixtures(PhysicsNode physicsNode) {
// Create FixtureDef
box2d.FixtureDef fixtureDef = new box2d.FixtureDef();
fixtureDef.friction = friction;
......@@ -339,19 +362,6 @@ class PhysicsBody {
box2d.Fixture fixture = _body.createFixtureFromFixtureDef(fixtureDef);
fixture.userData = physicsShape;
}
_body.userData = this;
_physicsNode = physicsNode;
_node = node;
_attached = true;
// Attach any joints
for (PhysicsJoint joint in _joints) {
if (joint.bodyA._attached && joint.bodyB._attached) {
joint._attach(physicsNode);
}
}
}
void _detach() {
......@@ -361,13 +371,26 @@ class PhysicsBody {
}
}
void _updateScale(PhysicsNode physicsNode) {
// Destroy old fixtures
for (box2d.Fixture fixture = _body.getFixtureList(); fixture != null; fixture = fixture.getNext()) {
_body.destroyFixture(fixture);
}
// Make sure we create new b2Shapes
shape._invalidate();
// Create new fixtures
_createFixtures(physicsNode);
}
void _addB2Shapes(PhysicsNode physicsNode, PhysicsShape shape, List<box2d.Shape> b2Shapes, List<PhysicsShape> physicsShapes) {
if (shape is PhysicsShapeGroup) {
for (PhysicsShape child in shape.shapes) {
_addB2Shapes(physicsNode, child, b2Shapes, physicsShapes);
}
} else {
b2Shapes.add(shape.getB2Shape(physicsNode));
b2Shapes.add(shape.getB2Shape(physicsNode, _scale));
physicsShapes.add(shape);
}
}
......
......@@ -181,6 +181,14 @@ class PhysicsNode extends Node {
body._body.setAwake(true);
}
void _updateScale(PhysicsBody body, double scale) {
body._scale = scale;
if (body._attached) {
body._updateScale(this);
}
}
void addChild(Node node) {
super.addChild(node);
if (node.physicsBody != null) {
......
......@@ -6,14 +6,18 @@ abstract class PhysicsShape {
Object userObject;
box2d.Shape getB2Shape(PhysicsNode node) {
box2d.Shape getB2Shape(PhysicsNode node, double scale) {
if (_b2Shape == null) {
_b2Shape = _createB2Shape(node);
_b2Shape = _createB2Shape(node, scale);
}
return _b2Shape;
}
box2d.Shape _createB2Shape(PhysicsNode node);
box2d.Shape _createB2Shape(PhysicsNode node, double scale);
void _invalidate() {
_b2Shape = null;
}
}
class PhysicsShapeCircle extends PhysicsShape {
......@@ -22,11 +26,11 @@ class PhysicsShapeCircle extends PhysicsShape {
final Point point;
final double radius;
box2d.Shape _createB2Shape(PhysicsNode node) {
box2d.Shape _createB2Shape(PhysicsNode node, double scale) {
box2d.CircleShape shape = new box2d.CircleShape();
shape.p.x = point.x / node.b2WorldToNodeConversionFactor;
shape.p.y = point.y / node.b2WorldToNodeConversionFactor;
shape.radius = radius / node.b2WorldToNodeConversionFactor;
shape.p.x = scale * point.x / node.b2WorldToNodeConversionFactor;
shape.p.y = scale * point.y / node.b2WorldToNodeConversionFactor;
shape.radius = scale * radius / node.b2WorldToNodeConversionFactor;
return shape;
}
}
......@@ -36,12 +40,12 @@ class PhysicsShapePolygon extends PhysicsShape {
final List<Point> points;
box2d.Shape _createB2Shape(PhysicsNode node) {
box2d.Shape _createB2Shape(PhysicsNode node, double scale) {
List<Vector2> vectors = [];
for (Point point in points) {
Vector2 vec = new Vector2(
point.x / node.b2WorldToNodeConversionFactor,
point.y / node.b2WorldToNodeConversionFactor
scale * point.x / node.b2WorldToNodeConversionFactor,
scale * point.y / node.b2WorldToNodeConversionFactor
);
vectors.add(vec);
}
......@@ -65,14 +69,14 @@ class PhysicsShapeBox extends PhysicsShape {
final Point center;
final double rotation;
box2d.Shape _createB2Shape(PhysicsNode node) {
box2d.Shape _createB2Shape(PhysicsNode node, double scale) {
box2d.PolygonShape shape = new box2d.PolygonShape();
shape.setAsBox(
width / node.b2WorldToNodeConversionFactor,
height / node.b2WorldToNodeConversionFactor,
scale * width / node.b2WorldToNodeConversionFactor,
scale * height / node.b2WorldToNodeConversionFactor,
new Vector2(
center.x / node.b2WorldToNodeConversionFactor,
center.y / node.b2WorldToNodeConversionFactor
scale * center.x / node.b2WorldToNodeConversionFactor,
scale * center.y / node.b2WorldToNodeConversionFactor
),
radians(rotation)
);
......@@ -86,12 +90,12 @@ class PhysicsShapeChain extends PhysicsShape {
final List<Point> points;
final bool loop;
box2d.Shape _createB2Shape(PhysicsNode node) {
box2d.Shape _createB2Shape(PhysicsNode node, double scale) {
List<Vector2> vectors = [];
for (Point point in points) {
Vector2 vec = new Vector2(
point.x / node.b2WorldToNodeConversionFactor,
point.y / node.b2WorldToNodeConversionFactor
scale * point.x / node.b2WorldToNodeConversionFactor,
scale * point.y / node.b2WorldToNodeConversionFactor
);
vectors.add(vec);
}
......@@ -111,16 +115,16 @@ class PhysicsShapeEdge extends PhysicsShape {
final Point pointA;
final Point pointB;
box2d.Shape _createB2Shape(PhysicsNode node) {
box2d.Shape _createB2Shape(PhysicsNode node, double scale) {
box2d.EdgeShape shape = new box2d.EdgeShape();
shape.set(
new Vector2(
pointA.x / node.b2WorldToNodeConversionFactor,
pointA.y / node.b2WorldToNodeConversionFactor
scale * pointA.x / node.b2WorldToNodeConversionFactor,
scale * pointA.y / node.b2WorldToNodeConversionFactor
),
new Vector2(
pointB.x / node.b2WorldToNodeConversionFactor,
pointB.y / node.b2WorldToNodeConversionFactor
scale * pointB.x / node.b2WorldToNodeConversionFactor,
scale * pointB.y / node.b2WorldToNodeConversionFactor
)
);
return shape;
......@@ -133,7 +137,13 @@ class PhysicsShapeGroup extends PhysicsShape {
final List<PhysicsShape> shapes;
box2d.Shape _createB2Shape(PhysicsNode node) {
box2d.Shape _createB2Shape(PhysicsNode node, double scale) {
return null;
}
void _invalidate() {
for (PhysicsShape shape in shapes) {
shape._invalidate();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment