Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
76b04cdd
Commit
76b04cdd
authored
May 04, 2016
by
Viktor Lidholt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor sprite physics, part 1 (#3711)
parent
4d88752c
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1 addition
and
2278 deletions
+1
-2278
flutter_sprites.dart
packages/flutter_sprites/lib/flutter_sprites.dart
+0
-8
node.dart
packages/flutter_sprites/lib/src/node.dart
+1
-185
physics_body.dart
packages/flutter_sprites/lib/src/physics_body.dart
+0
-549
physics_collision_groups.dart
...ges/flutter_sprites/lib/src/physics_collision_groups.dart
+0
-40
physics_debug.dart
packages/flutter_sprites/lib/src/physics_debug.dart
+0
-113
physics_group.dart
packages/flutter_sprites/lib/src/physics_group.dart
+0
-124
physics_joint.dart
packages/flutter_sprites/lib/src/physics_joint.dart
+0
-593
physics_shape.dart
packages/flutter_sprites/lib/src/physics_shape.dart
+0
-191
physics_world.dart
packages/flutter_sprites/lib/src/physics_world.dart
+0
-448
sprite_box.dart
packages/flutter_sprites/lib/src/sprite_box.dart
+0
-27
No files found.
packages/flutter_sprites/lib/flutter_sprites.dart
View file @
76b04cdd
...
@@ -12,7 +12,6 @@ import 'dart:math' as math;
...
@@ -12,7 +12,6 @@ import 'dart:math' as math;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
show
Image
;
import
'dart:ui'
as
ui
show
Image
;
import
'package:box2d/box2d.dart'
as
box2d
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/scheduler.dart'
;
...
@@ -35,13 +34,6 @@ part 'src/node.dart';
...
@@ -35,13 +34,6 @@ part 'src/node.dart';
part
'src/node3d.dart'
;
part
'src/node3d.dart'
;
part
'src/node_with_size.dart'
;
part
'src/node_with_size.dart'
;
part
'src/particle_system.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'
;
part
'src/physics_shape.dart'
;
part
'src/physics_world.dart'
;
part
'src/sound.dart'
;
part
'src/sound.dart'
;
part
'src/sprite.dart'
;
part
'src/sprite.dart'
;
part
'src/sprite_box.dart'
;
part
'src/sprite_box.dart'
;
...
...
packages/flutter_sprites/lib/src/node.dart
View file @
76b04cdd
...
@@ -134,72 +134,10 @@ class Node {
...
@@ -134,72 +134,10 @@ class Node {
void
set
rotation
(
double
rotation
)
{
void
set
rotation
(
double
rotation
)
{
assert
(
rotation
!=
null
);
assert
(
rotation
!=
null
);
if
(
_physicsBody
!=
null
&&
(
parent
is
PhysicsWorld
||
parent
is
PhysicsGroup
))
{
_updatePhysicsRotation
(
physicsBody
,
rotation
,
parent
);
return
;
}
_rotation
=
rotation
;
_rotation
=
rotation
;
invalidateTransformMatrix
();
invalidateTransformMatrix
();
}
}
void
_updatePhysicsRotation
(
PhysicsBody
body
,
double
rotation
,
Node
physicsParent
)
{
PhysicsWorld
world
=
_physicsWorld
(
physicsParent
);
if
(
world
==
null
)
return
;
world
.
_updateRotation
(
body
,
_rotationToPhysics
(
rotation
,
physicsParent
));
}
PhysicsWorld
_physicsWorld
(
Node
parent
)
{
if
(
parent
is
PhysicsWorld
)
{
return
parent
;
}
else
if
(
parent
is
PhysicsGroup
)
{
return
_physicsWorld
(
parent
.
parent
);
}
else
{
assert
(
false
);
return
null
;
}
}
double
_rotationToPhysics
(
double
rotation
,
Node
physicsParent
)
{
if
(
physicsParent
is
PhysicsWorld
)
{
return
rotation
;
}
else
if
(
physicsParent
is
PhysicsGroup
)
{
return
_rotationToPhysics
(
rotation
+
physicsParent
.
rotation
,
physicsParent
.
parent
);
}
else
{
assert
(
false
);
return
null
;
}
}
double
_rotationFromPhysics
(
double
rotation
,
Node
physicsParent
)
{
if
(
physicsParent
is
PhysicsWorld
)
{
return
rotation
;
}
else
if
(
physicsParent
is
PhysicsGroup
)
{
return
_rotationToPhysics
(
rotation
-
physicsParent
.
rotation
,
physicsParent
.
parent
);
}
else
{
assert
(
false
);
return
null
;
}
}
void
_setRotationFromPhysics
(
double
rotation
,
Node
physicsParent
)
{
assert
(
rotation
!=
null
);
_rotation
=
_rotationFromPhysics
(
rotation
,
physicsParent
);
invalidateTransformMatrix
();
}
void
teleportRotation
(
double
rotation
)
{
assert
(
rotation
!=
null
);
if
(
_physicsBody
!=
null
&&
(
parent
is
PhysicsWorld
||
parent
is
PhysicsGroup
))
{
rotation
=
_rotationToPhysics
(
rotation
,
parent
);
_physicsBody
.
_body
.
setTransform
(
_physicsBody
.
_body
.
position
,
radians
(
rotation
));
_physicsBody
.
_body
.
angularVelocity
=
0.0
;
_physicsBody
.
_body
.
setType
(
box2d
.
BodyType
.
STATIC
);
}
_setRotationFromPhysics
(
rotation
,
parent
);
}
/// The position of this node relative to its parent.
/// The position of this node relative to its parent.
///
///
...
@@ -209,74 +147,10 @@ class Node {
...
@@ -209,74 +147,10 @@ class Node {
void
set
position
(
Point
position
)
{
void
set
position
(
Point
position
)
{
assert
(
position
!=
null
);
assert
(
position
!=
null
);
if
(
_physicsBody
!=
null
&&
(
parent
is
PhysicsWorld
||
parent
is
PhysicsGroup
))
{
_updatePhysicsPosition
(
this
.
physicsBody
,
position
,
parent
);
return
;
}
_position
=
position
;
_position
=
position
;
invalidateTransformMatrix
();
invalidateTransformMatrix
();
}
}
void
_updatePhysicsPosition
(
PhysicsBody
body
,
Point
position
,
Node
physicsParent
)
{
PhysicsWorld
world
=
_physicsWorld
(
physicsParent
);
if
(
world
==
null
)
return
;
world
.
_updatePosition
(
body
,
_positionToPhysics
(
position
,
physicsParent
));
}
Point
_positionToPhysics
(
Point
position
,
Node
physicsParent
)
{
if
(
physicsParent
is
PhysicsWorld
)
{
return
position
;
}
else
if
(
physicsParent
is
PhysicsGroup
)
{
// Transform the position
Vector4
parentPos
=
physicsParent
.
transformMatrix
.
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
{
assert
(
false
);
return
null
;
}
}
void
_setPositionFromPhysics
(
Point
position
,
Node
physicsParent
)
{
assert
(
position
!=
null
);
_position
=
_positionFromPhysics
(
position
,
physicsParent
);
invalidateTransformMatrix
();
}
Point
_positionFromPhysics
(
Point
position
,
Node
physicsParent
)
{
if
(
physicsParent
is
PhysicsWorld
)
{
return
position
;
}
else
if
(
physicsParent
is
PhysicsGroup
)
{
// Transform the position
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
{
assert
(
false
);
return
null
;
}
}
void
teleportPosition
(
Point
position
)
{
assert
(
position
!=
null
);
PhysicsWorld
world
=
_physicsWorld
(
parent
);
if
(
_physicsBody
!=
null
&&
(
parent
is
PhysicsWorld
||
parent
is
PhysicsGroup
))
{
position
=
_positionToPhysics
(
position
,
parent
);
_physicsBody
.
_body
.
setTransform
(
new
Vector2
(
position
.
x
/
world
.
b2WorldToNodeConversionFactor
,
position
.
y
/
world
.
b2WorldToNodeConversionFactor
),
_physicsBody
.
_body
.
getAngle
()
);
_physicsBody
.
_body
.
linearVelocity
=
new
Vector2
.
zero
();
_physicsBody
.
_body
.
setType
(
box2d
.
BodyType
.
STATIC
);
}
_setPositionFromPhysics
(
position
,
parent
);
}
/// The skew along the x-axis of this node in degrees.
/// The skew along the x-axis of this node in degrees.
///
///
/// myNode.skewX = 45.0;
/// myNode.skewX = 45.0;
...
@@ -330,30 +204,10 @@ class Node {
...
@@ -330,30 +204,10 @@ class Node {
void
set
scale
(
double
scale
)
{
void
set
scale
(
double
scale
)
{
assert
(
scale
!=
null
);
assert
(
scale
!=
null
);
if
(
_physicsBody
!=
null
&&
(
parent
is
PhysicsWorld
||
parent
is
PhysicsGroup
))
{
_updatePhysicsScale
(
physicsBody
,
scale
,
parent
);
}
_scaleX
=
_scaleY
=
scale
;
_scaleX
=
_scaleY
=
scale
;
invalidateTransformMatrix
();
invalidateTransformMatrix
();
}
}
void
_updatePhysicsScale
(
PhysicsBody
body
,
double
scale
,
Node
physicsParent
)
{
if
(
physicsParent
==
null
)
return
;
_physicsWorld
(
physicsParent
).
_updateScale
(
body
,
_scaleToPhysics
(
scale
,
physicsParent
));
}
double
_scaleToPhysics
(
double
scale
,
Node
physicsParent
)
{
if
(
physicsParent
is
PhysicsWorld
)
{
return
scale
;
}
else
if
(
physicsParent
is
PhysicsGroup
)
{
return
_scaleToPhysics
(
scale
*
physicsParent
.
scale
,
physicsParent
.
parent
);
}
else
{
assert
(
false
);
return
null
;
}
}
/// The horizontal scale of this node relative its parent.
/// The horizontal scale of this node relative its parent.
///
///
/// myNode.scaleX = 5.0;
/// myNode.scaleX = 5.0;
...
@@ -361,7 +215,6 @@ class Node {
...
@@ -361,7 +215,6 @@ class Node {
void
set
scaleX
(
double
scaleX
)
{
void
set
scaleX
(
double
scaleX
)
{
assert
(
scaleX
!=
null
);
assert
(
scaleX
!=
null
);
assert
(
physicsBody
==
null
);
_scaleX
=
scaleX
;
_scaleX
=
scaleX
;
invalidateTransformMatrix
();
invalidateTransformMatrix
();
...
@@ -374,7 +227,6 @@ class Node {
...
@@ -374,7 +227,6 @@ class Node {
void
set
scaleY
(
double
scaleY
)
{
void
set
scaleY
(
double
scaleY
)
{
assert
(
scaleY
!=
null
);
assert
(
scaleY
!=
null
);
assert
(
physicsBody
==
null
);
_scaleY
=
scaleY
;
_scaleY
=
scaleY
;
invalidateTransformMatrix
();
invalidateTransformMatrix
();
...
@@ -403,7 +255,6 @@ class Node {
...
@@ -403,7 +255,6 @@ class Node {
void
addChild
(
Node
child
)
{
void
addChild
(
Node
child
)
{
assert
(
child
!=
null
);
assert
(
child
!=
null
);
assert
(
child
.
_parent
==
null
);
assert
(
child
.
_parent
==
null
);
assert
(!(
child
is
PhysicsGroup
)
||
this
is
PhysicsGroup
||
this
is
PhysicsWorld
);
assert
(()
{
assert
(()
{
Node
node
=
this
;
Node
node
=
this
;
...
@@ -420,10 +271,6 @@ class Node {
...
@@ -420,10 +271,6 @@ class Node {
_childrenLastAddedOrder
+=
1
;
_childrenLastAddedOrder
+=
1
;
child
.
_addedOrder
=
_childrenLastAddedOrder
;
child
.
_addedOrder
=
_childrenLastAddedOrder
;
if
(
_spriteBox
!=
null
)
_spriteBox
.
_registerNode
(
child
);
if
(
_spriteBox
!=
null
)
_spriteBox
.
_registerNode
(
child
);
if
(
child
is
PhysicsGroup
)
{
child
.
_attachGroup
(
child
,
child
.
_world
);
}
}
}
/// Removes a child from this node.
/// Removes a child from this node.
...
@@ -436,10 +283,6 @@ class Node {
...
@@ -436,10 +283,6 @@ class Node {
child
.
_spriteBox
=
null
;
child
.
_spriteBox
=
null
;
if
(
_spriteBox
!=
null
)
_spriteBox
.
_deregisterNode
(
child
);
if
(
_spriteBox
!=
null
)
_spriteBox
.
_deregisterNode
(
child
);
}
}
if
(
child
is
PhysicsGroup
)
{
child
.
_detachGroup
(
child
);
}
}
}
/// Removes this node from its parent node.
/// Removes this node from its parent node.
...
@@ -585,7 +428,7 @@ class Node {
...
@@ -585,7 +428,7 @@ class Node {
return
_transformMatrixBoxToNode
;
return
_transformMatrixBoxToNode
;
}
}
Matrix4
_inverse
Matrix
()
{
Matrix4
inverseTransform
Matrix
()
{
if
(
_transformMatrixInverse
==
null
)
{
if
(
_transformMatrixInverse
==
null
)
{
_transformMatrixInverse
=
new
Matrix4
.
copy
(
transformMatrix
);
_transformMatrixInverse
=
new
Matrix4
.
copy
(
transformMatrix
);
_transformMatrixInverse
.
invert
();
_transformMatrixInverse
.
invert
();
...
@@ -791,31 +634,4 @@ class Node {
...
@@ -791,31 +634,4 @@ class Node {
bool
handleEvent
(
SpriteBoxEvent
event
)
{
bool
handleEvent
(
SpriteBoxEvent
event
)
{
return
false
;
return
false
;
}
}
// Physics
PhysicsBody
_physicsBody
;
/// The physics body associated with this node. If a physics body is assigned,
/// and the node is a child of a [PhysicsWorld] or a [PhysicsGroup] the
/// node's position and rotation will be controlled by the body.
///
/// myNode.physicsBody = new PhysicsBody(
/// new PhysicsShapeCircle(Point.zero, 20.0)
/// );
PhysicsBody
get
physicsBody
=>
_physicsBody
;
void
set
physicsBody
(
PhysicsBody
physicsBody
)
{
if
(
parent
!=
null
)
{
assert
(
parent
is
PhysicsWorld
);
if
(
physicsBody
==
null
)
{
physicsBody
.
_detach
();
}
else
{
physicsBody
.
_attach
(
parent
,
this
);
}
}
_physicsBody
=
physicsBody
;
}
}
}
packages/flutter_sprites/lib/src/physics_body.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
enum
PhysicsBodyType
{
static
,
dynamic
}
/// A physics body can be assigned to any node to make it simulated by physics.
/// The body has a shape, and physical properties such as density, friction,
/// and velocity.
///
/// Bodies can be either dynamic or static. Dynamic bodies will move and rotate
/// the nodes that are associated with it. Static bodies can be moved by moving
/// or animating the node associated with them.
///
/// For a body to be simulated it needs to be associated with a [Node], through
/// the node's physicsBody property. The node also need to be a child of either
/// a [PhysicsWorld] or a [PhysicsGroup] (which in turn is a child of a
/// [PhysicsWorld] or a [Physics Group]).
class
PhysicsBody
{
PhysicsBody
(
this
.
shape
,
{
this
.
tag
:
null
,
this
.
type
:
PhysicsBodyType
.
dynamic
,
double
density:
1.0
,
double
friction:
0.0
,
double
restitution:
0.0
,
bool
isSensor:
false
,
Offset
linearVelocity:
Offset
.
zero
,
double
angularVelocity:
0.0
,
this
.
linearDampening
:
0.0
,
double
angularDampening:
0.0
,
bool
allowSleep:
true
,
bool
awake:
true
,
bool
fixedRotation:
false
,
bool
bullet:
false
,
bool
active:
true
,
this
.
gravityScale
:
1.0
,
String
collisionCategory:
"Default"
,
List
<
Object
>
collisionMask
})
{
this
.
density
=
density
;
this
.
friction
=
friction
;
this
.
restitution
=
restitution
;
this
.
isSensor
=
isSensor
;
this
.
linearVelocity
=
linearVelocity
;
this
.
angularVelocity
=
angularVelocity
;
this
.
angularDampening
=
angularDampening
;
this
.
allowSleep
=
allowSleep
;
this
.
awake
=
awake
;
this
.
fixedRotation
=
fixedRotation
;
this
.
bullet
=
bullet
;
this
.
active
=
active
;
this
.
collisionCategory
=
collisionCategory
;
this
.
collisionMask
=
collisionMask
;
}
Vector2
_lastPosition
;
double
_lastRotation
;
Vector2
_targetPosition
;
double
_targetAngle
;
double
_scale
;
/// An object associated with this body, normally used for detecting
/// collisions.
///
/// myBody.tag = "SpaceShip";
Object
tag
;
/// The shape of this physics body. The shape cannot be modified once the
/// body is created. If the shape is required to change, create a new body.
///
/// myShape = myBody.shape;
final
PhysicsShape
shape
;
/// The type of the body. This is either [PhysicsBodyType.dynamic] or
/// [PhysicsBodyType.static]. Dynamic bodies are simulated by the physics,
/// static objects affect the physics but are not moved by the physics.
///
/// myBody.type = PhysicsBodyType.static;
PhysicsBodyType
type
;
double
_density
;
/// The density of the body, default value is 1.0. The density has no specific
/// unit, instead densities are relative to each other.
///
/// myBody.density = 0.5;
double
get
density
=>
_density
;
void
set
density
(
double
density
)
{
_density
=
density
;
if
(
_body
==
null
)
return
;
for
(
box2d
.
Fixture
f
=
_body
.
getFixtureList
();
f
!=
null
;
f
=
f
.
getNext
())
{
f
.
setDensity
(
density
);
}
}
double
_friction
;
/// The fricion of the body, the default is 0.0 and the value should be in
/// the range of 0.0 to 1.0.
///
/// myBody.friction = 0.4;
double
get
friction
=>
_friction
;
void
set
friction
(
double
friction
)
{
_friction
=
friction
;
if
(
_body
==
null
)
return
;
for
(
box2d
.
Fixture
f
=
_body
.
getFixtureList
();
f
!=
null
;
f
=
f
.
getNext
())
{
f
.
setFriction
(
friction
);
}
}
double
_restitution
;
double
get
restitution
=>
_restitution
;
/// The restitution of the body, the default is 0.0 and the value should be in
/// the range of 0.0 to 1.0.
///
/// myBody.restitution = 0.5;
void
set
restitution
(
double
restitution
)
{
_restitution
=
restitution
;
if
(
_body
==
null
)
return
;
for
(
box2d
.
Fixture
f
=
_body
.
getFixtureList
();
f
!=
null
;
f
=
f
.
getNext
())
{
f
.
setRestitution
(
restitution
);
}
}
bool
_isSensor
;
/// True if the body is a sensor. Sensors doesn't collide with other bodies,
/// but will return collision callbacks. Use a sensor body to detect if two
/// bodies are overlapping.
///
/// myBody.isSensor = true;
bool
get
isSensor
=>
_isSensor
;
void
set
isSensor
(
bool
isSensor
)
{
_isSensor
=
isSensor
;
if
(
_body
==
null
)
return
;
for
(
box2d
.
Fixture
f
=
_body
.
getFixtureList
();
f
!=
null
;
f
=
f
.
getNext
())
{
f
.
setSensor
(
isSensor
);
}
}
Offset
_linearVelocity
;
/// The current linear velocity of the body in points / second.
///
/// myBody.velocity = Offset.zero;
Offset
get
linearVelocity
{
if
(
_body
==
null
)
return
_linearVelocity
;
else
{
double
dx
=
_body
.
linearVelocity
.
x
*
_physicsWorld
.
b2WorldToNodeConversionFactor
;
double
dy
=
_body
.
linearVelocity
.
y
*
_physicsWorld
.
b2WorldToNodeConversionFactor
;
return
new
Offset
(
dx
,
dy
);
}
}
void
set
linearVelocity
(
Offset
linearVelocity
)
{
_linearVelocity
=
linearVelocity
;
if
(
_body
!=
null
)
{
Vector2
vec
=
new
Vector2
(
linearVelocity
.
dx
/
_physicsWorld
.
b2WorldToNodeConversionFactor
,
linearVelocity
.
dy
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
_body
.
linearVelocity
=
vec
;
}
}
double
_angularVelocity
;
/// The angular velocity of the body in degrees / second.
///
/// myBody.angularVelocity = 0.0;
double
get
angularVelocity
{
if
(
_body
==
null
)
return
_angularVelocity
;
else
return
_body
.
angularVelocity
;
}
void
set
angularVelocity
(
double
angularVelocity
)
{
_angularVelocity
=
angularVelocity
;
if
(
_body
!=
null
)
{
_body
.
angularVelocity
=
angularVelocity
;
}
}
// TODO: Should this be editable in box2d.Body ?
/// Linear dampening, in the 0.0 to 1.0 range, default is 0.0.
///
/// double dampening = myBody.linearDampening;
final
double
linearDampening
;
double
_angularDampening
;
/// Angular dampening, in the 0.0 to 1.0 range, default is 0.0.
///
/// myBody.angularDampening = 0.1;
double
get
angularDampening
=>
_angularDampening
;
void
set
angularDampening
(
double
angularDampening
)
{
_angularDampening
=
angularDampening
;
if
(
_body
!=
null
)
_body
.
angularDamping
=
angularDampening
;
}
bool
_allowSleep
;
/// Allows the body to sleep if it hasn't moved.
///
/// myBody.allowSleep = false;
bool
get
allowSleep
=>
_allowSleep
;
void
set
allowSleep
(
bool
allowSleep
)
{
_allowSleep
=
allowSleep
;
if
(
_body
!=
null
)
_body
.
setSleepingAllowed
(
allowSleep
);
}
bool
_awake
;
/// True if the body is currently awake.
///
/// bool isAwake = myBody.awake;
bool
get
awake
{
if
(
_body
!=
null
)
return
_body
.
isAwake
();
else
return
_awake
;
}
void
set
awake
(
bool
awake
)
{
_awake
=
awake
;
if
(
_body
!=
null
)
_body
.
setAwake
(
awake
);
}
bool
_fixedRotation
;
/// If true, the body cannot be rotated by the physics simulation.
///
/// myBody.fixedRotation = true;
bool
get
fixedRotation
=>
_fixedRotation
;
void
set
fixedRotation
(
bool
fixedRotation
)
{
_fixedRotation
=
fixedRotation
;
if
(
_body
!=
null
)
_body
.
setFixedRotation
(
fixedRotation
);
}
bool
_bullet
;
bool
get
bullet
=>
_bullet
;
/// If true, the body cannot pass through other objects when moved at high
/// speed. Bullet bodies are slower to simulate, so only use this option
/// if neccessary.
///
/// myBody.bullet = true;
void
set
bullet
(
bool
bullet
)
{
_bullet
=
bullet
;
if
(
_body
!=
null
)
{
_body
.
setBullet
(
bullet
);
}
}
bool
_active
;
/// An active body is used in the physics simulation. Set this to false if
/// you want to temporarily exclude a body from the simulation.
///
/// myBody.active = false;
bool
get
active
{
if
(
_body
!=
null
)
return
_body
.
isActive
();
else
return
_active
;
}
void
set
active
(
bool
active
)
{
_active
=
active
;
if
(
_body
!=
null
)
_body
.
setActive
(
active
);
}
double
gravityScale
;
Object
_collisionCategory
;
/// The collision category assigned to this body. The default value is
/// "Default". The body will only collide with bodies that have the either
/// the [collisionMask] set to null or has the category in the mask.
///
/// myBody.collisionCategory = "Air";
Object
get
collisionCategory
{
return
_collisionCategory
;
}
void
set
collisionCategory
(
Object
collisionCategory
)
{
_collisionCategory
=
collisionCategory
;
_updateFilter
();
}
List
<
Object
>
_collisionMask
;
/// A list of collision categories that this object will collide with. If set
/// to null (the default value) the body will collide with all other bodies.
///
/// myBody.collisionMask = ["Air", "Ground"];
List
<
Object
>
get
collisionMask
=>
_collisionMask
;
void
set
collisionMask
(
List
<
Object
>
collisionMask
)
{
_collisionMask
=
collisionMask
;
_updateFilter
();
}
box2d
.
Filter
get
_b2Filter
{
print
(
"_physicsNode:
$_physicsWorld
groups:
${_physicsWorld._collisionGroups}
"
);
box2d
.
Filter
f
=
new
box2d
.
Filter
();
f
.
categoryBits
=
_physicsWorld
.
_collisionGroups
.
getBitmaskForKeys
([
_collisionCategory
]);
f
.
maskBits
=
_physicsWorld
.
_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
_physicsWorld
;
Node
_node
;
box2d
.
Body
_body
;
List
<
PhysicsJoint
>
_joints
=
<
PhysicsJoint
>[];
bool
_attached
=
false
;
/// Applies a force to the body at the [worldPoint] position in world
/// cordinates.
///
/// myBody.applyForce(new Offset(0.0, 100.0), myNode.position);
void
applyForce
(
Offset
force
,
Point
worldPoint
)
{
assert
(
_body
!=
null
);
Vector2
b2Force
=
new
Vector2
(
force
.
dx
/
_physicsWorld
.
b2WorldToNodeConversionFactor
,
force
.
dy
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
Vector2
b2Point
=
new
Vector2
(
worldPoint
.
x
/
_physicsWorld
.
b2WorldToNodeConversionFactor
,
worldPoint
.
y
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
_body
.
applyForce
(
b2Force
,
b2Point
);
}
/// Applice a force to the body at the its center of gravity.
///
/// myBody.applyForce(new Offset(0.0, 100.0));
void
applyForceToCenter
(
Offset
force
)
{
assert
(
_body
!=
null
);
Vector2
b2Force
=
new
Vector2
(
force
.
dx
/
_physicsWorld
.
b2WorldToNodeConversionFactor
,
force
.
dy
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
_body
.
applyForceToCenter
(
b2Force
);
}
/// Applies a torque to the body.
///
/// myBody.applyTorque(10.0);
void
applyTorque
(
double
torque
)
{
assert
(
_body
!=
null
);
_body
.
applyTorque
(
torque
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
}
/// Applies a linear impulse to the body at the [worldPoint] position in world
/// cordinates.
///
/// myBody.applyLinearImpulse(new Offset(0.0, 100.0), myNode.position);
void
applyLinearImpulse
(
Offset
impulse
,
Point
worldPoint
,
[
bool
wake
=
true
])
{
assert
(
_body
!=
null
);
Vector2
b2Impulse
=
new
Vector2
(
impulse
.
dx
/
_physicsWorld
.
b2WorldToNodeConversionFactor
,
impulse
.
dy
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
Vector2
b2Point
=
new
Vector2
(
worldPoint
.
x
/
_physicsWorld
.
b2WorldToNodeConversionFactor
,
worldPoint
.
y
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
_body
.
applyLinearImpulse
(
b2Impulse
,
b2Point
,
wake
);
}
/// Applies an angular impulse to the body.
///
/// myBody.applyAngularImpulse(20.0);
void
applyAngularImpulse
(
double
impulse
)
{
assert
(
_body
!=
null
);
_body
.
applyAngularImpulse
(
impulse
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
}
void
_attach
(
PhysicsWorld
physicsNode
,
Node
node
)
{
assert
(
_attached
==
false
);
_physicsWorld
=
physicsNode
;
// Account for physics groups
Point
positionWorld
=
node
.
_positionToPhysics
(
node
.
position
,
node
.
parent
);
double
rotationWorld
=
node
.
_rotationToPhysics
(
node
.
rotation
,
node
.
parent
);
double
scaleWorld
=
node
.
_scaleToPhysics
(
node
.
scale
,
node
.
parent
);
// Update scale
_scale
=
scaleWorld
;
// Create BodyDef
box2d
.
BodyDef
bodyDef
=
new
box2d
.
BodyDef
();
bodyDef
.
linearVelocity
=
new
Vector2
(
linearVelocity
.
dx
,
linearVelocity
.
dy
);
bodyDef
.
angularVelocity
=
angularVelocity
;
bodyDef
.
linearDamping
=
linearDampening
;
bodyDef
.
angularDamping
=
angularDampening
;
bodyDef
.
allowSleep
=
allowSleep
;
bodyDef
.
awake
=
awake
;
bodyDef
.
fixedRotation
=
fixedRotation
;
bodyDef
.
bullet
=
bullet
;
bodyDef
.
active
=
active
;
bodyDef
.
gravityScale
=
gravityScale
;
if
(
type
==
PhysicsBodyType
.
dynamic
)
bodyDef
.
type
=
box2d
.
BodyType
.
DYNAMIC
;
else
bodyDef
.
type
=
box2d
.
BodyType
.
STATIC
;
// Convert to world coordinates and set position and angle
double
conv
=
physicsNode
.
b2WorldToNodeConversionFactor
;
bodyDef
.
position
=
new
Vector2
(
positionWorld
.
x
/
conv
,
positionWorld
.
y
/
conv
);
bodyDef
.
angle
=
radians
(
rotationWorld
);
// Create Body
_body
=
physicsNode
.
b2World
.
createBody
(
bodyDef
);
_createFixtures
(
physicsNode
);
_body
.
userData
=
this
;
_node
=
node
;
_attached
=
true
;
// Attach any joints
for
(
PhysicsJoint
joint
in
_joints
)
{
if
(
joint
.
bodyA
.
_attached
&&
joint
.
bodyB
.
_attached
)
{
joint
.
_attach
(
physicsNode
);
}
}
}
void
_createFixtures
(
PhysicsWorld
physicsNode
)
{
// Create FixtureDef
box2d
.
FixtureDef
fixtureDef
=
new
box2d
.
FixtureDef
();
fixtureDef
.
friction
=
friction
;
fixtureDef
.
restitution
=
restitution
;
fixtureDef
.
density
=
density
;
fixtureDef
.
isSensor
=
isSensor
;
fixtureDef
.
filter
=
_b2Filter
;
// Get shapes
List
<
box2d
.
Shape
>
b2Shapes
=
<
box2d
.
Shape
>[];
List
<
PhysicsShape
>
physicsShapes
=
<
PhysicsShape
>[];
_addB2Shapes
(
physicsNode
,
shape
,
b2Shapes
,
physicsShapes
);
// Create fixtures
for
(
int
i
=
0
;
i
<
b2Shapes
.
length
;
i
++)
{
box2d
.
Shape
b2Shape
=
b2Shapes
[
i
];
PhysicsShape
physicsShape
=
physicsShapes
[
i
];
fixtureDef
.
shape
=
b2Shape
;
box2d
.
Fixture
fixture
=
_body
.
createFixtureFromFixtureDef
(
fixtureDef
);
fixture
.
userData
=
physicsShape
;
}
}
void
_detach
()
{
if
(
_attached
)
{
_physicsWorld
.
_bodiesScheduledForDestruction
.
add
(
_body
);
_attached
=
false
;
}
}
void
_updateScale
(
PhysicsWorld
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
(
PhysicsWorld
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
,
_scale
));
physicsShapes
.
add
(
shape
);
}
}
}
packages/flutter_sprites/lib/src/physics_collision_groups.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
class
_PhysicsCollisionGroups
{
_PhysicsCollisionGroups
()
{
// Make sure there is a default entry in the groups
getBitmaskForKeys
([
"Default"
]);
}
Map
<
Object
,
int
>
keyLookup
=
<
Object
,
int
>{};
List
<
Object
>
getKeysForBitmask
(
int
bitmask
)
{
List
<
Object
>
keys
=
[];
keyLookup
.
forEach
((
Object
key
,
int
value
)
{
if
(
value
&
bitmask
!=
0
)
{
keys
.
add
(
key
);
}
});
return
keys
;
}
int
getBitmaskForKeys
(
List
<
Object
>
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
;
}
}
packages/flutter_sprites/lib/src/physics_debug.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
class
_PhysicsDebugDraw
extends
box2d
.
DebugDraw
{
_PhysicsDebugDraw
(
box2d
.
ViewportTransform
transform
,
this
.
physicsWorld
)
:
super
(
transform
)
{
appendFlags
(
box2d
.
DebugDraw
.
JOINT_BIT
|
box2d
.
DebugDraw
.
CENTER_OF_MASS_BIT
|
box2d
.
DebugDraw
.
WIREFRAME_DRAWING_BIT
);
}
PhysicsWorld
physicsWorld
;
Canvas
canvas
;
@override
void
drawSegment
(
Vector2
p1
,
Vector2
p2
,
box2d
.
Color3i
color
)
{
Paint
paint
=
new
Paint
()
..
color
=
_toColor
(
color
)
..
strokeWidth
=
1.0
;
canvas
.
drawLine
(
_toPoint
(
p1
),
_toPoint
(
p2
),
paint
);
}
@override
void
drawSolidPolygon
(
List
<
Vector2
>
vertices
,
int
vertexCount
,
box2d
.
Color3i
color
)
{
Path
path
=
new
Path
();
Point
pt
=
_toPoint
(
vertices
[
0
]);
path
.
moveTo
(
pt
.
x
,
pt
.
y
);
for
(
int
i
=
1
;
i
<
vertexCount
;
i
++)
{
pt
=
_toPoint
(
vertices
[
i
]);
path
.
lineTo
(
pt
.
x
,
pt
.
y
);
}
Paint
paint
=
new
Paint
()..
color
=
_toColor
(
color
);
canvas
.
drawPath
(
path
,
paint
);
}
@override
void
drawCircle
(
Vector2
center
,
num
radius
,
box2d
.
Color3i
color
,
[
Vector2
axis
])
{
Paint
paint
=
new
Paint
()
..
color
=
_toColor
(
color
)
..
style
=
PaintingStyle
.
stroke
..
strokeWidth
=
1.0
;
canvas
.
drawCircle
(
_toPoint
(
center
),
_scale
(
radius
),
paint
);
}
@override
void
drawSolidCircle
(
Vector2
center
,
num
radius
,
Vector2
axis
,
box2d
.
Color3i
color
)
{
Paint
paint
=
new
Paint
()
..
color
=
_toColor
(
color
);
canvas
.
drawCircle
(
_toPoint
(
center
),
_scale
(
radius
),
paint
);
}
@override
void
drawPoint
(
Vector2
point
,
num
radiusOnScreen
,
box2d
.
Color3i
color
)
{
drawSolidCircle
(
point
,
radiusOnScreen
,
null
,
color
);
}
@override
void
drawParticles
(
List
<
Vector2
>
centers
,
double
radius
,
List
<
box2d
.
ParticleColor
>
colors
,
int
count
)
{
// TODO: Implement
}
@override
void
drawParticlesWireframe
(
List
<
Vector2
>
centers
,
double
radius
,
List
<
box2d
.
ParticleColor
>
colors
,
int
count
)
{
// TODO: Implement
}
@override
void
drawTransform
(
box2d
.
Transform
xf
,
box2d
.
Color3i
color
)
{
drawCircle
(
xf
.
p
,
0.1
,
color
);
// TODO: Improve
}
@override
void
drawStringXY
(
num
x
,
num
y
,
String
s
,
box2d
.
Color3i
color
)
{
// TODO: Implement
}
Color
_toColor
(
box2d
.
Color3i
color
)
{
return
new
Color
.
fromARGB
(
255
,
color
.
x
,
color
.
y
,
color
.
z
);
}
Point
_toPoint
(
Vector2
vec
)
{
return
new
Point
(
vec
.
x
*
physicsWorld
.
b2WorldToNodeConversionFactor
,
vec
.
y
*
physicsWorld
.
b2WorldToNodeConversionFactor
);
}
double
_scale
(
double
value
)
{
return
value
*
physicsWorld
.
b2WorldToNodeConversionFactor
;
}
}
packages/flutter_sprites/lib/src/physics_group.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
/// A [Node] that acts as a middle layer between a [PhysicsWorld] and a node
/// with an assigned [PhysicsBody]. The group's transformations are limited to
/// [position], [rotation], and uniform [scale].
///
/// PhysicsGroup group = new PhysicsGroup();
/// myWorld.addChild(group);
/// group.addChild(myNode);
class
PhysicsGroup
extends
Node
{
@override
void
set
scaleX
(
double
scaleX
)
{
assert
(
false
);
}
@override
void
set
scaleY
(
double
scaleX
)
{
assert
(
false
);
}
@override
void
set
skewX
(
double
scaleX
)
{
assert
(
false
);
}
@override
void
set
skewY
(
double
scaleX
)
{
assert
(
false
);
}
@override
void
set
physicsBody
(
PhysicsBody
body
)
{
assert
(
false
);
}
@override
void
set
position
(
Point
position
)
{
super
.
position
=
position
;
_invalidatePhysicsBodies
(
this
);
}
@override
void
set
rotation
(
double
rotation
)
{
super
.
rotation
=
rotation
;
_invalidatePhysicsBodies
(
this
);
}
@override
void
set
scale
(
double
scale
)
{
super
.
scale
=
scale
;
_invalidatePhysicsBodies
(
this
);
}
void
_invalidatePhysicsBodies
(
Node
node
)
{
if
(
_world
==
null
)
return
;
if
(
node
.
physicsBody
!=
null
)
{
// TODO: Add to list
_world
.
_bodiesScheduledForUpdate
.
add
(
node
.
physicsBody
);
}
for
(
Node
child
in
node
.
children
)
{
_invalidatePhysicsBodies
(
child
);
}
}
@override
void
addChild
(
Node
node
)
{
super
.
addChild
(
node
);
PhysicsWorld
world
=
_world
;
if
(
node
.
physicsBody
!=
null
&&
world
!=
null
)
{
node
.
physicsBody
.
_attach
(
world
,
node
);
}
if
(
node
is
PhysicsGroup
)
{
_attachGroup
(
this
,
world
);
}
}
void
_attachGroup
(
PhysicsGroup
group
,
PhysicsWorld
world
)
{
for
(
Node
child
in
group
.
children
)
{
if
(
child
is
PhysicsGroup
)
{
_attachGroup
(
child
,
world
);
}
else
if
(
child
.
physicsBody
!=
null
)
{
child
.
physicsBody
.
_attach
(
world
,
child
);
}
}
}
@override
void
removeChild
(
Node
node
)
{
super
.
removeChild
(
node
);
if
(
node
.
physicsBody
!=
null
)
{
node
.
physicsBody
.
_detach
();
}
if
(
node
is
PhysicsGroup
)
{
_detachGroup
(
this
);
}
}
void
_detachGroup
(
PhysicsGroup
group
)
{
for
(
Node
child
in
group
.
children
)
{
if
(
child
is
PhysicsGroup
)
{
_detachGroup
(
child
);
}
else
if
(
child
.
physicsBody
!=
null
)
{
child
.
physicsBody
.
_detach
();
}
}
}
PhysicsWorld
get
_world
{
if
(
this
.
parent
is
PhysicsWorld
)
return
this
.
parent
;
if
(
this
.
parent
is
PhysicsGroup
)
{
PhysicsGroup
group
=
this
.
parent
;
return
group
.
_world
;
}
return
null
;
}
}
packages/flutter_sprites/lib/src/physics_joint.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
typedef
void
PhysicsJointBreakCallback
(
PhysicsJoint
joint
);
/// A joint connects two physics bodies and restricts their movements. Some
/// types of joints also support motors that adds forces to the connected
/// bodies.
abstract
class
PhysicsJoint
{
PhysicsJoint
(
this
.
_bodyA
,
this
.
_bodyB
,
this
.
breakingForce
,
this
.
breakCallback
)
{
bodyA
.
_joints
.
add
(
this
);
bodyB
.
_joints
.
add
(
this
);
}
PhysicsBody
_bodyA
;
/// The first body connected to the joint.
///
/// PhysicsBody body = myJoint.bodyA;
PhysicsBody
get
bodyA
=>
_bodyA
;
PhysicsBody
_bodyB
;
/// The second body connected to the joint.
///
/// PhysicsBody body = myJoint.bodyB;
PhysicsBody
get
bodyB
=>
_bodyB
;
/// The maximum force the joint can handle before it breaks. If set to null,
/// the joint will never break.
final
double
breakingForce
;
final
PhysicsJointBreakCallback
breakCallback
;
bool
_active
=
true
;
box2d
.
Joint
_joint
;
PhysicsWorld
_physicsWorld
;
void
_completeCreation
()
{
if
(
bodyA
.
_attached
&&
bodyB
.
_attached
)
{
_attach
(
bodyA
.
_physicsWorld
);
}
}
void
_attach
(
PhysicsWorld
physicsNode
)
{
if
(
_joint
==
null
)
{
_physicsWorld
=
physicsNode
;
_joint
=
_createB2Joint
(
physicsNode
);
_physicsWorld
.
_joints
.
add
(
this
);
}
}
void
_detach
()
{
if
(
_joint
!=
null
&&
_active
)
{
_physicsWorld
.
b2World
.
destroyJoint
(
_joint
);
_joint
=
null
;
_physicsWorld
.
_joints
.
remove
(
this
);
}
_active
=
false
;
}
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
);
/// If the joint is no longer needed, call the the [destroy] method to detach
/// if from its connected bodies.
void
destroy
()
{
_detach
();
}
void
_checkBreakingForce
(
double
dt
)
{
if
(
breakingForce
==
null
)
return
;
if
(
_joint
!=
null
&&
_active
)
{
Vector2
reactionForce
=
new
Vector2
.
zero
();
_joint
.
getReactionForce
(
1.0
/
dt
,
reactionForce
);
if
(
breakingForce
*
breakingForce
<
reactionForce
.
length2
)
{
// Destroy the joint
destroy
();
// Notify any observer
if
(
breakCallback
!=
null
)
breakCallback
(
this
);
}
}
}
}
/// The revolute joint can be thought of as a hinge, a pin, or an axle.
/// An anchor point is defined in global space.
///
/// Revolute joints can be given limits so that the bodies can rotate only to a
/// certain point using [lowerAngle], [upperAngle], and [enableLimit].
/// They can also be given a motor using [enableMotore] together with
/// [motorSpeed] and [maxMotorTorque] so that the bodies will try
/// to rotate at a given speed, with a given torque.
///
/// Common uses for revolute joints include:
/// - wheels or rollers
/// - chains or swingbridges (using multiple revolute joints)
/// - rag-doll joints
/// - rotating doors, catapults, levers
///
/// new PhysicsJointRevolute(
/// nodeA.physicsBody,
/// nodeB.physicsBody,
/// nodeB.position
/// );
class
PhysicsJointRevolute
extends
PhysicsJoint
{
PhysicsJointRevolute
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
this
.
_worldAnchor
,
{
this
.
lowerAngle
:
0.0
,
this
.
upperAngle
:
0.0
,
this
.
enableLimit
:
false
,
PhysicsJointBreakCallback
breakCallback
,
double
breakingForce
,
bool
enableMotor:
false
,
double
motorSpeed:
0.0
,
double
maxMotorTorque:
0.0
})
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_enableMotor
=
enableMotor
;
_motorSpeed
=
motorSpeed
;
_maxMotorTorque
=
maxMotorTorque
;
_completeCreation
();
}
final
Point
_worldAnchor
;
/// The lower angle of the limits of this joint, only used if [enableLimit]
/// is set to true.
final
double
lowerAngle
;
/// The upper angle of the limits of this joint, only used if [enableLimit]
/// is set to true.
final
double
upperAngle
;
/// If set to true, the rotation will be limited to a value between
/// [lowerAngle] and [upperAngle].
final
bool
enableLimit
;
bool
_enableMotor
;
/// By setting enableMotor to true, the joint will automatically rotate, e.g.
/// this can be used for creating an engine for a wheel. For this to be
/// useful you also need to set [motorSpeed] and [maxMotorTorque].
bool
get
enableMotor
=>
_enableMotor
;
void
set
enableMotor
(
bool
enableMotor
)
{
_enableMotor
=
enableMotor
;
if
(
_joint
!=
null
)
{
box2d
.
RevoluteJoint
revoluteJoint
=
_joint
;
revoluteJoint
.
enableMotor
(
enableMotor
);
}
}
double
_motorSpeed
;
/// Sets the motor speed of this joint, will only work if [enableMotor] is
/// set to true and [maxMotorTorque] is set to a non zero value.
double
get
motorSpeed
=>
_motorSpeed
;
void
set
motorSpeed
(
double
motorSpeed
)
{
_motorSpeed
=
motorSpeed
;
if
(
_joint
!=
null
)
{
box2d
.
RevoluteJoint
revoluteJoint
=
_joint
;
revoluteJoint
.
setMotorSpeed
(
radians
(
motorSpeed
));
}
}
double
_maxMotorTorque
;
double
get
maxMotorTorque
=>
_maxMotorTorque
;
/// Sets the motor torque of this joint, will only work if [enableMotor] is
/// set to true and [motorSpeed] is set to a non zero value.
void
set
maxMotorTorque
(
double
maxMotorTorque
)
{
_maxMotorTorque
=
maxMotorTorque
;
if
(
_joint
!=
null
)
{
box2d
.
RevoluteJoint
revoluteJoint
=
_joint
;
revoluteJoint
.
setMaxMotorTorque
(
maxMotorTorque
);
}
}
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
// Create Joint Definition
Vector2
vecAnchor
=
new
Vector2
(
_worldAnchor
.
x
/
physicsNode
.
b2WorldToNodeConversionFactor
,
_worldAnchor
.
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
;
b2Def
.
enableMotor
=
_enableMotor
;
b2Def
.
motorSpeed
=
_motorSpeed
;
b2Def
.
maxMotorTorque
=
_maxMotorTorque
;
// Create joint
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// The prismatic joint is probably more commonly known as a slider joint.
/// The two joined bodies have their rotation held fixed relative to each
/// other, and they can only move along a specified axis.
///
/// Prismatic joints can be given limits so that the bodies can only move
/// along the axis within a specific range. They can also be given a motor so
/// that the bodies will try to move at a given speed, with a given force.
///
/// Common uses for prismatic joints include:
/// - elevators
/// - moving platforms
/// - sliding doors
/// - pistons
///
/// new PhysicsJointPrismatic(
/// nodeA.physicsBody,
/// nodeB.physicsBody,
/// new Offset(0.0, 1.0)
/// );
class
PhysicsJointPrismatic
extends
PhysicsJoint
{
PhysicsJointPrismatic
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
this
.
axis
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
bool
enableMotor:
false
,
double
motorSpeed:
0.0
,
double
maxMotorForce:
0.0
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_enableMotor
=
enableMotor
;
_motorSpeed
=
motorSpeed
;
_maxMotorForce
=
maxMotorForce
;
_completeCreation
();
}
/// Axis that the movement is restricted to (in global space at the time of
/// creation)
final
Offset
axis
;
bool
_enableMotor
;
/// For the motor to be effective you also need to set [motorSpeed] and
/// [maxMotorForce].
bool
get
enableMotor
=>
_enableMotor
;
void
set
enableMotor
(
bool
enableMotor
)
{
_enableMotor
=
enableMotor
;
if
(
_joint
!=
null
)
{
box2d
.
PrismaticJoint
prismaticJoint
=
_joint
;
prismaticJoint
.
enableMotor
(
enableMotor
);
}
}
double
_motorSpeed
;
/// Sets the motor speed of this joint, will only work if [enableMotor] is
/// set to true and [maxMotorForce] is set to a non zero value.
double
get
motorSpeed
=>
_motorSpeed
;
void
set
motorSpeed
(
double
motorSpeed
)
{
_motorSpeed
=
motorSpeed
;
if
(
_joint
!=
null
)
{
box2d
.
PrismaticJoint
prismaticJoint
=
_joint
;
prismaticJoint
.
setMotorSpeed
(
motorSpeed
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
}
}
double
_maxMotorForce
;
/// Sets the motor force of this joint, will only work if [enableMotor] is
/// set to true and [motorSpeed] is set to a non zero value.
double
get
maxMotorForce
=>
_maxMotorForce
;
void
set
maxMotorForce
(
double
maxMotorForce
)
{
_maxMotorForce
=
maxMotorForce
;
if
(
_joint
!=
null
)
{
box2d
.
PrismaticJoint
prismaticJoint
=
_joint
;
prismaticJoint
.
setMaxMotorForce
(
maxMotorForce
/
_physicsWorld
.
b2WorldToNodeConversionFactor
);
}
}
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
PrismaticJointDef
b2Def
=
new
box2d
.
PrismaticJointDef
();
b2Def
.
initialize
(
bodyA
.
_body
,
bodyB
.
_body
,
bodyA
.
_body
.
position
,
new
Vector2
(
axis
.
dx
,
axis
.
dy
));
b2Def
.
enableMotor
=
_enableMotor
;
b2Def
.
motorSpeed
=
_motorSpeed
;
b2Def
.
maxMotorForce
=
_maxMotorForce
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// The weld joint attempts to constrain all relative motion between two bodies.
///
/// new PhysicsJointWeld(bodyA.physicsJoint, bodyB.physicsJoint)
class
PhysicsJointWeld
extends
PhysicsJoint
{
PhysicsJointWeld
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
this
.
dampening
:
0.0
,
this
.
frequency
:
0.0
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_completeCreation
();
}
final
double
dampening
;
final
double
frequency
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
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
);
b2Def
.
dampingRatio
=
dampening
;
b2Def
.
frequencyHz
=
frequency
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// A pulley is used to create an idealized pulley. The pulley connects two
/// bodies to ground and to each other. As one body goes up, the other goes
/// down.
///
/// The total length of the pulley rope is conserved according to the initial
/// configuration.
///
/// new PhysicsJointPulley(
/// nodeA.physicsBody,
/// nodeB.physicsBody,
/// new Point(0.0, 100.0),
/// new Point(100.0, 100.0),
/// nodeA.position,
/// nodeB.position,
/// 1.0
/// );
class
PhysicsJointPulley
extends
PhysicsJoint
{
PhysicsJointPulley
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
this
.
groundAnchorA
,
this
.
groundAnchorB
,
this
.
anchorA
,
this
.
anchorB
,
this
.
ratio
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_completeCreation
();
}
final
Point
groundAnchorA
;
final
Point
groundAnchorB
;
final
Point
anchorA
;
final
Point
anchorB
;
final
double
ratio
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
PulleyJointDef
b2Def
=
new
box2d
.
PulleyJointDef
();
b2Def
.
initialize
(
bodyA
.
_body
,
bodyB
.
_body
,
_convertPosToVec
(
groundAnchorA
,
physicsNode
),
_convertPosToVec
(
groundAnchorB
,
physicsNode
),
_convertPosToVec
(
anchorA
,
physicsNode
),
_convertPosToVec
(
anchorB
,
physicsNode
),
ratio
);
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// The gear joint can only connect revolute and/or prismatic joints.
///
/// Like the pulley ratio, you can specify a gear ratio. However, in this case
/// the gear ratio can be negative. Also keep in mind that when one joint is a
/// revolute joint (angular) and the other joint is prismatic (translation),
/// and then the gear ratio will have units of length or one over length.
///
/// new PhysicsJointGear(nodeA.physicsBody, nodeB.physicsBody);
class
PhysicsJointGear
extends
PhysicsJoint
{
PhysicsJointGear
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
this
.
ratio
:
1.0
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_completeCreation
();
}
/// The ratio of the rotation for bodyA relative bodyB.
final
double
ratio
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
GearJointDef
b2Def
=
new
box2d
.
GearJointDef
();
b2Def
.
bodyA
=
bodyA
.
_body
;
b2Def
.
bodyB
=
bodyB
.
_body
;
b2Def
.
ratio
=
ratio
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// Keeps a fixed distance between two bodies, [anchorA] and [anchorB] are
/// defined in world coordinates.
class
PhysicsJointDistance
extends
PhysicsJoint
{
PhysicsJointDistance
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
this
.
anchorA
,
this
.
anchorB
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
this
.
length
,
this
.
dampening
:
0.0
,
this
.
frequency
:
0.0
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_completeCreation
();
}
/// The anchor of bodyA in world coordinates at the time of creation.
final
Point
anchorA
;
/// The anchor of bodyB in world coordinates at the time of creation.
final
Point
anchorB
;
/// The desired distance between the joints, if not passed in at creation
/// it will be set automatically to the distance between the anchors at the
/// time of creation.
final
double
length
;
/// Dampening factor.
final
double
dampening
;
/// Dampening frequency.
final
double
frequency
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
DistanceJointDef
b2Def
=
new
box2d
.
DistanceJointDef
();
b2Def
.
initialize
(
bodyA
.
_body
,
bodyB
.
_body
,
_convertPosToVec
(
anchorA
,
physicsNode
),
_convertPosToVec
(
anchorB
,
physicsNode
)
);
b2Def
.
dampingRatio
=
dampening
;
b2Def
.
frequencyHz
=
frequency
;
if
(
length
!=
null
)
b2Def
.
length
=
length
/
physicsNode
.
b2WorldToNodeConversionFactor
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// The wheel joint restricts a point on bodyB to a line on bodyA. The wheel
/// joint also optionally provides a suspension spring.
class
PhysicsJointWheel
extends
PhysicsJoint
{
PhysicsJointWheel
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
this
.
anchor
,
this
.
axis
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
this
.
dampening
:
0.0
,
this
.
frequency
:
0.0
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_completeCreation
();
}
/// The rotational point in global space at the time of creation.
final
Point
anchor
;
/// The axis which to restrict the movement to.
final
Offset
axis
;
/// Dampening factor.
final
double
dampening
;
/// Dampening frequency.
final
double
frequency
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
WheelJointDef
b2Def
=
new
box2d
.
WheelJointDef
();
b2Def
.
initialize
(
bodyA
.
_body
,
bodyB
.
_body
,
_convertPosToVec
(
anchor
,
physicsNode
),
new
Vector2
(
axis
.
dx
,
axis
.
dy
)
);
b2Def
.
dampingRatio
=
dampening
;
b2Def
.
frequencyHz
=
frequency
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
/// The friction joint is used for top-down friction. The joint provides 2D
/// translational friction and angular friction.
class
PhysicsJointFriction
extends
PhysicsJoint
{
PhysicsJointFriction
(
PhysicsBody
bodyA
,
PhysicsBody
bodyB
,
this
.
anchor
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
this
.
maxForce
:
0.0
,
this
.
maxTorque
:
0.0
}
)
:
super
(
bodyA
,
bodyB
,
breakingForce
,
breakCallback
)
{
_completeCreation
();
}
final
Point
anchor
;
final
double
maxForce
;
final
double
maxTorque
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
FrictionJointDef
b2Def
=
new
box2d
.
FrictionJointDef
();
b2Def
.
initialize
(
bodyA
.
_body
,
bodyB
.
_body
,
_convertPosToVec
(
anchor
,
physicsNode
)
);
b2Def
.
maxForce
=
maxForce
/
physicsNode
.
b2WorldToNodeConversionFactor
;
b2Def
.
maxTorque
=
maxTorque
/
physicsNode
.
b2WorldToNodeConversionFactor
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
class
PhysicsJointConstantVolume
extends
PhysicsJoint
{
PhysicsJointConstantVolume
(
this
.
bodies
,
{
double
breakingForce
,
PhysicsJointBreakCallback
breakCallback
,
this
.
dampening
,
this
.
frequency
}
)
:
super
(
null
,
null
,
breakingForce
,
breakCallback
)
{
assert
(
bodies
.
length
>
2
);
_bodyA
=
bodies
[
0
];
_bodyB
=
bodies
[
1
];
_completeCreation
();
}
final
List
<
PhysicsBody
>
bodies
;
final
double
dampening
;
final
double
frequency
;
@override
box2d
.
Joint
_createB2Joint
(
PhysicsWorld
physicsNode
)
{
box2d
.
ConstantVolumeJointDef
b2Def
=
new
box2d
.
ConstantVolumeJointDef
();
for
(
PhysicsBody
body
in
bodies
)
{
b2Def
.
addBody
(
body
.
_body
);
}
b2Def
.
dampingRatio
=
dampening
;
b2Def
.
frequencyHz
=
frequency
;
return
physicsNode
.
b2World
.
createJoint
(
b2Def
);
}
}
Vector2
_convertPosToVec
(
Point
pt
,
PhysicsWorld
physicsNode
)
{
return
new
Vector2
(
pt
.
x
/
physicsNode
.
b2WorldToNodeConversionFactor
,
pt
.
y
/
physicsNode
.
b2WorldToNodeConversionFactor
);
}
packages/flutter_sprites/lib/src/physics_shape.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
/// Defines the shape of a [PhysicsBody].
abstract
class
PhysicsShape
{
box2d
.
Shape
_b2Shape
;
Object
userObject
;
box2d
.
Shape
getB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
if
(
_b2Shape
==
null
)
{
_b2Shape
=
_createB2Shape
(
node
,
scale
);
}
return
_b2Shape
;
}
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
);
void
_invalidate
()
{
_b2Shape
=
null
;
}
}
/// Defines a circle shape with a given center [point] and [radius].
///
/// var shape = PhysicsShapeCircle(Point.origin, 20.0);
class
PhysicsShapeCircle
extends
PhysicsShape
{
PhysicsShapeCircle
(
this
.
point
,
this
.
radius
);
final
Point
point
;
final
double
radius
;
@override
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
box2d
.
CircleShape
shape
=
new
box2d
.
CircleShape
();
shape
.
p
.
x
=
scale
*
point
.
x
/
node
.
b2WorldToNodeConversionFactor
;
shape
.
p
.
y
=
scale
*
point
.
y
/
node
.
b2WorldToNodeConversionFactor
;
shape
.
radius
=
scale
*
radius
/
node
.
b2WorldToNodeConversionFactor
;
return
shape
;
}
}
/// Defines a polygon shape from a list of [points];
///
/// var points = [
/// new Point(-10.0, 0.0),
/// new Point(0.0, 10.0),
/// new Point(10.0, 0.0)
/// ];
/// var shape = new PhysicsShapePolygon(points);
class
PhysicsShapePolygon
extends
PhysicsShape
{
PhysicsShapePolygon
(
this
.
points
);
final
List
<
Point
>
points
;
@override
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
List
<
Vector2
>
vectors
=
<
Vector2
>[];
for
(
Point
point
in
points
)
{
Vector2
vec
=
new
Vector2
(
scale
*
point
.
x
/
node
.
b2WorldToNodeConversionFactor
,
scale
*
point
.
y
/
node
.
b2WorldToNodeConversionFactor
);
vectors
.
add
(
vec
);
}
box2d
.
PolygonShape
shape
=
new
box2d
.
PolygonShape
();
shape
.
set
(
vectors
,
vectors
.
length
);
return
shape
;
}
}
/// Defines a box shape from a [width] and [height].
///
/// var shape = new PhysicsShapeBox(50.0, 100.0);
class
PhysicsShapeBox
extends
PhysicsShape
{
PhysicsShapeBox
(
this
.
width
,
this
.
height
,
[
this
.
center
=
Point
.
origin
,
this
.
rotation
=
0.0
]);
final
double
width
;
final
double
height
;
final
Point
center
;
final
double
rotation
;
@override
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
box2d
.
PolygonShape
shape
=
new
box2d
.
PolygonShape
();
shape
.
setAsBox
(
scale
*
width
/
node
.
b2WorldToNodeConversionFactor
,
scale
*
height
/
node
.
b2WorldToNodeConversionFactor
,
new
Vector2
(
scale
*
center
.
x
/
node
.
b2WorldToNodeConversionFactor
,
scale
*
center
.
y
/
node
.
b2WorldToNodeConversionFactor
),
radians
(
rotation
)
);
return
shape
;
}
}
/// Defines a chain shape from a set of [points]. This can be used to create
/// a continuous chain of edges or, if [loop] is set to true, concave polygons.
///
/// var points = [
/// new Point(-10.0, 0.0),
/// new Point(0.0, 10.0),
/// new Point(10.0, 0.0)
/// ];
/// var shape = new PhysicsShapeChain(points);
class
PhysicsShapeChain
extends
PhysicsShape
{
PhysicsShapeChain
(
this
.
points
,
[
this
.
loop
=
false
]);
final
List
<
Point
>
points
;
final
bool
loop
;
@override
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
List
<
Vector2
>
vectors
=
<
Vector2
>[];
for
(
Point
point
in
points
)
{
Vector2
vec
=
new
Vector2
(
scale
*
point
.
x
/
node
.
b2WorldToNodeConversionFactor
,
scale
*
point
.
y
/
node
.
b2WorldToNodeConversionFactor
);
vectors
.
add
(
vec
);
}
box2d
.
ChainShape
shape
=
new
box2d
.
ChainShape
();
if
(
loop
)
shape
.
createLoop
(
vectors
,
vectors
.
length
);
else
shape
.
createChain
(
vectors
,
vectors
.
length
);
return
shape
;
}
}
/// Defines a single edge line shape from [pointA] to [pointB].
///
/// var shape = new PhysicsShapeEdge(
/// new Point(20.0, 20.0),
/// new Point(50.0, 20.0)
/// );
class
PhysicsShapeEdge
extends
PhysicsShape
{
PhysicsShapeEdge
(
this
.
pointA
,
this
.
pointB
);
final
Point
pointA
;
final
Point
pointB
;
@override
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
box2d
.
EdgeShape
shape
=
new
box2d
.
EdgeShape
();
shape
.
set
(
new
Vector2
(
scale
*
pointA
.
x
/
node
.
b2WorldToNodeConversionFactor
,
scale
*
pointA
.
y
/
node
.
b2WorldToNodeConversionFactor
),
new
Vector2
(
scale
*
pointB
.
x
/
node
.
b2WorldToNodeConversionFactor
,
scale
*
pointB
.
y
/
node
.
b2WorldToNodeConversionFactor
)
);
return
shape
;
}
}
/// A group combines several [shapes] into a single shape.
///
/// var s0 = new PhysicsShapeCircle(new Point(-10.0, 0.0), 20.0);
/// var s1 = new PhysicsShapeCircle(new Point(10.0, 0.0), 20.0);
/// var shape = new PhysicsShapeGroup([s0, s1]);
class
PhysicsShapeGroup
extends
PhysicsShape
{
PhysicsShapeGroup
(
this
.
shapes
);
final
List
<
PhysicsShape
>
shapes
;
@override
box2d
.
Shape
_createB2Shape
(
PhysicsWorld
node
,
double
scale
)
{
return
null
;
}
@override
void
_invalidate
()
{
for
(
PhysicsShape
shape
in
shapes
)
{
shape
.
_invalidate
();
}
}
}
packages/flutter_sprites/lib/src/physics_world.dart
deleted
100644 → 0
View file @
4d88752c
part of
flutter_sprites
;
enum
PhysicsContactType
{
preSolve
,
postSolve
,
begin
,
end
}
typedef
void
PhysicsContactCallback
(
PhysicsContactType
type
,
PhysicsContact
contact
);
/// A [Node] that performs a 2D physics simulation on any children with a
/// [PhysicsBody] attached. To simulate grand children, they need to be placed
/// in a [PhysicsGroup].
///
/// The PhysicsWorld uses Box2D.dart to perform the actual simulation, but
/// wraps its behavior in a way that is more integrated with the sprite node
/// tree. If needed, you can still access the Box2D world through the [b2World]
/// property.
class
PhysicsWorld
extends
Node
{
PhysicsWorld
(
Offset
gravity
)
{
b2World
=
new
box2d
.
World
.
withGravity
(
new
Vector2
(
gravity
.
dx
/
b2WorldToNodeConversionFactor
,
gravity
.
dy
/
b2WorldToNodeConversionFactor
));
_init
();
}
PhysicsWorld
.
fromB2World
(
this
.
b2World
,
this
.
b2WorldToNodeConversionFactor
)
{
_init
();
}
void
_init
()
{
_contactHandler
=
new
_ContactHandler
(
this
);
b2World
.
setContactListener
(
_contactHandler
);
box2d
.
ViewportTransform
transform
=
new
box2d
.
ViewportTransform
(
new
Vector2
.
zero
(),
new
Vector2
.
zero
(),
1.0
);
_debugDraw
=
new
_PhysicsDebugDraw
(
transform
,
this
);
b2World
.
debugDraw
=
_debugDraw
;
}
/// The Box2D world used to perform the physics simulations.
box2d
.
World
b2World
;
_ContactHandler
_contactHandler
;
_PhysicsCollisionGroups
_collisionGroups
=
new
_PhysicsCollisionGroups
();
List
<
PhysicsJoint
>
_joints
=
<
PhysicsJoint
>[];
List
<
box2d
.
Body
>
_bodiesScheduledForDestruction
=
<
box2d
.
Body
>[];
List
<
PhysicsBody
>
_bodiesScheduledForUpdate
=
<
PhysicsBody
>[];
/// If set to true, a debug image of all physics shapes and joints will
/// be drawn on top of the [SpriteBox].
bool
drawDebug
=
false
;
Matrix4
_debugDrawTransform
;
_PhysicsDebugDraw
_debugDraw
;
/// The conversion factor that is used to convert points in the physics world
/// node to points in the Box2D physics simulation.
double
b2WorldToNodeConversionFactor
=
10.0
;
/// The gravity vector used in the simulation.
Offset
get
gravity
{
Vector2
g
=
b2World
.
getGravity
();
return
new
Offset
(
g
.
x
,
g
.
y
);
}
void
set
gravity
(
Offset
gravity
)
{
// Convert from points/s^2 to m/s^2
b2World
.
setGravity
(
new
Vector2
(
gravity
.
dx
/
b2WorldToNodeConversionFactor
,
gravity
.
dy
/
b2WorldToNodeConversionFactor
));
}
/// If set to true, objects can fall asleep if the haven't moved in a while.
bool
get
allowSleep
=>
b2World
.
isAllowSleep
();
void
set
allowSleep
(
bool
allowSleep
)
{
b2World
.
setAllowSleep
(
allowSleep
);
}
/// True if sub stepping should be used in the simulation.
bool
get
subStepping
=>
b2World
.
isSubStepping
();
void
set
subStepping
(
bool
subStepping
)
{
b2World
.
setSubStepping
(
subStepping
);
}
void
_stepPhysics
(
double
dt
)
{
// Update transformations of bodies whose groups have moved
for
(
PhysicsBody
body
in
_bodiesScheduledForUpdate
)
{
Node
node
=
body
.
_node
;
node
.
_updatePhysicsPosition
(
body
,
node
.
position
,
node
.
parent
);
node
.
_updatePhysicsRotation
(
body
,
node
.
rotation
,
node
.
parent
);
}
_bodiesScheduledForUpdate
.
clear
();
// 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
||
body
.
_targetPosition
==
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
||
body
.
_targetAngle
==
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
);
// Iterate over the bodies
for
(
box2d
.
Body
b2Body
=
b2World
.
bodyList
;
b2Body
!=
null
;
b2Body
=
b2Body
.
getNext
())
{
// Update visual position and rotation
PhysicsBody
body
=
b2Body
.
userData
;
if
(
b2Body
.
getType
()
==
box2d
.
BodyType
.
KINEMATIC
)
{
body
.
_targetPosition
=
null
;
body
.
_targetAngle
=
null
;
}
// Update visual position and rotation
if
(
body
.
type
==
PhysicsBodyType
.
dynamic
)
{
body
.
_node
.
_setPositionFromPhysics
(
new
Point
(
b2Body
.
position
.
x
*
b2WorldToNodeConversionFactor
,
b2Body
.
position
.
y
*
b2WorldToNodeConversionFactor
),
body
.
_node
.
parent
);
body
.
_node
.
_setRotationFromPhysics
(
degrees
(
b2Body
.
getAngle
()),
body
.
_node
.
parent
);
}
}
// Break joints
for
(
PhysicsJoint
joint
in
_joints
)
{
joint
.
_checkBreakingForce
(
dt
);
}
// Remove bodies that were marked for destruction during the simulation
_removeBodiesScheduledForDestruction
();
}
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
();
}
void
_updatePosition
(
PhysicsBody
body
,
Point
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
();
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
);
body
.
_body
.
setAwake
(
true
);
}
void
_updateScale
(
PhysicsBody
body
,
double
scale
)
{
body
.
_scale
=
scale
;
if
(
body
.
_attached
)
{
body
.
_updateScale
(
this
);
}
}
@override
void
addChild
(
Node
node
)
{
super
.
addChild
(
node
);
if
(
node
.
physicsBody
!=
null
)
{
node
.
physicsBody
.
_attach
(
this
,
node
);
}
}
@override
void
removeChild
(
Node
node
)
{
super
.
removeChild
(
node
);
if
(
node
.
physicsBody
!=
null
)
{
node
.
physicsBody
.
_detach
();
}
}
/// Adds a contact callback, the callback will be invoked when bodies collide
/// in the world.
///
/// To match specific sets bodies, use the [tagA] and [tagB]
/// which will be matched to the tag property that is set on the
/// [PhysicsBody]. If [tagA] or [tagB] is set to null, it will match any
/// body.
///
/// By default, callbacks are made at four different times during a
/// collision; preSolve, postSolve, begin, and end. If you are only interested
/// in one of these events you can pass in a [type].
///
/// myWorld.addContactCallback(
/// (PhysicsContactType type, PhysicsContact contact) {
/// print("Collision between ship and asteroid");
/// },
/// "Ship",
/// "Asteroid",
/// PhysicsContactType.begin
/// );
void
addContactCallback
(
PhysicsContactCallback
callback
,
Object
tagA
,
Object
tagB
,
[
PhysicsContactType
type
])
{
_contactHandler
.
addContactCallback
(
callback
,
tagA
,
tagB
,
type
);
}
@override
void
paint
(
Canvas
canvas
)
{
if
(
drawDebug
)
{
_debugDrawTransform
=
new
Matrix4
.
fromFloat64List
(
canvas
.
getTotalMatrix
());
}
super
.
paint
(
canvas
);
}
/// Draws the debug data of the physics world, normally this method isn't
/// invoked directly. Instead, set the [drawDebug] property to true.
void
paintDebug
(
Canvas
canvas
)
{
_debugDraw
.
canvas
=
canvas
;
b2World
.
drawDebugData
();
}
}
/// Contains information about a physics collision and is normally passed back
/// in callbacks from the [PhysicsWorld].
///
/// void myCallback(PhysicsContactType type, PhysicsContact contact) {
/// if (contact.isTouching)
/// print("Bodies are touching");
/// }
class
PhysicsContact
{
PhysicsContact
(
this
.
nodeA
,
this
.
nodeB
,
this
.
shapeA
,
this
.
shapeB
,
this
.
isTouching
,
this
.
isEnabled
,
this
.
touchingPoints
,
this
.
touchingNormal
);
/// The first node as matched in the rules set when adding the callback.
final
Node
nodeA
;
/// The second node as matched in the rules set when adding the callback.
final
Node
nodeB
;
/// The first shape as matched in the rules set when adding the callback.
final
PhysicsShape
shapeA
;
/// The second shape as matched in the rules set when adding the callback.
final
PhysicsShape
shapeB
;
/// True if the two nodes are touching.
final
bool
isTouching
;
/// To ignore the collision to take place, you can set isEnabled to false
/// during the preSolve phase.
bool
isEnabled
;
/// List of points that are touching, in world coordinates.
final
List
<
Point
>
touchingPoints
;
/// The normal from [shapeA] to [shapeB] at the touchingPoint.
final
Offset
touchingNormal
;
}
class
_ContactCallbackInfo
{
_ContactCallbackInfo
(
this
.
callback
,
this
.
tagA
,
this
.
tagB
,
this
.
type
);
PhysicsContactCallback
callback
;
Object
tagA
;
Object
tagB
;
PhysicsContactType
type
;
}
class
_ContactHandler
extends
box2d
.
ContactListener
{
_ContactHandler
(
this
.
physicsNode
);
PhysicsWorld
physicsNode
;
List
<
_ContactCallbackInfo
>
callbackInfos
=
<
_ContactCallbackInfo
>[];
void
addContactCallback
(
PhysicsContactCallback
callback
,
Object
tagA
,
Object
tagB
,
PhysicsContactType
type
)
{
callbackInfos
.
add
(
new
_ContactCallbackInfo
(
callback
,
tagA
,
tagB
,
type
));
}
void
handleCallback
(
PhysicsContactType
type
,
box2d
.
Contact
b2Contact
,
box2d
.
Manifold
oldManifold
,
box2d
.
ContactImpulse
impulse
)
{
// Get info about the contact
PhysicsBody
bodyA
=
b2Contact
.
fixtureA
.
getBody
().
userData
;
PhysicsBody
bodyB
=
b2Contact
.
fixtureB
.
getBody
().
userData
;
box2d
.
Fixture
fixtureA
=
b2Contact
.
fixtureA
;
box2d
.
Fixture
fixtureB
=
b2Contact
.
fixtureB
;
// Match callback with added callbacks
for
(
_ContactCallbackInfo
info
in
callbackInfos
)
{
// Check that type is matching
if
(
info
.
type
!=
null
&&
info
.
type
!=
type
)
continue
;
// Check if there is a match
bool
matchA
=
(
info
.
tagA
==
null
)
||
info
.
tagA
==
bodyA
.
tag
;
bool
matchB
=
(
info
.
tagB
==
null
)
||
info
.
tagB
==
bodyB
.
tag
;
bool
match
=
(
matchA
&&
matchB
);
if
(!
match
)
{
// Check if there is a match if we swap a & b
bool
matchA
=
(
info
.
tagA
==
null
)
||
info
.
tagA
==
bodyB
.
tag
;
bool
matchB
=
(
info
.
tagB
==
null
)
||
info
.
tagB
==
bodyA
.
tag
;
match
=
(
matchA
&&
matchB
);
if
(
match
)
{
// Swap a & b
PhysicsBody
tempBody
=
bodyA
;
bodyA
=
bodyB
;
bodyB
=
tempBody
;
box2d
.
Fixture
tempFixture
=
fixtureA
;
fixtureA
=
fixtureB
;
fixtureB
=
tempFixture
;
}
}
if
(
match
)
{
// We have contact and a matched callback, setup contact info
List
<
Point
>
touchingPoints
;
Offset
touchingNormal
;
// Fetch touching points, if any
if
(
b2Contact
.
isTouching
())
{
box2d
.
WorldManifold
manifold
=
new
box2d
.
WorldManifold
();
b2Contact
.
getWorldManifold
(
manifold
);
touchingNormal
=
new
Offset
(
manifold
.
normal
.
x
,
manifold
.
normal
.
y
);
touchingPoints
=
<
Point
>[];
for
(
Vector2
vec
in
manifold
.
points
)
{
touchingPoints
.
add
(
new
Point
(
vec
.
x
*
physicsNode
.
b2WorldToNodeConversionFactor
,
vec
.
y
*
physicsNode
.
b2WorldToNodeConversionFactor
));
}
}
// Create the contact
PhysicsContact
contact
=
new
PhysicsContact
(
bodyA
.
_node
,
bodyB
.
_node
,
fixtureA
.
userData
,
fixtureB
.
userData
,
b2Contact
.
isTouching
(),
b2Contact
.
isEnabled
(),
touchingPoints
,
touchingNormal
);
// Make callback
info
.
callback
(
type
,
contact
);
// Update Box2D contact
b2Contact
.
setEnabled
(
contact
.
isEnabled
);
}
}
}
@override
void
beginContact
(
box2d
.
Contact
contact
)
{
handleCallback
(
PhysicsContactType
.
begin
,
contact
,
null
,
null
);
}
@override
void
endContact
(
box2d
.
Contact
contact
)
{
handleCallback
(
PhysicsContactType
.
end
,
contact
,
null
,
null
);
}
@override
void
preSolve
(
box2d
.
Contact
contact
,
box2d
.
Manifold
oldManifold
)
{
handleCallback
(
PhysicsContactType
.
preSolve
,
contact
,
oldManifold
,
null
);
}
@override
void
postSolve
(
box2d
.
Contact
contact
,
box2d
.
ContactImpulse
impulse
)
{
handleCallback
(
PhysicsContactType
.
postSolve
,
contact
,
null
,
impulse
);
}
}
packages/flutter_sprites/lib/src/sprite_box.dart
View file @
76b04cdd
...
@@ -126,8 +126,6 @@ class SpriteBox extends RenderBox {
...
@@ -126,8 +126,6 @@ class SpriteBox extends RenderBox {
List
<
Node
>
_constrainedNodes
;
List
<
Node
>
_constrainedNodes
;
List
<
PhysicsWorld
>
_physicsNodes
;
Rect
_visibleArea
;
Rect
_visibleArea
;
Rect
get
visibleArea
{
Rect
get
visibleArea
{
...
@@ -158,14 +156,12 @@ class SpriteBox extends RenderBox {
...
@@ -158,14 +156,12 @@ class SpriteBox extends RenderBox {
void
_registerNode
(
Node
node
)
{
void
_registerNode
(
Node
node
)
{
_actionControllers
=
null
;
_actionControllers
=
null
;
_eventTargets
=
null
;
_eventTargets
=
null
;
_physicsNodes
=
null
;
if
(
node
==
null
||
node
.
constraints
!=
null
)
_constrainedNodes
=
null
;
if
(
node
==
null
||
node
.
constraints
!=
null
)
_constrainedNodes
=
null
;
}
}
void
_deregisterNode
(
Node
node
)
{
void
_deregisterNode
(
Node
node
)
{
_actionControllers
=
null
;
_actionControllers
=
null
;
_eventTargets
=
null
;
_eventTargets
=
null
;
_physicsNodes
=
null
;
if
(
node
==
null
||
node
.
constraints
!=
null
)
_constrainedNodes
=
null
;
if
(
node
==
null
||
node
.
constraints
!=
null
)
_constrainedNodes
=
null
;
}
}
...
@@ -356,17 +352,6 @@ class SpriteBox extends RenderBox {
...
@@ -356,17 +352,6 @@ class SpriteBox extends RenderBox {
Matrix4
totalMatrix
=
new
Matrix4
.
fromFloat64List
(
canvas
.
getTotalMatrix
());
Matrix4
totalMatrix
=
new
Matrix4
.
fromFloat64List
(
canvas
.
getTotalMatrix
());
_rootNode
.
_visit
(
canvas
,
totalMatrix
);
_rootNode
.
_visit
(
canvas
,
totalMatrix
);
// Draw physics debug
if
(
_physicsNodes
==
null
)
_rebuildActionControllersAndPhysicsNodes
();
for
(
PhysicsWorld
world
in
_physicsNodes
)
{
if
(
world
.
drawDebug
)
{
canvas
.
setMatrix
(
world
.
_debugDrawTransform
.
storage
);
world
.
paintDebug
(
canvas
);
}
}
canvas
.
restore
();
canvas
.
restore
();
}
}
...
@@ -398,7 +383,6 @@ class SpriteBox extends RenderBox {
...
@@ -398,7 +383,6 @@ class SpriteBox extends RenderBox {
_callConstraintsPreUpdate
(
delta
);
_callConstraintsPreUpdate
(
delta
);
_runActions
(
delta
);
_runActions
(
delta
);
_callUpdate
(
_rootNode
,
delta
);
_callUpdate
(
_rootNode
,
delta
);
_callStepPhysics
(
delta
);
_callConstraintsConstrain
(
delta
);
_callConstraintsConstrain
(
delta
);
}
}
...
@@ -420,13 +404,11 @@ class SpriteBox extends RenderBox {
...
@@ -420,13 +404,11 @@ class SpriteBox extends RenderBox {
void
_rebuildActionControllersAndPhysicsNodes
()
{
void
_rebuildActionControllersAndPhysicsNodes
()
{
_actionControllers
=
<
ActionController
>[];
_actionControllers
=
<
ActionController
>[];
_physicsNodes
=
<
PhysicsWorld
>[];
_addActionControllersAndPhysicsNodes
(
_rootNode
);
_addActionControllersAndPhysicsNodes
(
_rootNode
);
}
}
void
_addActionControllersAndPhysicsNodes
(
Node
node
)
{
void
_addActionControllersAndPhysicsNodes
(
Node
node
)
{
if
(
node
.
_actions
!=
null
)
_actionControllers
.
add
(
node
.
_actions
);
if
(
node
.
_actions
!=
null
)
_actionControllers
.
add
(
node
.
_actions
);
if
(
node
is
PhysicsWorld
)
_physicsNodes
.
add
(
node
);
for
(
int
i
=
node
.
children
.
length
-
1
;
i
>=
0
;
i
--)
{
for
(
int
i
=
node
.
children
.
length
-
1
;
i
>=
0
;
i
--)
{
Node
child
=
node
.
children
[
i
];
Node
child
=
node
.
children
[
i
];
...
@@ -444,15 +426,6 @@ class SpriteBox extends RenderBox {
...
@@ -444,15 +426,6 @@ class SpriteBox extends RenderBox {
}
}
}
}
void
_callStepPhysics
(
double
dt
)
{
if
(
_physicsNodes
==
null
)
_rebuildActionControllersAndPhysicsNodes
();
for
(
PhysicsWorld
physicsNode
in
_physicsNodes
)
{
physicsNode
.
_stepPhysics
(
dt
);
}
}
void
_callConstraintsPreUpdate
(
double
dt
)
{
void
_callConstraintsPreUpdate
(
double
dt
)
{
if
(
_constrainedNodes
==
null
)
{
if
(
_constrainedNodes
==
null
)
{
_constrainedNodes
=
<
Node
>[];
_constrainedNodes
=
<
Node
>[];
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment