gpt4 book ai didi

java - 静止物体与运动物体的碰撞

转载 作者:行者123 更新时间:2023-12-02 11:06:13 26 4
gpt4 key购买 nike

我正在构建一个迷宫游戏,这里有一个简单的 map ......

直到没有问题,但我的问题是碰撞

这是我的 map :

enter image description here

这里我用以下代码自己构建了 map :

package maze;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;

public class Maze1 extends GameObject{

public Maze1(int x, int y, ID id) {
super(x, y, id);
}

public void tick() {

}

public void render(Graphics g){
Font fnt = new Font("arial", 1, 25);
g.setFont(fnt);
g.drawString("Level : 1",165 , 433);

//x, y, WIDTH, HEIGHT
g.setColor(Color.darkGray);
g.fillRect(65, 65, 130 ,15);
g.fillRect(0, 130, 145 ,15);
g.fillRect(195, 195, 400 ,15);
g.fillRect(65, 195, 80 ,15);
g.fillRect(130, 260, 80 ,15);
g.fillRect(65, 325, 195 ,15);
g.fillRect(325, 325, 80 ,15);

// x, y, WIDTH, HEIGHT

g.fillRect(195, 130, 80 ,80);
g.fillRect(260, 0, 145 ,80);

//x, y, HEIGHT, WIDTH

g.fillRect(65, 145, 15 ,130);
g.fillRect(195, 65, 15 ,195);
g.fillRect(260, 260, 15 ,130);
g.fillRect(325, 130, 15 ,80);
g.fillRect(325, 260, 15 ,65);


g.setColor(Color.black);
g.fillRect(0, -20, 500 ,32); //x, y, WIDTH, HEIGHT
g.fillRect(0, 390, 500 ,15);
g.fillRect(0, Game.HEIGHT - 41, 500 ,30);
g.fillRect(-20, 0, 32 ,500);
g.fillRect(Game.WIDTH -18, 0, 32 ,340);
g.fillRect(Game.WIDTH -18, 400, 32 ,100);
}
}

此碰撞代码适用于右上角矩形

我尝试了两种不同类型的碰撞代码,但都不起作用

碰撞代码:

public void collision() {
if(this.getX() >=229 && this.getY() <= 79) {
if(this.getX() >=229) {
this.setVelX(0);
this.setVelY(0);
this.setX(this.getX() -1);
}

if(this.getY() <= 79){
this.setVelX(0);
this.setVelY(0);
this.setY(this.getY() +1);
}
}

这里,当玩家从左侧击中矩形时,玩家会向下移动,而当玩家从底部击中矩形时,玩家会向左移动。

我已经用 if, else if 语句尝试了相同的代码,但它仍然不起作用。当玩家击中左侧时,它可以正常工作,但是当玩家从底部击中矩形时,它会传送到矩形的边缘。

我希望我的描述足以让您了解我的情况。

提前致谢!

最佳答案

对于碰撞检测,我建议将 map 数据保存在矩形列表中。像这样的东西:

public class Rect {
public int topLeftX;
public int topLeftY;
public int width;
public int height;

public Rect(int x, int y, int w, int h){
topLeftX = x;
topLeftY = y;
width = w;
height = h;
}


//Ignore the code below here for now


public boolean collidingWith(int x, int y, int width, int height){
Rect r = new Rect(x, y, width, height);
boolean rLeftInWidth = r.topLeftX > topLeftX && r.topLeftX < topLeftX + width;
boolean rRightInWidth = r.topLeftX + r.width > topLeftX && r.topLeftX + width < topLeftX + width;
boolean rTopInHeight = r.topLeftY > topLeftY && r.topLeftY < topLeftY + width;
boolean rBottomInHeight = r.topLeftY + r.width > topLeftY && r.topLeftY + width < topLeftY + width;


if(rLeftInWidth || rRightInWidth){
//If there is horizantal overlap between the other rectangle and this one
if(rTopInHeight || rBottomInHeight){
//If there is also vertical overlap then we must be colliding
return true;
}
}
return false;
}
}

然后将矩形保存在数组或某种集合中,ArrayList 可能是最简单的。

ArrayList<Rect> wallData = new ArrayList<Rect>();

然后您可以添加 map 数据。这是取自你的矩形绘画:

g.fillRect(65, 65, 130 ,15);

它变成一个矩形,具有相同的参数。您甚至可以在填充矩形并重复使用之前执行此操作。

wallData.add(new Rect(65, 65, 130, 15));
Rect r = wallData.get(0);
g.fillRect(r.topLeftX, r.topLeftY, r.width, r.height);

既然您已经有了这些数据,那么如何使用它呢?当您想要检查碰撞时,只需循环遍历矩形列表并检查玩家是否发生碰撞。

for(Rect rectangle: wallData){
if(rectangle.collidingWith(<playerX>, <playerY>, <playerWidth>, <playerHeight>)){
//Your player is colliding with a rectangle!
}
}

还记得我之前告诉你忽略的那部分吗?现在让我们回顾一下。我发誓,它比看起来更简单!

    public boolean collidingWith(int x, int y, int width, int height){ 
Rect r = new Rect(x, y, width, height);
boolean rLeftInWidth = r.topLeftX > topLeftX && r.topLeftX < topLeftX + width;
boolean rRightInWidth = r.topLeftX + r.width > topLeftX && r.topLeftX + width < topLeftX + width;
boolean rTopInHeight = r.topLeftY > topLeftY && r.topLeftY < topLeftY + width;
boolean rBottomInHeight = r.topLeftY + r.width > topLeftY && r.topLeftY + width < topLeftY + width;


if(rLeftInWidth || rRightInWidth){
//If there is horizantal overlap between the other rectangle and this one
if(rTopInHeight || rBottomInHeight){
//If there is also vertical overlap then we must be colliding
return true;
}
}
return false;
}
}

我们首先确定是否水平重叠。例如,以下内容在水平方向上重叠,但在垂直方向上不重叠。

=-----=
- -
- -
-------
+------
- -
- -
-------

您可以看出,因为带加号的角位于带等号的角之间。这四个 boolean 值仅保存我们的角是否位于另一个对象的角之间。

boolean rLeftInWidth = r.topLeftX > topLeftX && r.topLeftX < topLeftX + width;

如果我们的左上角位于其他矩形的左上角和右上角之间,则情况成立。然后我们对右角也这样做。如果其中任何一个为真,那么我们就水平重叠了!

从那里,我们只需检查它是否水平和垂直重叠。如果是,那就是碰撞,就像这样!

-------
- -
- ------
----- -
- -
------

现在,当您意识到您的玩家发生碰撞时,您会做什么?这需要一些工作,但没什么特别的。在通过将玩家的速度添加到其位置来移动玩家之前,只需保存他们的位置即可。

private int playerX;
private int playerY;

<method where you change it>{
playerX = <playerX>;
playerY = <playerY>;
<change their location according to velocity>
}

现在,如果玩家与墙壁发生碰撞,只需将其位置设置回您刚刚保存的值,并将其速度设置为 0!

设置起来有点复杂,但是一旦你开始使用,这就是一个很好的解决方案。

在这个答案中,我在<>之间放了一堆东西。这仅仅意味着您需要该值,或者这就是它所说的发生的地方。

希望这对您有帮助!如果您有任何疑问,请随时提问,我很乐意为您提供更多帮助。碰撞检测是一个复杂的课题,有很多方法。这通常是我认为对于简单应用程序来说最简单的一种。

此方法与原始方法相比的优点:

  • 您可以在绘制之前设置矩形,并将其用于绘制和碰撞检测。

如果您创建了矩形列表,则可以使用循环来绘制它们:

for(Rect r: wallData){
g.fillRect(r.topLeftX, r.topLeftY, r.width, r.height);
}
  • 易于编辑:如果您决定更改 map ,您只需更改一些矩形的宽度、高度和位置,而不必通过一堆 if 语句来尝试确定这是否是正确的。改变。 (我以前经历过)

  • 不易出错:为每面墙设置一些矩形比使用大量 if 语句要容易得多。

此方法与原始方法的缺点

  • 这个效率较低——需要更多的操作来检查玩家是否与矩形碰撞,而不是 2 个 if。此外,可能存在玩家无法碰撞的矩形。但是,效率损失非常小,尤其是在 map 中矩形数量较少的情况下。

  • 这个比较复杂。最好了解您使用的代码,而不是盲目复制粘贴。如果你需要改变,如果你不理解的话,那就更难了。 (并不是说你不这样做,只是可能会有点困难。)

关于java - 静止物体与运动物体的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50935053/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com