addShape -> addHitbox (#882)

This commit is contained in:
Lukas Klingsbo
2021-07-26 20:19:45 +02:00
committed by GitHub
parent 3b5d7e22d5
commit e3f9f1a469
12 changed files with 45 additions and 42 deletions

View File

@ -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 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 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 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: 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(0, -1),
Vector2(-1, 0), Vector2(-1, 0),
]); ]);
addShape(shape); addHitbox(shape);
} }
} }
``` ```
@ -165,11 +165,11 @@ There are currently three shapes: [Polygon](#Polygon), [Rectangle](#Rectangle) a
[Cirlce](#Circle). [Cirlce](#Circle).
### HitboxShape ### HitboxShape
A HitboxShape is a Shape defined from the center position of the component that it is attached to A `HitboxShape` is a `Shape` defined from the center position of the component that it is attached
and it has the same bounding size and angle as the component. You can set `localPosition` to have 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 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 shape that you add to your `Hitbox`, or `Collidable`. Usually these types of shapes are the only
that you need to use. ones that you need to use.
#### HitboxPolygon #### HitboxPolygon
It should be noted that if you want to use collision detection or `containsPoint` on the `Polygon`, It should be noted that if you want to use collision detection or `containsPoint` on the `Polygon`,

View File

@ -24,7 +24,7 @@ class MovableSquare extends SquareComponent
late Timer timer; late Timer timer;
MovableSquare() : super(priority: 1) { MovableSquare() : super(priority: 1) {
addShape(HitboxRectangle()); addHitbox(HitboxRectangle());
timer = Timer(3.0) timer = Timer(3.0)
..stop() ..stop()
..callback = () { ..callback = () {
@ -89,7 +89,7 @@ class Rock extends SquareComponent with Hitbox, Collidable, Tappable {
this.position.setFrom(position); this.position.setFrom(position);
size.setValues(50, 50); size.setValues(50, 50);
paint = unpressedPaint; paint = unpressedPaint;
addShape(HitboxRectangle()); addHitbox(HitboxRectangle());
} }
@override @override

View File

@ -21,7 +21,7 @@ class MyCollidable extends PositionComponent
size: Vector2.all(100), size: Vector2.all(100),
anchor: Anchor.center, anchor: Anchor.center,
) { ) {
addShape(HitboxCircle()); addHitbox(HitboxCircle());
} }
@override @override
@ -45,7 +45,7 @@ class MyCollidable extends PositionComponent
@override @override
void render(Canvas canvas) { void render(Canvas canvas) {
super.render(canvas); super.render(canvas);
renderShapes(canvas); renderHitboxes(canvas);
} }
@override @override

View File

@ -63,7 +63,7 @@ abstract class MyCollidable extends PositionComponent
@override @override
void render(Canvas canvas) { void render(Canvas canvas) {
super.render(canvas); super.render(canvas);
renderShapes(canvas, paint: _activePaint); renderHitboxes(canvas, paint: _activePaint);
if (_isDragged) { if (_isDragged) {
final localCenter = (size / 2).toOffset(); final localCenter = (size / 2).toOffset();
canvas.drawCircle(localCenter, 5, _activePaint); canvas.drawCircle(localCenter, 5, _activePaint);
@ -134,7 +134,7 @@ class CollidablePolygon extends MyCollidable {
Vector2(0, -1.0), Vector2(0, -1.0),
Vector2(-0.8, -0.8), Vector2(-0.8, -0.8),
]); ]);
addShape(shape); addHitbox(shape);
} }
} }
@ -145,7 +145,7 @@ class CollidableRectangle extends MyCollidable {
Vector2 velocity, Vector2 velocity,
ScreenCollidable screenCollidable, ScreenCollidable screenCollidable,
) : super(position, size, velocity, screenCollidable) { ) : super(position, size, velocity, screenCollidable) {
addShape(HitboxRectangle()); addHitbox(HitboxRectangle());
} }
} }
@ -157,7 +157,7 @@ class CollidableCircle extends MyCollidable {
ScreenCollidable screenCollidable, ScreenCollidable screenCollidable,
) : super(position, size, velocity, screenCollidable) { ) : super(position, size, velocity, screenCollidable) {
final shape = HitboxCircle(); 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 top = SnowmanPart(0.4, Vector2(0, -0.8), Colors.red);
final middle = SnowmanPart(0.6, Vector2(0, -0.3), Colors.yellow); final middle = SnowmanPart(0.6, Vector2(0, -0.3), Colors.yellow);
final bottom = SnowmanPart(1.0, Vector2(0, 0.5), Colors.green); final bottom = SnowmanPart(1.0, Vector2(0, 0.5), Colors.green);
addShape(top); addHitbox(top);
addShape(middle); addHitbox(middle);
addShape(bottom); addHitbox(bottom);
} }
} }

View File

@ -10,6 +10,7 @@
- Add `SpriteButton.asset` - Add `SpriteButton.asset`
- Add `NineTileBox.asset` - Add `NineTileBox.asset`
- Rename `Camera.cameraSpeed` to `Camera.speed` - Rename `Camera.cameraSpeed` to `Camera.speed`
- Rename `addShape` to `addHitbox` in `Hitbox` mixin
## [1.0.0-releasecandidate.13] ## [1.0.0-releasecandidate.13]
- Fix camera not ending up in the correct position on long jumps - Fix camera not ending up in the correct position on long jumps

View File

@ -30,7 +30,7 @@ class ScreenCollidable extends PositionComponent
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
size = gameRef.size; size = gameRef.size;
addShape(HitboxRectangle()); addHitbox(HitboxRectangle());
} }
final _zeroVector = Vector2.zero(); final _zeroVector = Vector2.zero();

View File

@ -6,17 +6,19 @@ import '../../geometry/shape.dart';
import '../position_component.dart'; import '../position_component.dart';
mixin Hitbox on PositionComponent { mixin Hitbox on PositionComponent {
final List<HitboxShape> _shapes = <HitboxShape>[]; final List<HitboxShape> _hitboxes = <HitboxShape>[];
UnmodifiableListView<HitboxShape> get shapes => UnmodifiableListView(_shapes); UnmodifiableListView<HitboxShape> get hitboxes {
return UnmodifiableListView(_hitboxes);
void addShape(HitboxShape shape) {
shape.component = this;
_shapes.add(shape);
} }
void removeShape(HitboxShape shape) { void addHitbox(HitboxShape shape) {
_shapes.remove(shape); shape.component = this;
_hitboxes.add(shape);
}
void removeHitbox(HitboxShape shape) {
_hitboxes.remove(shape);
} }
/// Checks whether the hitbox represented by the list of [HitboxShape] /// Checks whether the hitbox represented by the list of [HitboxShape]
@ -24,11 +26,11 @@ mixin Hitbox on PositionComponent {
@override @override
bool containsPoint(Vector2 point) { bool containsPoint(Vector2 point) {
return possiblyContainsPoint(point) && return possiblyContainsPoint(point) &&
_shapes.any((shape) => shape.containsPoint(point)); _hitboxes.any((shape) => shape.containsPoint(point));
} }
void renderShapes(Canvas canvas, {Paint? paint}) { void renderHitboxes(Canvas canvas, {Paint? paint}) {
_shapes.forEach((shape) => shape.render(canvas, paint ?? debugPaint)); _hitboxes.forEach((shape) => shape.render(canvas, paint ?? debugPaint));
} }
/// Since this is a cheaper calculation than checking towards all shapes, this /// Since this is a cheaper calculation than checking towards all shapes, this

View File

@ -158,7 +158,7 @@ abstract class PositionComponent extends BaseComponent {
@override @override
void renderDebugMode(Canvas canvas) { void renderDebugMode(Canvas canvas) {
if (this is Hitbox) { if (this is Hitbox) {
(this as Hitbox).renderShapes(canvas); (this as Hitbox).renderHitboxes(canvas);
} }
canvas.drawRect(size.toRect(), debugPaint); canvas.drawRect(size.toRect(), debugPaint);
debugTextPaint.render( debugTextPaint.render(

View File

@ -75,8 +75,8 @@ Set<Vector2> intersections(
if (!collidableA.possiblyOverlapping(collidableB)) { if (!collidableA.possiblyOverlapping(collidableB)) {
// These collidables can't have any intersection points // These collidables can't have any intersection points
if (hasActiveCollision(collidableA, collidableB)) { if (hasActiveCollision(collidableA, collidableB)) {
for (final shapeA in collidableA.shapes) { for (final shapeA in collidableA.hitboxes) {
for (final shapeB in collidableB.shapes) { for (final shapeB in collidableB.hitboxes) {
_handleShapeCollisionEnd(shapeA, shapeB); _handleShapeCollisionEnd(shapeA, shapeB);
} }
} }
@ -86,8 +86,8 @@ Set<Vector2> intersections(
final result = <Vector2>{}; final result = <Vector2>{};
final currentResult = <Vector2>{}; final currentResult = <Vector2>{};
for (final shapeA in collidableA.shapes) { for (final shapeA in collidableA.hitboxes) {
for (final shapeB in collidableB.shapes) { for (final shapeB in collidableB.hitboxes) {
currentResult.addAll(shapeA.intersections(shapeB)); currentResult.addAll(shapeA.intersections(shapeB));
if (currentResult.isNotEmpty) { if (currentResult.isNotEmpty) {
result.addAll(currentResult); result.addAll(currentResult);

View File

@ -20,7 +20,7 @@ class TestBlock extends PositionComponent with Hitbox, Collidable {
size: size, size: size,
) { ) {
collidableType = type; collidableType = type;
addShape( addHitbox(
HitboxRectangle(), HitboxRectangle(),
); );
} }

View File

@ -38,7 +38,7 @@ class TestBlock extends PositionComponent with Hitbox, Collidable {
position: position, position: position,
size: size, size: size,
) { ) {
addShape(hitbox); addHitbox(hitbox);
} }
bool hasCollisionWith(Collidable otherCollidable) { bool hasCollisionWith(Collidable otherCollidable) {

View File

@ -98,7 +98,7 @@ void main() {
Vector2(-1, 0), Vector2(-1, 0),
Vector2(0, 1), Vector2(0, 1),
]); ]);
component.addShape(hitbox); component.addHitbox(hitbox);
final point = component.position + component.size / 4; final point = component.position + component.size / 4;
expect(component.containsPoint(point), true); expect(component.containsPoint(point), true);
@ -110,7 +110,7 @@ void main() {
component.anchor = Anchor.topLeft; component.anchor = Anchor.topLeft;
component.size.setValues(2.0, 2.0); component.size.setValues(2.0, 2.0);
final hitbox = HitboxRectangle(); final hitbox = HitboxRectangle();
component.addShape(hitbox); component.addHitbox(hitbox);
expect(component.containsPoint(Vector2(1, 1)), true); expect(component.containsPoint(Vector2(1, 1)), true);
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.anchor = Anchor.bottomRight;
component.size.setValues(2.0, 2.0); component.size.setValues(2.0, 2.0);
final hitbox = HitboxRectangle(); final hitbox = HitboxRectangle();
component.addShape(hitbox); component.addHitbox(hitbox);
expect(component.containsPoint(Vector2(1, 1)), true); expect(component.containsPoint(Vector2(1, 1)), true);
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.anchor = Anchor.topLeft;
component.size.setValues(2.0, 2.0); component.size.setValues(2.0, 2.0);
final hitbox = HitboxRectangle(); final hitbox = HitboxRectangle();
component.addShape(hitbox); component.addHitbox(hitbox);
expect(component.containsPoint(Vector2(0.0, 0.0)), false); expect(component.containsPoint(Vector2(0.0, 0.0)), false);
expect(component.containsPoint(Vector2(0.9, 0.9)), false); expect(component.containsPoint(Vector2(0.9, 0.9)), false);
@ -151,7 +151,7 @@ void main() {
component.position.setValues(1.0, 1.0); component.position.setValues(1.0, 1.0);
component.anchor = Anchor.topLeft; component.anchor = Anchor.topLeft;
component.size.setValues(2.0, 2.0); component.size.setValues(2.0, 2.0);
component.addShape(HitboxPolygon([ component.addHitbox(HitboxPolygon([
Vector2(1, 0), Vector2(1, 0),
Vector2(0, -1), Vector2(0, -1),
Vector2(-1, 0), Vector2(-1, 0),