在不同位置创建的 PolygonShape

发布于 2025-01-15 17:21:09 字数 3086 浏览 7 评论 0原文

我试图用鼠标关节在屏幕中心创建一个多边形,非常简单。 CircleShape 效果很好。而且鼠标关节的行为很奇怪,我找不到模式。 所有代码都位于主文件此处中。我将代码保持在最低限度。

Vector2 vec2Median(List<Vector2> vecs) {
  var sum = Vector2(0, 0);
  for (final v in vecs) {
    sum += v;
  }
  return sum / vecs.length.toDouble();
}

void main() {
  final game = MyGame();
  runApp(GameWidget(game: game));
}

class MyGame extends Forge2DGame with MultiTouchDragDetector, HasTappables {
  MouseJoint? mouseJoint;
  static late BodyComponent grabbedBody;
  late Body groundBody;

  MyGame() : super(gravity: Vector2(0, -10.0));

  @override
  Future<void> onLoad() async {
    final boundaries = createBoundaries(this); //Adding boundries
    boundaries.forEach(add);

    groundBody = world.createBody(BodyDef());
    final center = screenToWorld(camera.viewport.effectiveSize / 2);
    final poly = Polygon([
      center + Vector2(0, 0),
      center + Vector2(0, 5),
      center + Vector2(5, 0),
      center + Vector2(5, 5)
    ], bodyType: BodyType.dynamic);
    add(poly);
    grabbedBody = poly;
  }

  @override
  bool onDragUpdate(int pointerId, DragUpdateInfo details) {
    final mouseJointDef = MouseJointDef()
      ..maxForce = 3000 * grabbedBody.body.mass * 10 //Not neccerly needed
      ..dampingRatio = 1
      ..frequencyHz = 5
      ..target.setFrom(grabbedBody.body.position)
      ..collideConnected = false //Maybe set to true
      ..bodyA = groundBody
      ..bodyB = grabbedBody.body;

    mouseJoint ??= world.createJoint(mouseJointDef) as MouseJoint;

    mouseJoint?.setTarget(details.eventPosition.game);
    return false;
  }

  @override
  bool onDragEnd(int pointerId, DragEndInfo details) {
    if (mouseJoint == null) {
      return true;
    }
    world.destroyJoint(mouseJoint!);
    mouseJoint = null;
    return false;
  }
}

abstract class TappableBodyComponent extends BodyComponent with Tappable {
  final Vector2 position;
  final BodyType bodyType;
  TappableBodyComponent(this.position, {this.bodyType = BodyType.dynamic});

  @override
  bool onTapDown(_) {
    MyGame.grabbedBody = this;
    return false;
  }

  Body tappableBCreateBody(Shape shape) {
    final fixtureDef = FixtureDef(shape)
      ..restitution = 0.8
      ..density = 1.0
      ..friction = 0.4;

    final bodyDef = BodyDef()
      // To be able to determine object in collision
      ..userData = this
      ..angularDamping = 0.8
      ..position = position
      ..type = bodyType;

    return world.createBody(bodyDef)..createFixture(fixtureDef);
  }
}

class Polygon extends TappableBodyComponent {
  final List<Vector2> vertecies;

  Polygon(this.vertecies, {BodyType bodyType = BodyType.dynamic})
      : super(vec2Median(vertecies), bodyType: bodyType);

  @override
  Body createBody() {
    final shape = PolygonShape()..set(vertecies);
    return tappableBCreateBody(shape);
  }
}

tappableBCreateBody 封装了 Tappable 和 body 创建方法,Polygon 是我要创建的对象,vec2Median 返回多边形的中心(通过顶点)。

非常感谢!

I'm trying to create a polygon at the center of the screen with a mouse joint, very simple.
A CircleShape works great. Also the mouse joint behaves strangely and I couldn't find a pattern.
All code is in the main file here. I kept the code to a minimum.

Vector2 vec2Median(List<Vector2> vecs) {
  var sum = Vector2(0, 0);
  for (final v in vecs) {
    sum += v;
  }
  return sum / vecs.length.toDouble();
}

void main() {
  final game = MyGame();
  runApp(GameWidget(game: game));
}

class MyGame extends Forge2DGame with MultiTouchDragDetector, HasTappables {
  MouseJoint? mouseJoint;
  static late BodyComponent grabbedBody;
  late Body groundBody;

  MyGame() : super(gravity: Vector2(0, -10.0));

  @override
  Future<void> onLoad() async {
    final boundaries = createBoundaries(this); //Adding boundries
    boundaries.forEach(add);

    groundBody = world.createBody(BodyDef());
    final center = screenToWorld(camera.viewport.effectiveSize / 2);
    final poly = Polygon([
      center + Vector2(0, 0),
      center + Vector2(0, 5),
      center + Vector2(5, 0),
      center + Vector2(5, 5)
    ], bodyType: BodyType.dynamic);
    add(poly);
    grabbedBody = poly;
  }

  @override
  bool onDragUpdate(int pointerId, DragUpdateInfo details) {
    final mouseJointDef = MouseJointDef()
      ..maxForce = 3000 * grabbedBody.body.mass * 10 //Not neccerly needed
      ..dampingRatio = 1
      ..frequencyHz = 5
      ..target.setFrom(grabbedBody.body.position)
      ..collideConnected = false //Maybe set to true
      ..bodyA = groundBody
      ..bodyB = grabbedBody.body;

    mouseJoint ??= world.createJoint(mouseJointDef) as MouseJoint;

    mouseJoint?.setTarget(details.eventPosition.game);
    return false;
  }

  @override
  bool onDragEnd(int pointerId, DragEndInfo details) {
    if (mouseJoint == null) {
      return true;
    }
    world.destroyJoint(mouseJoint!);
    mouseJoint = null;
    return false;
  }
}

abstract class TappableBodyComponent extends BodyComponent with Tappable {
  final Vector2 position;
  final BodyType bodyType;
  TappableBodyComponent(this.position, {this.bodyType = BodyType.dynamic});

  @override
  bool onTapDown(_) {
    MyGame.grabbedBody = this;
    return false;
  }

  Body tappableBCreateBody(Shape shape) {
    final fixtureDef = FixtureDef(shape)
      ..restitution = 0.8
      ..density = 1.0
      ..friction = 0.4;

    final bodyDef = BodyDef()
      // To be able to determine object in collision
      ..userData = this
      ..angularDamping = 0.8
      ..position = position
      ..type = bodyType;

    return world.createBody(bodyDef)..createFixture(fixtureDef);
  }
}

class Polygon extends TappableBodyComponent {
  final List<Vector2> vertecies;

  Polygon(this.vertecies, {BodyType bodyType = BodyType.dynamic})
      : super(vec2Median(vertecies), bodyType: bodyType);

  @override
  Body createBody() {
    final shape = PolygonShape()..set(vertecies);
    return tappableBCreateBody(shape);
  }
}

tappableBCreateBody encapsulate Tappable and body creation methods, Polygon is the object I'm trying to create, vec2Median returns the center of the polygon (by vertices).

Thank you very much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橘味果▽酱 2025-01-22 17:21:09

我认为您必须从顶点中删除 center ,然后仅将其添加为 BodyComponent 的位置,就像您在 的超级调用中所做的那样多边形类。

I think that you have to remove center from the vertices and only add that as the position of the BodyComponent instead, like you already do in the super call of your Polygon class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文