检测多个缓冲区映像的冲突Java

检测多个缓冲区映像的冲突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 <

我正在用java制作一个2d rpg游戏,我遇到了一个问题。我可以让玩家在舞台上走动,舞台上也有岩石、树木、墙壁等。我不知道如何检测碰撞并使其到达玩家无法穿过物体的位置。读取地图文件并在画布上绘制图像的代码如下:

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°自上而下的方式进行碰撞检测,因为这样更容易,更真实。
我们有两种可能性:

  • 将您的
    播放器
    移动到下一个位置。如果发生碰撞,重置其位置
  • 计算下一个位置,如果发生碰撞,不要移动
  • 如果要获得“滑动”碰撞响应,必须检查碰撞将发生在哪个轴上,并仅停止/重置该轴的移动

    要进行更有效的碰撞检测,请仅检查可能发生碰撞的附近对象。 通过将正方形“dangerRadius”与玩家与对象之间的平方距离进行比较来实现此目的:

    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;
        }
    
    }