检测多个缓冲区映像的冲突Java
我正在用java制作一个2d rpg游戏,我遇到了一个问题。我可以让玩家在舞台上走动,舞台上也有岩石、树木、墙壁等。我不知道如何检测碰撞并使其到达玩家无法穿过物体的位置。读取地图文件并在画布上绘制图像的代码如下:检测多个缓冲区映像的冲突Java,java,collision-detection,bufferedimage,game-physics,Java,Collision Detection,Bufferedimage,Game Physics,我正在用java制作一个2d rpg游戏,我遇到了一个问题。我可以让玩家在舞台上走动,舞台上也有岩石、树木、墙壁等。我不知道如何检测碰撞并使其到达玩家无法穿过物体的位置。读取地图文件并在画布上绘制图像的代码如下: public void loadLevel(BufferedImage levelImage){ tiles = new int[levelImage.getWidth()][levelImage.getHeight()]; for (int y = 0; y <
public void loadLevel(BufferedImage levelImage){
tiles = new int[levelImage.getWidth()][levelImage.getHeight()];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
Color c = new Color(levelImage.getRGB(x, y));
String h = String.format("%02x%02x%02x", c.getRed(),c.getGreen(),c.getBlue());
switch(h){
case "00ff00"://GRASS Tile - 1
tiles[x][y] = 1;
break;
case "808080"://Stone -2
tiles[x][y] = 2;
break;
case "894627"://Dirt -3
tiles[x][y] = 3;
break;
case "404040"://Rock on Grass -4
tiles[x][y] = 4;
break;
case "00b700"://Tree -5
tiles[x][y] = 5;
break;
case"000000"://Wall -6
tiles[x][y] = 6;
break;
case "cccccc"://Rock on stone -7
tiles[x][y] = 7;
break;
default:
tiles[x][y] = 1;
System.out.println(h);
break;
}
}
}
}
}
我真的不知道如何进行碰撞,但我在谷歌上搜索了一下,人们说要为玩家和玩家应该碰撞的所有对象制作一个矩形,每当玩家移动时,移动玩家的矩形。这样做对吗
编辑编辑编辑
碰撞为真时的代码:
if (rt) {
x+=SPEED;
locx = x;
locy = y;
playerR.setLocation(locx, locy);
for(int i = 0;i<Level.collisions.size();i++){
if(intersects(playerR,Level.collisions.get(i))==true){
x-=SPEED;
locx = x;
playerR.setLocation(locx, locy);
}
}
moving = true;
}
我将重点讨论你的勾选方法,因为这是这个逻辑的主要方向。这里有一些变化。最值得注意的是,我们只在检查碰撞之前移动矩形。然后循环通过关卡中的所有可碰撞对象。一旦找到一个,我们重置x和y并打破循环(因为我们已经找到了我们碰撞的那个对象,所以看其他任何对象都没有意义)。然后我们更新我们的球员位置。通过这种方式,我集中了代码,因此不会重复。如果您曾经看到自己在重复代码,那么很有可能它会被拉到一个公共位置或一个方法
public void tick() {
if (up) {
y -= SPEED;
} else if (dn) {
y += SPEED;
} else if (lt) {
x -= SPEED;
} else if (rt) {
x += SPEED;
}
playerR.setLocation(x, y);
for (Rectangle collideable : Level.collisions) {
if (intersects(playerR, collideable)) {
x = locx;
y = locy;
playerR.setLocation(x, y);
break;
}
}
locx = x;
locy = y;
}
有不同的方法可以做到这一点。当你谈论“rpg”时,我认为你的观点是等距的(45°自上而下)。
我会用纯90°自上而下的方式进行碰撞检测,因为这样更容易,更真实。
我们有两种可能性:
播放器
移动到下一个位置。如果发生碰撞,重置其位置if ((player.x - object.x)² + (player.y - object.y)² <= dangerRadius²)
// Check for intersection
if((player.x-object.x)²+(player.y-object.y)²我个人对Java相当陌生,尽管我过去曾与C#合作过。我正在制作一个类似的游戏,为了进行碰撞检测,我只需检查玩家和对象的位置:
if (z.gettileX() == p.gettileX()){
if (z.gettileY() == p.gettileY()){
System.out.println("Collision!");
}
}
如果玩家(p)的X坐标和Y坐标与z坐标相等(坏人),它将发送此消息并确认两者实际上发生了碰撞。如果您可以在z后面的实际类中固有它来检查坐标a是否相等,那么您可以创建无限数量的游戏内对象,这些对象检测碰撞并以相同的方式作出反应,即墙。这可能就是您所寻找的。我制作了这个class专门用于多个对象的碰撞和单个侧面碰撞
abstract class Entity {
private Line2D topLine;
private Line2D bottomLine;
private Line2D leftLine;
private Line2D rightLine;
private Rectangle rectangle;
private Entity entity;
protected boolean top;
protected boolean bottom;
protected boolean left;
protected boolean right;
protected int x;
protected int y;
protected int width;
protected int height;
public Entity(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
updateLinesAndRects();
}
public void updateLinesAndRects() {
topLine = new Line(x + 1, y, width - 2, 0);
bottomLine = new Line(x + 1, y + height, width - 2, height);
leftLine = new Line(x, y + 1, 0, height - 2);
rightLine = new Line(x + width, y + 1, 0, height - 2);
rectangle = new Rectangle(x, y, width, height)
}
public void setCollision(Entity entity) {
this.entity = entity;
top = isColliding(new Line2D[]{topLine, bottomLine, leftLine, rightLine});
bottom = isColliding(new Line2D[]{bottomLine, topLine, leftLine, rightLine});
left = isColliding(new Line2D[]{leftLine, topLine, bottomLine, rightLine});
right = isColliding(new Line2D[]{rightLine, topLine, bottomLine, leftLine});
}
public void updateBounds() {
if(top) y = entity.y + entity.height;
if(bottom) y = entity.y - height;
if(left) x = entity.x + entity.width;
if(right) x = entity.x - width;
}
public boolean isColliding() {
return rectangle.intersects(entity.rect);
}
private boolean isLinesColliding(Line2D[] lines) {
Rectangle rect = entity.getRectangle();
return lines[0].intersects(rect) && !lines[1].intersects(rect) && !lines[2].intersects(rect) && !lines[3].intersects(rect);
}
private Line2D line(float x, float y, float width, float height) {
return new Line2D(new Point2D.Float(x, y), new Point2D.Float(x + width, x + height));
}
public Rectangle getRectangle() {
return rectangle;
}
}
例如:
class Player extends Entity{
Entity[] entities;
public Player(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void update() {
updateLinesAndRects();
for(Entity entity : entities) {
setCollision(entity);
if(top) system.out.println("player is colliding from the top!");
if(isColliding()) system.out.println("player is colliding!");
updateBounds(); // updates the collision bounds for the player from the entities when colliding.
}
}
public void setEntities(Entity[] entities) {
this.entities = entities;
}
}
一般来说,是的,最简单的2D碰撞检测是用矩形或圆形物体完成的。这些物体需要连接到屏幕上移动的物体上,这样才能计算碰撞检测。看看JBox2D,它是一个开源的物理引擎。有没有一种方法可以不用任何外部引擎或任何东西来实现这一点?是的当然。看起来你已经对玩家有了一个开始。确保玩家每次移动时矩形都会更新。你还需要在你想知道玩家是否与之碰撞的任何东西上添加一个矩形。最后,你需要在每个帧中循环所有可碰撞的对象,看看玩家的矩形是否正确le与对象的矩形相交。这是一个非常粗略的算法,但这是一个很好的起点。在第一种方法中,我如何为每个“草地上的岩石”创建一个矩形?我曾想过将矩形存储在ArrayList中,但我不确定如何对其进行编码?或者是否有更好的方法。此外,为了检查碰撞,请d我在Player类中的tick方法的开头使用for循环,如果发生碰撞,则将CanMove设置为false?最后,要检查碰撞,我使用.intersects right?一个包含所有可碰撞矩形的ArrayList是完全可以接受的。在创建对象时添加它们。至于检测碰撞,请按原样移动播放器mally会的。如果发生碰撞,请将播放机向后移动。您必须移动播放机才能确定是否发生碰撞。如果您想更有趣,只需将播放机向后移动足够远,以便不再发生碰撞。使用Rectangle.intersects()可以,或者如果您想自己学习它的工作原理,请创建一个新方法private boolean intersects(矩形r1,矩形r2)
我试过了,但不幸的是,它不起作用。玩家正通过对象移动。还有其他想法吗?关卡类循环的x和y值与画布的x和y值不在同一比例上吗?我在地图文件中读取的for循环只指向x 20和y 20,因为地图文件是20像素乘20像素。有没有办法得到整个磁贴的坐标?因为我发现有碰撞发生,但只发生在左上角的磁贴上。这不是玩家应该碰撞的对象所在的位置。忽略我刚才所说的一切。我忘了用我的刻度乘以x和y,所以一切都合适。抱歉,还有谢谢你的帮助!
abstract class Entity {
private Line2D topLine;
private Line2D bottomLine;
private Line2D leftLine;
private Line2D rightLine;
private Rectangle rectangle;
private Entity entity;
protected boolean top;
protected boolean bottom;
protected boolean left;
protected boolean right;
protected int x;
protected int y;
protected int width;
protected int height;
public Entity(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
updateLinesAndRects();
}
public void updateLinesAndRects() {
topLine = new Line(x + 1, y, width - 2, 0);
bottomLine = new Line(x + 1, y + height, width - 2, height);
leftLine = new Line(x, y + 1, 0, height - 2);
rightLine = new Line(x + width, y + 1, 0, height - 2);
rectangle = new Rectangle(x, y, width, height)
}
public void setCollision(Entity entity) {
this.entity = entity;
top = isColliding(new Line2D[]{topLine, bottomLine, leftLine, rightLine});
bottom = isColliding(new Line2D[]{bottomLine, topLine, leftLine, rightLine});
left = isColliding(new Line2D[]{leftLine, topLine, bottomLine, rightLine});
right = isColliding(new Line2D[]{rightLine, topLine, bottomLine, leftLine});
}
public void updateBounds() {
if(top) y = entity.y + entity.height;
if(bottom) y = entity.y - height;
if(left) x = entity.x + entity.width;
if(right) x = entity.x - width;
}
public boolean isColliding() {
return rectangle.intersects(entity.rect);
}
private boolean isLinesColliding(Line2D[] lines) {
Rectangle rect = entity.getRectangle();
return lines[0].intersects(rect) && !lines[1].intersects(rect) && !lines[2].intersects(rect) && !lines[3].intersects(rect);
}
private Line2D line(float x, float y, float width, float height) {
return new Line2D(new Point2D.Float(x, y), new Point2D.Float(x + width, x + height));
}
public Rectangle getRectangle() {
return rectangle;
}
}
class Player extends Entity{
Entity[] entities;
public Player(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void update() {
updateLinesAndRects();
for(Entity entity : entities) {
setCollision(entity);
if(top) system.out.println("player is colliding from the top!");
if(isColliding()) system.out.println("player is colliding!");
updateBounds(); // updates the collision bounds for the player from the entities when colliding.
}
}
public void setEntities(Entity[] entities) {
this.entities = entities;
}
}