`flame_forge2d` easier `Ray2` visualisation
What could be improved
For Flame_Forge2D there could exist a mixin that helps users to actually see the Ray2 in the screen.
Why should this be improved
This could help people debug HitBoxes easier.
Any risks?
I don't believe that anything is a risk here.
More information
Here is an example using the code below.
https://github.com/flame-engine/flame/assets/52160996/5518a2f7-76e4-427e-bba9-368cec75a27f
Here is an example of what could be written (copied from raycast_example.dart):
mixin RayCastToMouse on Forge2DGame implements RayCast, MouseMovementDetector {
late Vector2 _direction = Vector2(1, 0);
@override
void onMouseMove(PointerHoverInfo info) {
final vector = info.eventPosition.game;
final tempDirection = Vector2(
vector.x - rayStartPosition.x,
vector.y - rayStartPosition.y,
);
_direction = Vector2(
tempDirection.x / tempDirection.length.abs(),
tempDirection.y / tempDirection.length.abs(),
);
}
@override
Vector2 get rayDirection => _direction;
}
mixin RayCast on Forge2DGame implements HasCollisionDetection {
final _points = <Vector2>[];
@override
void update(double dt) {
super.update(dt);
final ray = Ray2(
origin: Vector2(rayStartPosition.x, rayStartPosition.y),
direction: rayDirection,
);
final result = collisionDetection.raycast(ray);
if ((result != null) && (result.intersectionPoint != null)) {
_fireRay(ray.origin, result.intersectionPoint!);
}
}
@override
void render(Canvas canvas) {
super.render(canvas);
for (int i = 0; i < _points.length - 1; i++) {
canvas.drawLine(
_points[i].toOffset(),
_points[i + 1].toOffset(),
Paint()
..color = Colors.red
..strokeWidth = 4,
);
}
}
void _fireRay(
Vector2 rayStart,
Vector2 rayTarget,
) {
_points.clear();
_points.add(worldToScreen(rayStart));
final nearestCallback = _NearestBoxRayCastCallback();
world.raycast(nearestCallback, rayStart, rayTarget);
if (nearestCallback.nearestPoint != null) {
_points.add(worldToScreen(nearestCallback.nearestPoint!));
} else {
_points.add(worldToScreen(rayTarget));
}
}
Vector2 get rayDirection => Vector2(1, 0);
Vector2 get rayStartPosition;
}
class _NearestBoxRayCastCallback extends RayCastCallback {
Vector2? nearestPoint;
double nearestFraction = 0;
@override
double reportFixture(
Fixture fixture,
Vector2 point,
Vector2 normal,
double fraction,
) {
if ((nearestPoint == null) || (fraction < nearestFraction)) {
nearestPoint = point;
nearestFraction = fraction;
}
return 1;
}
}
Do you want to work on this? :)
I could.
Are there any docs on your PR guidelines?
Also, I would like feedback on this code snippet, do you think creating the two mixins is the best approach? I'm not sure as of right now because https://github.com/dart-lang/language/issues/540 is open still, and that would mean if a user wanted to use the RayCastToMouse mixin, the mixins in the Forge2DGame would look a bit like:
class MyGame extends Forge2DGame
with
HasCollisionDetection,
MouseMovementDetector,
RayCast,
RayCastToMouse {
Are there any docs on your PR guidelines?
https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md
Also, I would like feedback on this code snippet, do you think creating the two mixins is the best approach? I'm not sure as of right now because https://github.com/dart-lang/language/issues/540 is open still, and that would mean if a user wanted to use the RayCastToMouse mixin, the mixins in the Forge2DGame would look a bit like:
It looks like they could be components instead of mixins.
Another thing, make sure you don't create any new Ray2 Vector2 or Paint objects in the update or render methods, since that will hurt performance. Since they are mutable you can just set them outside of the method or in onLoad and then do changes to them within the update/render method if needed, so that the same objects always are used instead of creating new ones.