LWJGL - 当我的玩家与不止一个墙壁物体碰撞时,他开始来回弹跳

LWJGL - When my player collides with more than one wall object he starts to bounce back and forth

所以我和我的朋友们决定制作游戏,所以我决定为游戏创建一个引擎。一切进展顺利,我实现了一种我称之为 "Push Collision" 的碰撞类型,这基本上意味着:当玩家朝向物体移动时,物体采用它在物体上移动的速度并将其减去位置,所以说我我按下 W 或向上箭头,我正在撞墙,墙将采用我的水平速度或 ysp(Y 速度)并将其减去我的 y 位置。它开始工作,直到我添加了第二个盒子,知道当我一个接一个地与盒子碰撞时它起作用了,但是当我到达两个墙物体的中间时,我的播放器会开始从墙壁。现在我知道发生了什么事,因为它与一堵墙相撞,它正在减去我的 y 或 x 位置的速度,但是因为我正在与两个相撞,它会减去我移动到我的 x 或 y 的速度的两倍,我是以为我可以只增加 object/player 的 x 或 y 速度,但是当我移动时对象只会减去两次,所以我有点难过。这是我为 "Push Collision type" 和游戏 class 以及玩家 class 和 TestBox class 或 Wall class.[=15= 制作的代码]

碰撞Class:

package engine.test.core;

public class Collision {
    public static void PushCollision(BaseObject obj1, BaseObject obj2) {
        if (obj1.box.CollideWOB(obj2.box)) {

            if (obj1.MoveDir == 2) {
                obj1.Position.x -= obj1.xsp;
            } else if (obj1.MoveDir == 1) {
                obj1.Position.x += obj1.xsp;
            } else if (obj1.MoveDir == 3) {
                obj1.Position.y += obj1.ysp;
            } else if (obj1.MoveDir == 4) {
                obj1.Position.y -= obj1.ysp;
            }
        }
    }
}

玩家Class:

package engine.test.game;

import org.lwjgl.input.Keyboard;

import engine.test.core.BaseObject;
import engine.test.core.Renderer;

public class Player extends BaseObject {

    public Player(int x, int y, int w, int h) {
        super(x, y, w, h);
    }

    @Override
    public void Init() {
        xsp = 5;
        ysp = 5;
    }

    @Override
    public void Update() {
        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
            MoveDir = 2;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            MoveDir = 1;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
            MoveDir = 4;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
            MoveDir = 3;
        } else {
            MoveDir = 0;
        }

        if (MoveDir == 1) {
            Position.x -= xsp;
        } else if (MoveDir == 2) {
            Position.x += xsp;
        } else if (MoveDir == 3) {
            Position.y -= ysp;
        } else if (MoveDir == 4) {
            Position.y += ysp;
        }

        box.UpdateBox(Position, Size);
    }

    @Override
    public void Draw() {
        Renderer.Quad(Position, Size);
    }
}

测试框Class:

package engine.test.game;

import engine.test.core.BaseObject;
import engine.test.core.Renderer;

public class TestBox extends BaseObject {

    public TestBox(int x, int y, int w, int h) {
        super(x, y, w, h);
    }

    @Override
    public void Init() {

    }

    @Override
    public void Update() {
        box.UpdateBox(Position, Size);
    }

    @Override
    public void Draw() {
        Renderer.Quad(Position, Size);
    }
}

游戏Class:

package engine.test.game;

import java.util.ArrayList;
import java.util.List;

import engine.test.core.BaseGame;
import engine.test.core.Collision;

public class Game extends BaseGame {

    Player p;
    TestBox tb;
    TestBox tb2;

    List<TestBox> TestBoxes = new ArrayList<TestBox>();


    boolean Debug = false;

    @Override
    public void Init() {
        p = new Player(0, 0, 32, 32);

        p.Init();

        tb = new TestBox(100, 100, 32, 32);
        tb2 = new TestBox(132, 100, 32, 32);

        tb.Init();
        tb2.Init();

        TestBoxes.add(tb);
        TestBoxes.add(tb2);
    }

    @Override
    public void Update() {

        p.Update();

        for (TestBox box : TestBoxes) {
            Collision.PushCollision(p, box);
        }
    }

    @Override
    public void Draw() {
        p.Draw();

        for (TestBox box : TestBoxes) {
            box.Draw();
        }
    }
}

解决此问题的一种方法是:

  • 当检测到碰撞时,将其添加到 "detected collisions" 的队列中,该队列应包含碰撞框数据。
  • 检测到所有碰撞并将其添加到队列后,遍历队列并在每次推送后检查该对象是否仍在与该对象发生碰撞。如果是,计算一个新的推送并应用它。否则,忽略原来的碰撞。

这是我想到的第一个解决方案。如果您对此有任何疑问,请告诉我! :)