From 8799c62549ed8a29e1ac92f913d30e1700b2796d Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 15 Oct 2015 14:43:48 -0700 Subject: [PATCH 1/3] Remember last position in sprite physics --- skysprites/lib/src/physics_body.dart | 3 +++ skysprites/lib/src/physics_node.dart | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/skysprites/lib/src/physics_body.dart b/skysprites/lib/src/physics_body.dart index 0517d7b7024..270f8efb390 100644 --- a/skysprites/lib/src/physics_body.dart +++ b/skysprites/lib/src/physics_body.dart @@ -40,6 +40,9 @@ class PhysicsBody { this.active = active; } + Vector2 _lastPosition; + double _lastRotation; + Object tag; final PhysicsShape shape; diff --git a/skysprites/lib/src/physics_node.dart b/skysprites/lib/src/physics_node.dart index f95bb2df5af..1cff1aa9372 100644 --- a/skysprites/lib/src/physics_node.dart +++ b/skysprites/lib/src/physics_node.dart @@ -113,6 +113,9 @@ class PhysicsNode extends Node { } void _updatePosition(PhysicsBody body, Point position) { + if (body._lastPosition == null) + body._lastPosition = body._body.position; + Vector2 newPos = new Vector2( position.x / b2WorldToNodeConversionFactor, position.y / b2WorldToNodeConversionFactor @@ -123,6 +126,9 @@ class PhysicsNode extends Node { } void _updateRotation(PhysicsBody body, double rotation) { + if (body._lastRotation == null) + body._lastRotation = body._body.getAngle(); + Vector2 pos = body._body.position; double newAngle = radians(rotation); body._body.setTransform(pos, newAngle); From eff62325b2d07257c2ef052de0794ec8b39c889e Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 15 Oct 2015 17:01:47 -0700 Subject: [PATCH 2/3] Animated sprite physics bodies now correctly transfers energy to dynamic bodies --- skysprites/lib/src/physics_body.dart | 2 ++ skysprites/lib/src/physics_node.dart | 47 +++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/skysprites/lib/src/physics_body.dart b/skysprites/lib/src/physics_body.dart index 270f8efb390..8b8d22ff980 100644 --- a/skysprites/lib/src/physics_body.dart +++ b/skysprites/lib/src/physics_body.dart @@ -42,6 +42,8 @@ class PhysicsBody { Vector2 _lastPosition; double _lastRotation; + Vector2 _targetPosition; + double _targetAngle; Object tag; diff --git a/skysprites/lib/src/physics_node.dart b/skysprites/lib/src/physics_node.dart index 1cff1aa9372..12685c0c5c3 100644 --- a/skysprites/lib/src/physics_node.dart +++ b/skysprites/lib/src/physics_node.dart @@ -74,6 +74,37 @@ class PhysicsNode extends Node { // Remove bodies that were marked for destruction during the update phase _removeBodiesScheduledForDestruction(); + // Assign velocities and momentum to static and kinetic bodies + for (box2d.Body b2Body = b2World.bodyList; b2Body != null; b2Body = b2Body.getNext()) { + // Fetch body + PhysicsBody body = b2Body.userData; + + // Skip all dynamic bodies + if (b2Body.getType() == box2d.BodyType.DYNAMIC) { + body._lastPosition = null; + body._lastRotation = null; + continue; + } + + // Update linear velocity + if (body._lastPosition == null) { + b2Body.linearVelocity.setZero(); + } else { + Vector2 velocity = (body._targetPosition - body._lastPosition) / dt; + b2Body.linearVelocity = velocity; + body._lastPosition = null; + } + + // Update angular velocity + if (body._lastRotation == null) { + b2Body.angularVelocity = 0.0; + } else { + double angularVelocity = (body._targetAngle - body._lastRotation) / dt; + b2Body.angularVelocity = angularVelocity; + body._lastRotation = 0.0; + } + } + // Calculate a step in the simulation b2World.stepDt(dt, 10, 10); @@ -113,22 +144,30 @@ class PhysicsNode extends Node { } void _updatePosition(PhysicsBody body, Point position) { - if (body._lastPosition == null) - body._lastPosition = body._body.position; + if (body._lastPosition == null && body.type == PhysicsBodyType.static) { + body._lastPosition = new Vector2.copy(body._body.position); + body._body.setType(box2d.BodyType.KINEMATIC); + } Vector2 newPos = new Vector2( position.x / b2WorldToNodeConversionFactor, position.y / b2WorldToNodeConversionFactor ); double angle = body._body.getAngle(); - body._body.setTransform(newPos, angle); + + if (body.type == PhysicsBodyType.dynamic) { + body._body.setTransform(newPos, angle); + } else { + body._targetPosition = newPos; + body._targetAngle = angle; + } body._body.setAwake(true); } void _updateRotation(PhysicsBody body, double rotation) { if (body._lastRotation == null) body._lastRotation = body._body.getAngle(); - + Vector2 pos = body._body.position; double newAngle = radians(rotation); body._body.setTransform(pos, newAngle); From 477b231b6388db32181df5d1876aab095d0475b1 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 15 Oct 2015 17:08:51 -0700 Subject: [PATCH 3/3] Updates physics test --- examples/game/test_physics.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index ecadb2f6f0a..059acfb8c55 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:flutter/animation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; @@ -52,7 +53,7 @@ class TestBed extends NodeWithSize { _physicsNode = new PhysicsNode(new Offset(0.0, 100.0)); _obstacle = new Sprite(_spriteSheet["ship.png"]); - _obstacle.position = new Point(532.0, 800.0); + _obstacle.position = new Point(512.0, 800.0); _obstacle.size = new Size(64.0, 64.0); _obstacle.physicsBody = new PhysicsBody( new PhysicsShapeCircle(Point.origin, 32.0), @@ -63,6 +64,13 @@ class TestBed extends NodeWithSize { _physicsNode.addChild(_obstacle); _physicsNode.addContactCallback(myCallback, "obstacle", "ship", PhysicsContactType.begin); + // Animate obstacle + ActionSequence seq = new ActionSequence([ + new ActionTween((a) => _obstacle.position = a, new Point(256.0, 800.0), new Point(768.0, 800.0), 1.0, easeInOut), + new ActionTween((a) => _obstacle.position = a, new Point(768.0, 800.0), new Point(256.0, 800.0), 1.0, easeInOut) + ]); + _obstacle.actions.run(new ActionRepeatForever(seq)); + addChild(_physicsNode); userInteractionEnabled = true;