From e3f9f1a469563f95ce8b65bce8dc2a83a565d76f Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 26 Jul 2021 20:19:45 +0200 Subject: [PATCH] addShape -> addHitbox (#882) --- doc/collision_detection.md | 14 +++++------ .../camera_and_viewport/follow_object.dart | 4 ++-- .../stories/collision_detection/circles.dart | 4 ++-- .../collision_detection/multiple_shapes.dart | 14 +++++------ packages/flame/CHANGELOG.md | 1 + .../lib/src/components/mixins/collidable.dart | 2 +- .../lib/src/components/mixins/hitbox.dart | 24 ++++++++++--------- .../src/components/position_component.dart | 2 +- .../lib/src/geometry/collision_detection.dart | 8 +++---- .../test/components/collidable_type_test.dart | 2 +- .../components/collision_callback_test.dart | 2 +- .../components/position_component_test.dart | 10 ++++---- 12 files changed, 45 insertions(+), 42 deletions(-) diff --git a/doc/collision_detection.md b/doc/collision_detection.md index a2cc154e2..76746969a 100644 --- a/doc/collision_detection.md +++ b/doc/collision_detection.md @@ -45,7 +45,7 @@ You can add new shapes to the `Hitbox` just like they are added in the below `Co The `Collidable` mixin is added to a `PositionComponent` that has a `HitBox` and it is used for detecting collisions with other `Collidable`s. If you do not add a shape to your `Hitbox` component it will never collide with anything. If you want the component to have a default rectangular shape -that fills the size of your component you can simply do `addShape(HitboxRectangle())`. +that fills the size of your component you can simply do `addHitbox(HitboxRectangle())`. To make your component collidable you would start off something like this: @@ -59,7 +59,7 @@ class MyCollidable extends PositionComponent with Hitbox, Collidable { Vector2(0, -1), Vector2(-1, 0), ]); - addShape(shape); + addHitbox(shape); } } ``` @@ -165,11 +165,11 @@ There are currently three shapes: [Polygon](#Polygon), [Rectangle](#Rectangle) a [Cirlce](#Circle). ### HitboxShape -A HitboxShape is a Shape defined from the center position of the component that it is attached to -and it has the same bounding size and angle as the component. You can set `localPosition` to have -the position of the shape deviate from the center of the component. A HitboxShape is the type of -shape that you add to your Hitbox, or Collidable. Usually these types of shapes are the only ones -that you need to use. +A `HitboxShape` is a `Shape` defined from the center position of the component that it is attached +to and it has the same bounding size and angle as the component. You can set `localPosition` to have +the position of the shape deviate from the center of the component. A `HitboxShape` is the type of +shape that you add to your `Hitbox`, or `Collidable`. Usually these types of shapes are the only +ones that you need to use. #### HitboxPolygon It should be noted that if you want to use collision detection or `containsPoint` on the `Polygon`, diff --git a/examples/lib/stories/camera_and_viewport/follow_object.dart b/examples/lib/stories/camera_and_viewport/follow_object.dart index 2692ebb71..20a368b36 100644 --- a/examples/lib/stories/camera_and_viewport/follow_object.dart +++ b/examples/lib/stories/camera_and_viewport/follow_object.dart @@ -24,7 +24,7 @@ class MovableSquare extends SquareComponent late Timer timer; MovableSquare() : super(priority: 1) { - addShape(HitboxRectangle()); + addHitbox(HitboxRectangle()); timer = Timer(3.0) ..stop() ..callback = () { @@ -89,7 +89,7 @@ class Rock extends SquareComponent with Hitbox, Collidable, Tappable { this.position.setFrom(position); size.setValues(50, 50); paint = unpressedPaint; - addShape(HitboxRectangle()); + addHitbox(HitboxRectangle()); } @override diff --git a/examples/lib/stories/collision_detection/circles.dart b/examples/lib/stories/collision_detection/circles.dart index c60605533..7f103d03f 100644 --- a/examples/lib/stories/collision_detection/circles.dart +++ b/examples/lib/stories/collision_detection/circles.dart @@ -21,7 +21,7 @@ class MyCollidable extends PositionComponent size: Vector2.all(100), anchor: Anchor.center, ) { - addShape(HitboxCircle()); + addHitbox(HitboxCircle()); } @override @@ -45,7 +45,7 @@ class MyCollidable extends PositionComponent @override void render(Canvas canvas) { super.render(canvas); - renderShapes(canvas); + renderHitboxes(canvas); } @override diff --git a/examples/lib/stories/collision_detection/multiple_shapes.dart b/examples/lib/stories/collision_detection/multiple_shapes.dart index fa2212003..7ece53948 100644 --- a/examples/lib/stories/collision_detection/multiple_shapes.dart +++ b/examples/lib/stories/collision_detection/multiple_shapes.dart @@ -63,7 +63,7 @@ abstract class MyCollidable extends PositionComponent @override void render(Canvas canvas) { super.render(canvas); - renderShapes(canvas, paint: _activePaint); + renderHitboxes(canvas, paint: _activePaint); if (_isDragged) { final localCenter = (size / 2).toOffset(); canvas.drawCircle(localCenter, 5, _activePaint); @@ -134,7 +134,7 @@ class CollidablePolygon extends MyCollidable { Vector2(0, -1.0), Vector2(-0.8, -0.8), ]); - addShape(shape); + addHitbox(shape); } } @@ -145,7 +145,7 @@ class CollidableRectangle extends MyCollidable { Vector2 velocity, ScreenCollidable screenCollidable, ) : super(position, size, velocity, screenCollidable) { - addShape(HitboxRectangle()); + addHitbox(HitboxRectangle()); } } @@ -157,7 +157,7 @@ class CollidableCircle extends MyCollidable { ScreenCollidable screenCollidable, ) : super(position, size, velocity, screenCollidable) { final shape = HitboxCircle(); - addShape(shape); + addHitbox(shape); } } @@ -196,9 +196,9 @@ class CollidableSnowman extends MyCollidable { final top = SnowmanPart(0.4, Vector2(0, -0.8), Colors.red); final middle = SnowmanPart(0.6, Vector2(0, -0.3), Colors.yellow); final bottom = SnowmanPart(1.0, Vector2(0, 0.5), Colors.green); - addShape(top); - addShape(middle); - addShape(bottom); + addHitbox(top); + addHitbox(middle); + addHitbox(bottom); } } diff --git a/packages/flame/CHANGELOG.md b/packages/flame/CHANGELOG.md index a0a4e89e1..e864e1f95 100644 --- a/packages/flame/CHANGELOG.md +++ b/packages/flame/CHANGELOG.md @@ -10,6 +10,7 @@ - Add `SpriteButton.asset` - Add `NineTileBox.asset` - Rename `Camera.cameraSpeed` to `Camera.speed` + - Rename `addShape` to `addHitbox` in `Hitbox` mixin ## [1.0.0-releasecandidate.13] - Fix camera not ending up in the correct position on long jumps diff --git a/packages/flame/lib/src/components/mixins/collidable.dart b/packages/flame/lib/src/components/mixins/collidable.dart index 44fee5765..1241adb21 100644 --- a/packages/flame/lib/src/components/mixins/collidable.dart +++ b/packages/flame/lib/src/components/mixins/collidable.dart @@ -30,7 +30,7 @@ class ScreenCollidable extends PositionComponent Future onLoad() async { await super.onLoad(); size = gameRef.size; - addShape(HitboxRectangle()); + addHitbox(HitboxRectangle()); } final _zeroVector = Vector2.zero(); diff --git a/packages/flame/lib/src/components/mixins/hitbox.dart b/packages/flame/lib/src/components/mixins/hitbox.dart index deebc7325..53102673f 100644 --- a/packages/flame/lib/src/components/mixins/hitbox.dart +++ b/packages/flame/lib/src/components/mixins/hitbox.dart @@ -6,17 +6,19 @@ import '../../geometry/shape.dart'; import '../position_component.dart'; mixin Hitbox on PositionComponent { - final List _shapes = []; + final List _hitboxes = []; - UnmodifiableListView get shapes => UnmodifiableListView(_shapes); - - void addShape(HitboxShape shape) { - shape.component = this; - _shapes.add(shape); + UnmodifiableListView get hitboxes { + return UnmodifiableListView(_hitboxes); } - void removeShape(HitboxShape shape) { - _shapes.remove(shape); + void addHitbox(HitboxShape shape) { + shape.component = this; + _hitboxes.add(shape); + } + + void removeHitbox(HitboxShape shape) { + _hitboxes.remove(shape); } /// Checks whether the hitbox represented by the list of [HitboxShape] @@ -24,11 +26,11 @@ mixin Hitbox on PositionComponent { @override bool containsPoint(Vector2 point) { return possiblyContainsPoint(point) && - _shapes.any((shape) => shape.containsPoint(point)); + _hitboxes.any((shape) => shape.containsPoint(point)); } - void renderShapes(Canvas canvas, {Paint? paint}) { - _shapes.forEach((shape) => shape.render(canvas, paint ?? debugPaint)); + void renderHitboxes(Canvas canvas, {Paint? paint}) { + _hitboxes.forEach((shape) => shape.render(canvas, paint ?? debugPaint)); } /// Since this is a cheaper calculation than checking towards all shapes, this diff --git a/packages/flame/lib/src/components/position_component.dart b/packages/flame/lib/src/components/position_component.dart index 25a91dfb1..95c345e68 100644 --- a/packages/flame/lib/src/components/position_component.dart +++ b/packages/flame/lib/src/components/position_component.dart @@ -158,7 +158,7 @@ abstract class PositionComponent extends BaseComponent { @override void renderDebugMode(Canvas canvas) { if (this is Hitbox) { - (this as Hitbox).renderShapes(canvas); + (this as Hitbox).renderHitboxes(canvas); } canvas.drawRect(size.toRect(), debugPaint); debugTextPaint.render( diff --git a/packages/flame/lib/src/geometry/collision_detection.dart b/packages/flame/lib/src/geometry/collision_detection.dart index 2628d81c4..98894909a 100644 --- a/packages/flame/lib/src/geometry/collision_detection.dart +++ b/packages/flame/lib/src/geometry/collision_detection.dart @@ -75,8 +75,8 @@ Set intersections( if (!collidableA.possiblyOverlapping(collidableB)) { // These collidables can't have any intersection points if (hasActiveCollision(collidableA, collidableB)) { - for (final shapeA in collidableA.shapes) { - for (final shapeB in collidableB.shapes) { + for (final shapeA in collidableA.hitboxes) { + for (final shapeB in collidableB.hitboxes) { _handleShapeCollisionEnd(shapeA, shapeB); } } @@ -86,8 +86,8 @@ Set intersections( final result = {}; final currentResult = {}; - for (final shapeA in collidableA.shapes) { - for (final shapeB in collidableB.shapes) { + for (final shapeA in collidableA.hitboxes) { + for (final shapeB in collidableB.hitboxes) { currentResult.addAll(shapeA.intersections(shapeB)); if (currentResult.isNotEmpty) { result.addAll(currentResult); diff --git a/packages/flame/test/components/collidable_type_test.dart b/packages/flame/test/components/collidable_type_test.dart index caab96ab4..34954ae90 100644 --- a/packages/flame/test/components/collidable_type_test.dart +++ b/packages/flame/test/components/collidable_type_test.dart @@ -20,7 +20,7 @@ class TestBlock extends PositionComponent with Hitbox, Collidable { size: size, ) { collidableType = type; - addShape( + addHitbox( HitboxRectangle(), ); } diff --git a/packages/flame/test/components/collision_callback_test.dart b/packages/flame/test/components/collision_callback_test.dart index fb1fe6ce9..d5d87156b 100644 --- a/packages/flame/test/components/collision_callback_test.dart +++ b/packages/flame/test/components/collision_callback_test.dart @@ -38,7 +38,7 @@ class TestBlock extends PositionComponent with Hitbox, Collidable { position: position, size: size, ) { - addShape(hitbox); + addHitbox(hitbox); } bool hasCollisionWith(Collidable otherCollidable) { diff --git a/packages/flame/test/components/position_component_test.dart b/packages/flame/test/components/position_component_test.dart index 69b5e659a..236d1b99c 100644 --- a/packages/flame/test/components/position_component_test.dart +++ b/packages/flame/test/components/position_component_test.dart @@ -98,7 +98,7 @@ void main() { Vector2(-1, 0), Vector2(0, 1), ]); - component.addShape(hitbox); + component.addHitbox(hitbox); final point = component.position + component.size / 4; expect(component.containsPoint(point), true); @@ -110,7 +110,7 @@ void main() { component.anchor = Anchor.topLeft; component.size.setValues(2.0, 2.0); final hitbox = HitboxRectangle(); - component.addShape(hitbox); + component.addHitbox(hitbox); expect(component.containsPoint(Vector2(1, 1)), true); expect(component.containsPoint(Vector2(1, -1)), true); @@ -124,7 +124,7 @@ void main() { component.anchor = Anchor.bottomRight; component.size.setValues(2.0, 2.0); final hitbox = HitboxRectangle(); - component.addShape(hitbox); + component.addHitbox(hitbox); expect(component.containsPoint(Vector2(1, 1)), true); expect(component.containsPoint(Vector2(1, -1)), true); @@ -138,7 +138,7 @@ void main() { component.anchor = Anchor.topLeft; component.size.setValues(2.0, 2.0); final hitbox = HitboxRectangle(); - component.addShape(hitbox); + component.addHitbox(hitbox); expect(component.containsPoint(Vector2(0.0, 0.0)), false); expect(component.containsPoint(Vector2(0.9, 0.9)), false); @@ -151,7 +151,7 @@ void main() { component.position.setValues(1.0, 1.0); component.anchor = Anchor.topLeft; component.size.setValues(2.0, 2.0); - component.addShape(HitboxPolygon([ + component.addHitbox(HitboxPolygon([ Vector2(1, 0), Vector2(0, -1), Vector2(-1, 0),