Skip to content

flame_forge2d easier Ray2 visualisation #2533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
FMorschel opened this issue May 11, 2023 · 3 comments
Open

flame_forge2d easier Ray2 visualisation #2533

FMorschel opened this issue May 11, 2023 · 3 comments
Assignees

Comments

@FMorschel
Copy link

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.

20230511_080724.mp4

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;
  }
}
@spydon
Copy link
Member

spydon commented May 11, 2023

Do you want to work on this? :)

@FMorschel
Copy link
Author

FMorschel commented May 11, 2023

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 dart-lang/language#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 {

@spydon
Copy link
Member

spydon commented May 11, 2023

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 dart-lang/language#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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants