Flutter Flame检测障碍物的碰撞

huangapple go评论63阅读模式
英文:

Flutter Flame collision detection with obstacles

问题

我正在尝试创建一个游戏,其中有一个玩家和一个带有墙壁和障碍物的平铺地图,玩家可以向上、向右、向下、向左移动,我希望玩家不会穿过墙壁或障碍物。

我使用了Flutter Flame的碰撞系统来实现这一点,但我遇到了一个困扰我的错误,让我用一个示例来解释一下这个错误。

假设玩家向上移动并与墙壁碰撞,那么玩家将无法再向上移动,但如果他继续与顶边碰撞并开始向右或向左移动,当他到达边缘时,他将穿过左侧或右侧的墙壁。

class Player extends SpriteComponent
    with CollisionCallbacks, HasGameRef<MobArena> {
  final MovementJoystick joystick;
  bool collided = false;
  double speed = 50;
  JoystickDirection collidedDirection = JoystickDirection.idle;

  Player({required this.joystick}) : super(size: Vector2.all(16));

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    add(RectangleHitbox());
  }

  @override
  void update(double dt) {
    super.update(dt);

    if (!joystick.relativeDelta.isZero()) {
      switch (joystick.direction) {
        case JoystickDirection.up:
          if (collided && collidedDirection == JoystickDirection.up) {
            break;
          }

          position.y += (joystick.relativeDelta * speed * dt)[1];
          break;
        case JoystickDirection.right:
          if (collided && collidedDirection == JoystickDirection.right) {
            break;
          }
          position.x += (joystick.relativeDelta * speed * dt)[0];
          break;
        case JoystickDirection.down:
          if (collided && collidedDirection == JoystickDirection.down) {
            break;
          }
          position.y += (joystick.relativeDelta * speed * dt)[1];
          break;
        case JoystickDirection.left:
          if (collided && collidedDirection == JoystickDirection.left) {
            break;
          }
          position.x += (joystick.relativeDelta * speed * dt)[0];
          break;
      }
    }
  }

  @override
  void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
    super.onCollision(intersectionPoints, other);
    if (other is Obstacle && !collided) {
      collided = true;
      collidedDirection = joystick.direction;
    }
  }

  @override
  void onCollisionEnd(PositionComponent other) {
    super.onCollisionEnd(other);

    collidedDirection = JoystickDirection.idle;
    collided = false;
  }
}

这是你提供的代码的翻译部分。

英文:

I'm trying to build a game were I have a player and a tiled map with walls and obstacles, the player can move up, right, down, left and I want the player to not go trough the walls or obstacles.

I used the collision system of flutter flame to implement this but I have a bug that its killing me, let me explain the bug that i have with an example

Let's say that the player goes up and collides with a wall, then the player cannot move up anymore
but if he keep colliding with the top edge and start moving right or left he will go through the walls on the left or right when he reaches the edge

class Player extends SpriteComponent
with CollisionCallbacks, HasGameRef&lt;MobArena&gt; {
final MovementJoystick joystick;
bool collided = false;
double speed = 50;
JoystickDirection collidedDirection = JoystickDirection.idle;
Player({required this.joystick}) : super(size: Vector2.all(16));
@override
Future&lt;void&gt; onLoad() async {
await super.onLoad();
add(RectangleHitbox());
}
@override
void update(double dt) {
super.update(dt);
if (!joystick.relativeDelta.isZero()) {
switch (joystick.direction) {
case JoystickDirection.up:
if (collided &amp;&amp; collidedDirection == JoystickDirection.up) {
break;
}
position.y += (joystick.relativeDelta * speed * dt)[1];
break;
case JoystickDirection.right:
if (collided &amp;&amp; collidedDirection == JoystickDirection.right) {
break;
}
position.x += (joystick.relativeDelta * speed * dt)[0];
break;
case JoystickDirection.down:
if (collided &amp;&amp; collidedDirection == JoystickDirection.down) {
break;
}
position.y += (joystick.relativeDelta * speed * dt)[1];
break;
case JoystickDirection.left:
if (collided &amp;&amp; collidedDirection == JoystickDirection.left) {
break;
}
position.x += (joystick.relativeDelta * speed * dt)[0];
break;
}
}
}
@override
void onCollision(Set&lt;Vector2&gt; intersectionPoints, PositionComponent other) {
super.onCollision(intersectionPoints, other);
if (other is Obstacle &amp;&amp; !collided) {
collided = true;
collidedDirection = joystick.direction;
}
}
@override
void onCollisionEnd(PositionComponent other) {
super.onCollisionEnd(other);
collidedDirection = JoystickDirection.idle;
collided = false;
}
}

答案1

得分: 0

如果您想使用这种类型的检查,您将需要一个碰撞方向列表,而不仅仅是一个,因为它可以同时从多个方向碰撞。

onCollisionEnd中,您还需要从该列表中删除它不再与之碰撞的方向。

为了使其更加高效,您可以使用onCollisionStart而不是onCollision来检查当您开始与新墙碰撞时。

英文:

If you want to use this type of checking you will have to have a list of collision directions instead of only one, since it can collide from multiple directions at the same time.

In the onCollsionEnd you'll also have to remove the directions that it no longer collides with from that list.

To make it a bit more efficient, you can use onCollisionStart instead of onCollision for checking when you are starting to collide with a new wall.

huangapple
  • 本文由 发表于 2023年4月4日 13:46:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75925861.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定