Skip to content

Commit 92c7ccb

Browse files
authored
fix: Destroy and create bodies after step is done (#106)
# Description This creates and destroys bodies after `stepDt` is done to avoid concurrency issues from destroying bodies based on for example taps or other gestures that can happen meanwhile `stepDt` is running. Fixes: flame-engine/flame#3712 ## Checklist <!-- Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (`[x]`). This will ensure a smooth and quick review process. --> - [x] The title of my PR starts with a [Conventional Commit] prefix (`fix:`, `feat:`, `docs:` etc). - [x] I have read the [Contributor Guide] and followed the process outlined for submitting PRs. - [ ] I have updated/added tests for ALL new/updated/fixed functionality. - [x] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`. - [x] I have updated/added relevant examples in `examples`. ## Breaking Change <!-- Does your PR require Flame users to manually update their apps to accommodate your change? If the PR is a breaking change this should be indicated with suffix "!" (for example, `feat!:`, `fix!:`). See [Conventional Commit] for details. --> - [ ] Yes, this is a breaking change. - [x] No, this is *not* a breaking change. ## Related Issues <!-- Provide a list of issues related to this PR from the [issue database]. Indicate which of these issues are resolved or fixed by this PR, i.e. Fixes #xxxx* !--> <!-- Links --> [issue database]: https://github.com/flame-engine/flame/issues [Contributor Guide]: https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md [Flame Style Guide]: https://github.com/flame-engine/flame/blob/main/STYLEGUIDE.md [Conventional Commit]: https://conventionalcommits.org
1 parent 4c35c4a commit 92c7ccb

File tree

4 files changed

+38
-18
lines changed

4 files changed

+38
-18
lines changed

packages/forge2d/lib/src/collision/broadphase/dynamic_tree.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ class DynamicTree implements BroadPhaseStrategy {
461461

462462
/// returns a node to the pool
463463
void _freeNode(DynamicTreeNode node) {
464-
assert(0 < _nodeCount);
464+
assert(_nodeCount > 0);
465465
node.parent = _freeList != nullNode ? _nodes[_freeList] : null;
466466
node.height = -1;
467467
_freeList = node.id;

packages/forge2d/lib/src/dynamics/contact_manager.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ class ContactManager implements PairCallback {
66
final Collision collision;
77
final Distance distance;
88
final List<Contact> contacts = [];
9-
ContactFilter? contactFilter;
9+
ContactFilter contactFilter;
1010
ContactListener? contactListener;
1111

12-
ContactManager(this.broadPhase, this.collision, this.distance) {
13-
contactFilter = ContactFilter();
14-
}
12+
ContactManager(this.broadPhase, this.collision, this.distance)
13+
: contactFilter = ContactFilter();
1514

1615
/// Broad-phase callback.
1716
@override
@@ -49,7 +48,7 @@ class ContactManager implements PairCallback {
4948
}
5049

5150
// Check user filtering.
52-
if (contactFilter?.shouldCollide(fixtureA, fixtureB) == false) {
51+
if (contactFilter.shouldCollide(fixtureA, fixtureB) == false) {
5352
return;
5453
}
5554

@@ -122,7 +121,7 @@ class ContactManager implements PairCallback {
122121
}
123122

124123
// Check user filtering.
125-
if (contactFilter?.shouldCollide(fixtureA, fixtureB) == false) {
124+
if (contactFilter.shouldCollide(fixtureA, fixtureB) == false) {
126125
contactRemovals.add(c);
127126
continue;
128127
}

packages/forge2d/lib/src/dynamics/world.dart

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class World {
2525
late ContactManager contactManager;
2626
final List<Body> bodies = <Body>[];
2727
final List<Joint> joints = <Joint>[];
28+
final List<Body> bodiesToCreate = <Body>[];
29+
final List<Body> bodiesToDestroy = <Body>[];
30+
final List<Joint> jointsToCreate = <Joint>[];
31+
final List<Joint> jointsToDestroy = <Joint>[];
2832

2933
final Vector2 _gravity;
3034

@@ -37,7 +41,7 @@ class World {
3741
///
3842
/// See also:
3943
///
40-
/// * [Body.gravityScale], to multipy [gravity] for a [Body].
44+
/// * [Body.gravityScale], to multiply [gravity] for a [Body].
4145
/// * [Body.gravityOverride], to change how the world treats the gravity for
4246
/// a [Body].
4347
/// {@endtemplate}
@@ -133,8 +137,11 @@ class World {
133137
///
134138
/// Warning: This function is locked during callbacks.
135139
Body createBody(BodyDef def) {
136-
assert(!isLocked);
137140
final body = Body(def, this);
141+
if (isLocked) {
142+
bodiesToCreate.add(body);
143+
return body;
144+
}
138145
bodies.add(body);
139146
return body;
140147
}
@@ -145,8 +152,10 @@ class World {
145152
/// Warning: This automatically deletes all associated shapes and joints.
146153
/// Warning: This function is locked during callbacks.
147154
void destroyBody(Body body) {
148-
assert(bodies.isNotEmpty);
149-
assert(!isLocked);
155+
if (isLocked) {
156+
bodiesToDestroy.add(body);
157+
return;
158+
}
150159

151160
// Delete the attached joints.
152161
while (body.joints.isNotEmpty) {
@@ -173,10 +182,11 @@ class World {
173182
/// This may cause the connected bodies to cease colliding.
174183
///
175184
/// Adding a joint doesn't wake up the bodies.
176-
///
177-
/// Warning: This function is locked during callbacks.
178185
void createJoint(Joint joint) {
179-
assert(!isLocked);
186+
if (isLocked) {
187+
jointsToCreate.add(joint);
188+
return;
189+
}
180190
joints.add(joint);
181191

182192
final bodyA = joint.bodyA;
@@ -197,10 +207,11 @@ class World {
197207
}
198208

199209
/// Destroys a joint. This may cause the connected bodies to begin colliding.
200-
///
201-
/// Warning: This function is locked during callbacks.
202210
void destroyJoint(Joint joint) {
203-
assert(!isLocked);
211+
if (isLocked) {
212+
jointsToDestroy.add(joint);
213+
return;
214+
}
204215

205216
final collideConnected = joint.collideConnected;
206217
joints.remove(joint);
@@ -297,6 +308,16 @@ class World {
297308

298309
flags &= ~locked;
299310

311+
for (final body in bodiesToCreate) {
312+
bodies.add(body);
313+
}
314+
bodiesToCreate.clear();
315+
316+
for (final body in bodiesToDestroy) {
317+
destroyBody(body);
318+
}
319+
bodiesToDestroy.clear();
320+
300321
_profile.step.record(_stepTimer.getMilliseconds());
301322
}
302323

packages/forge2d/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ environment:
88
sdk: ">=3.8.0 <4.0.0"
99

1010
dependencies:
11-
meta: ^1.17.0
11+
meta: ^1.16.0
1212
vector_math: ^2.2.0
1313
web: ^1.1.1
1414

0 commit comments

Comments
 (0)