Skip to content

Commit

Permalink
fix(flame_behaviors): make PropagatingCollisionBehavior more open (#42
Browse files Browse the repository at this point in the history
)
  • Loading branch information
wolfenrain authored May 11, 2023
1 parent 8ea3554 commit 4ae0553
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:flutter/material.dart';
/// the entity that is colliding with the [Parent] is an instance of [Collider].
/// {@endtemplate}
abstract class CollisionBehavior<Collider extends Component,
Parent extends PositionedEntity> extends Behavior<Parent> {
Parent extends EntityMixin> extends Behavior<Parent> {
/// Check if the given component is an instance of [Collider].
bool isValid(Component c) => c is Collider;

Expand Down Expand Up @@ -56,14 +56,26 @@ abstract class CollisionBehavior<Collider extends Component,
/// **Note**: This behavior can also be used for collisions between entities
/// and non-entity components, by passing the component's type as the
/// `Collider` to the [CollisionBehavior].
///
/// The parent to which this behavior is added should be a [PositionComponent]
/// that uses the [EntityMixin]. Flame behaviors comes with the
/// [PositionedEntity] which does exactly that but any kind of position
/// component will work.
/// {@endtemplate}
class PropagatingCollisionBehavior<Parent extends PositionedEntity>
class PropagatingCollisionBehavior<Parent extends EntityMixin>
extends Behavior<Parent> with CollisionCallbacks {
/// {@macro propagating_collision_behavior}
PropagatingCollisionBehavior(this._hitbox) : super(children: [_hitbox]);

final ShapeHitbox _hitbox;

@override
@mustCallSuper
void onMount() {
assert(parent is PositionComponent, 'parent must be a PositionComponent');
super.onMount();
}

@override
Future<void> onLoad() async {
_hitbox
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ class _EntityC extends PositionedEntity {
_EntityC() : super(size: Vector2.all(16));
}

class _EntityD extends Entity {
_EntityD();
}

abstract class _CollisionBehavior<A extends Component,
B extends PositionedEntity> extends CollisionBehavior<A, B> {
bool onCollisionStartCalled = false;
Expand Down Expand Up @@ -59,7 +63,7 @@ class _CollisionBehaviorAtoComponent
void main() {
final flameTester = FlameTester(TestGame.new);

group('CollisionBehavior', () {
group('$CollisionBehavior', () {
flameTester.testGameWidget(
'isColliding returns true if it is current colliding with the Collider',
setUp: (game, tester) async {
Expand Down Expand Up @@ -119,35 +123,57 @@ void main() {
);
});

group('PropagatingCollisionBehavior', () {
group('$PropagatingCollisionBehavior', () {
flameTester.testGameWidget(
'can be added to an Entity',
setUp: (game, tester) async {
final passableCollisionBehavior = PropagatingCollisionBehavior(
final propagatingCollisionBehavior = PropagatingCollisionBehavior(
RectangleHitbox(),
);
final entityA = _EntityA(behaviors: [passableCollisionBehavior]);
final entityA = _EntityA(behaviors: [propagatingCollisionBehavior]);

await game.ensureAdd(entityA);
},
verify: (game, tester) async {
final entityA = game.firstChild<_EntityA>()!;
final passableCollisionBehavior =
final propagatingCollisionBehavior =
entityA.firstChild<PropagatingCollisionBehavior>()!;

expect(
entityA.findBehavior<PropagatingCollisionBehavior>(),
equals(passableCollisionBehavior),
equals(propagatingCollisionBehavior),
);
expect(
passableCollisionBehavior.children
propagatingCollisionBehavior.children
.whereType<RectangleHitbox>()
.length,
equals(1),
);
},
);

flameTester.testGameWidget(
'throws assertion exception if parent is not a positioned component',
setUp: (game, tester) async {
await game.ensureAdd(_EntityD());
return game.pauseEngine(); // Pausing engine to trigger it manually
},
verify: (game, tester) async {
final entity = game.firstChild<_EntityD>()!;
final propagatingCollisionBehavior = PropagatingCollisionBehavior(
RectangleHitbox(),
);

await expectLater(
() async {
await entity.add(propagatingCollisionBehavior);
game.update(0);
},
failsAssert('parent must be a PositionComponent'),
);
},
);

group('propagates collision', () {
flameTester.testGameWidget(
'on start to the correct collision behavior',
Expand Down

0 comments on commit 4ae0553

Please sign in to comment.