Java Slick2d 矩形碰撞检测奇怪的行为
Java Slick2d rectangle collision detection strange behavior
我想做一个 slick2d java 游戏,遇到了一个问题,我在过去的几个小时里无法解决。我查看了许多其他帖子,但没有一个适合我的问题。
碰撞检测在 9/10 的情况下工作正常。每次它与另一个矩形相交时,它都会根据下面的代码向后移动并显示在 picture1. But sometimes if I get as near as possble to the edge the edges seem to overlap shown here picture2 中。如果我上去,他会检测到十字路口并向下移动。如果我下去,一切都很好。如果我向左或向右走,什么也不会发生。只有当矩形的角相交时才会发生这种情况。如果我同时向上、向左或向右走,他有时会走错方向。似乎如果我同时向上和向侧面移动,他会检测到碰撞并朝相反的方向移动,直到他到达与拐角相交的点并再次停止。关键是在检测和碰撞之后,他再也不会向后移动,而他之前已经向前移动了。此外,他不应该检测矩形的交点并再次向后移动,但为什么他不检测边缘的交点,如图 2 所示?我真的希望有人知道为什么会这样。这个问题发生在每一面。这是代码。
public class Player extends Creature {
int posX = 0;
int posY = 0;
Rectangle hitbox;
Input input;
public Player(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@Override
public void init() {
hitbox = new Rectangle(posX + 320, posY + 240, 32, 32);
}
@Override
public void render(Graphics g) {
g.setColor(Color.red);
g.draw(hitbox);
g.setColor(Color.cyan);
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
g.draw(handler.getWorldCollision().get(i));
}
}
@Override
public void update(GameContainer gc, int delta) {
input = gc.getInput();
if (input.isKeyDown(Input.KEY_W)) {
// move
posY -= 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posY += 100 * delta / 1000f;
break;
}
}
hitbox.setY(posY + 240);
}
if (input.isKeyDown(Input.KEY_S)) {
// move
posY += 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posY -= 100 * delta / 1000f;
break;
}
}
hitbox.setY(posY + 240);
}
if (input.isKeyDown(Input.KEY_A)) {
// move
posX -= 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posX += 100 * delta / 1000f;
break;
}
}
hitbox.setX(posX + 320);
}
if (input.isKeyDown(Input.KEY_D)) {
// move
posX += 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posX -= 100 * delta / 1000f;
break;
}
}
hitbox.setX(posX + 320);
}
handler.setPlayerX(posX);
handler.setPlayerY(posY);
}
}
handler.getWorldCollision()是一个数组,包含图片中所有用青色绘制的矩形。
public class TestWorld extends World {
int[][] map = new int[87][35];
ArrayList<Rectangle> worldCollision;
MapLoader maploader;
public TestWorld(Handler handler) {
super(handler);
}
@Override
public void init() throws IOException {
maploader = new MapLoader(handler);
map = maploader.readMapFile("gameResources/map/testmap.map");
worldCollision = new ArrayList<Rectangle>();
}
@Override
public void render(Graphics g) throws SlickException {
// Render all Tiles given by the map of this world.
for (int i = 0; i < 87; i++) {
for (int j = 0; j < 35; j++) {
g.drawImage(handler.getTileList()[map[j][i]].getImage(), i * 16 - handler.getPlayerX(), j * 16 - handler.getPlayerY());
}
}
}
@Override
public void update(GameContainer gc, int delta) {
worldCollision.clear();
for (int i = 0; i < 87; i++) {
for (int j = 0; j < 35; j++) {
if(handler.getTileList()[map[j][i]].hasCollision()){
worldCollision.add(new Rectangle(i * 16 - handler.getPlayerX(), j * 16 - handler.getPlayerY(), 16, 16));
}
}
}
handler.setWorldCollision(worldCollision);
}
}
谢谢指教!
我不确定我是否完全理解为什么会出现这种重叠。你说“如果我尽可能靠近边缘,边缘似乎会重叠”,所以在向上时会发生重叠,但在向左或向右移动时不会纠正?
顺便说一句,如果左右移动时没有检测到,那是因为你只在上行或下行时检查Y碰撞;虽然这应该足够了,但这就是为什么当左右移动并且已经与边缘重叠时这不是 corrected/detected 的原因!
我想做一个 slick2d java 游戏,遇到了一个问题,我在过去的几个小时里无法解决。我查看了许多其他帖子,但没有一个适合我的问题。
碰撞检测在 9/10 的情况下工作正常。每次它与另一个矩形相交时,它都会根据下面的代码向后移动并显示在 picture1. But sometimes if I get as near as possble to the edge the edges seem to overlap shown here picture2 中。如果我上去,他会检测到十字路口并向下移动。如果我下去,一切都很好。如果我向左或向右走,什么也不会发生。只有当矩形的角相交时才会发生这种情况。如果我同时向上、向左或向右走,他有时会走错方向。似乎如果我同时向上和向侧面移动,他会检测到碰撞并朝相反的方向移动,直到他到达与拐角相交的点并再次停止。关键是在检测和碰撞之后,他再也不会向后移动,而他之前已经向前移动了。此外,他不应该检测矩形的交点并再次向后移动,但为什么他不检测边缘的交点,如图 2 所示?我真的希望有人知道为什么会这样。这个问题发生在每一面。这是代码。
public class Player extends Creature {
int posX = 0;
int posY = 0;
Rectangle hitbox;
Input input;
public Player(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@Override
public void init() {
hitbox = new Rectangle(posX + 320, posY + 240, 32, 32);
}
@Override
public void render(Graphics g) {
g.setColor(Color.red);
g.draw(hitbox);
g.setColor(Color.cyan);
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
g.draw(handler.getWorldCollision().get(i));
}
}
@Override
public void update(GameContainer gc, int delta) {
input = gc.getInput();
if (input.isKeyDown(Input.KEY_W)) {
// move
posY -= 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posY += 100 * delta / 1000f;
break;
}
}
hitbox.setY(posY + 240);
}
if (input.isKeyDown(Input.KEY_S)) {
// move
posY += 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posY -= 100 * delta / 1000f;
break;
}
}
hitbox.setY(posY + 240);
}
if (input.isKeyDown(Input.KEY_A)) {
// move
posX -= 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posX += 100 * delta / 1000f;
break;
}
}
hitbox.setX(posX + 320);
}
if (input.isKeyDown(Input.KEY_D)) {
// move
posX += 100 * delta / 1000f;
// if collision move back
for (int i = 0; i < handler.getWorldCollision().size(); i++) {
if (hitbox.intersects(handler.getWorldCollision().get(i))) {
posX -= 100 * delta / 1000f;
break;
}
}
hitbox.setX(posX + 320);
}
handler.setPlayerX(posX);
handler.setPlayerY(posY);
}
}
handler.getWorldCollision()是一个数组,包含图片中所有用青色绘制的矩形。
public class TestWorld extends World {
int[][] map = new int[87][35];
ArrayList<Rectangle> worldCollision;
MapLoader maploader;
public TestWorld(Handler handler) {
super(handler);
}
@Override
public void init() throws IOException {
maploader = new MapLoader(handler);
map = maploader.readMapFile("gameResources/map/testmap.map");
worldCollision = new ArrayList<Rectangle>();
}
@Override
public void render(Graphics g) throws SlickException {
// Render all Tiles given by the map of this world.
for (int i = 0; i < 87; i++) {
for (int j = 0; j < 35; j++) {
g.drawImage(handler.getTileList()[map[j][i]].getImage(), i * 16 - handler.getPlayerX(), j * 16 - handler.getPlayerY());
}
}
}
@Override
public void update(GameContainer gc, int delta) {
worldCollision.clear();
for (int i = 0; i < 87; i++) {
for (int j = 0; j < 35; j++) {
if(handler.getTileList()[map[j][i]].hasCollision()){
worldCollision.add(new Rectangle(i * 16 - handler.getPlayerX(), j * 16 - handler.getPlayerY(), 16, 16));
}
}
}
handler.setWorldCollision(worldCollision);
}
}
谢谢指教!
我不确定我是否完全理解为什么会出现这种重叠。你说“如果我尽可能靠近边缘,边缘似乎会重叠”,所以在向上时会发生重叠,但在向左或向右移动时不会纠正?
顺便说一句,如果左右移动时没有检测到,那是因为你只在上行或下行时检查Y碰撞;虽然这应该足够了,但这就是为什么当左右移动并且已经与边缘重叠时这不是 corrected/detected 的原因!