使用 BufferedImage 的 getRGB 进行每像素碰撞(Java2D Api)

发布于 2024-09-29 20:01:39 字数 570 浏览 1 评论 0原文

你好,我目前正在开发一款 2D 平台游戏。 我希望我的播放器(矩形)和自由地形(使用斜坡、BufferedImage)之间发生逐像素碰撞。

我对检查矩形的任何部分的概念有点困惑 与地形发生碰撞。

目前我正在尝试查看地形的一部分是否包含不透明像素。 我将其与矩形中的每个坐标进行比较,看看它们是否相遇,但是我运气不佳。

这是我的代码:

    public boolean rgbCollide () {
    int a = terrain.getRGB(x, y);
    System.out.println(a);
    // Per-pixel Bitwise collision check
    for (int i =0; i < width; i++) {
        for (int j =0; j < height; j++) {
           //Hmm what to do here...? 
        }
    }
    return false;
}

其中:地形是我的 bufferedImage x、y、宽度和高度是我的玩家的矩形坐标

Hello I'm currently working on a 2D platformer game.
I would like to have per-pixel collisions between my player (a Rectangle) and a freeform terrain (uses slopes, a BufferedImage).

I am a bit confused on the concept to check if any part of my rectangle
collides with the terrain.

Currently I'm trying to see if a part of my terrain contains a non-transparent pixel.
I compare this to each coordinate in my rectangle and see if they meet, however I am not having luck.

Here is my code:

    public boolean rgbCollide () {
    int a = terrain.getRGB(x, y);
    System.out.println(a);
    // Per-pixel Bitwise collision check
    for (int i =0; i < width; i++) {
        for (int j =0; j < height; j++) {
           //Hmm what to do here...? 
        }
    }
    return false;
}

where: terrain is my bufferedImage
x,y,width, and height are my player's Rectangle coordinates

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

残疾 2024-10-06 20:01:39

我猜你的游戏没有滚动功能?

你至少需要
玩家的位置 - 比如说矩形左下角的 x,y
玩家的宽度、高度
地形位图

所以它会是这样的:

public boolean rgbCollide (
    terrain,
    playerX,
    playerY,
    playerWidth,
    playerHeight
) {

    int startX = max(playerX,0);
    int endX = min(playerX + playerWidth, terrain.width());
    int startY = max(playerY-playerHeight,0); //because Y goes from top to bottom
    int endY = min(playerY, terrain.height());

    for (int y = startY; y < endY; y++) {
        for (int x = startX; x < endX; x++) {
            if (terrain.getRGB(x, y) is not transparent) {
                return true;
            }
        }
    }

    return false;
}

我不知道java2d api,所以也许方法 width() 和 height() 的调用方式不同。检查“如果不透明”也取决于api,所以它留给学生作为练习:)。

I assume your game doesn't have scrolling?

You need at least
position of player - say x,y of the left bottom corner of the rectangle
width, height of player
terrain bitmap

So it will be sth like that:

public boolean rgbCollide (
    terrain,
    playerX,
    playerY,
    playerWidth,
    playerHeight
) {

    int startX = max(playerX,0);
    int endX = min(playerX + playerWidth, terrain.width());
    int startY = max(playerY-playerHeight,0); //because Y goes from top to bottom
    int endY = min(playerY, terrain.height());

    for (int y = startY; y < endY; y++) {
        for (int x = startX; x < endX; x++) {
            if (terrain.getRGB(x, y) is not transparent) {
                return true;
            }
        }
    }

    return false;
}

I don't know java2d api, so maybe the methods width() and height() are called differently there. Checking "if not transparent" also depends on api, so it is left as exercise to the student :).

甜尕妞 2024-10-06 20:01:39

假设您使用 ARGB 格式,最高 8 位代表 alpha(透明度)通道。
像素完美碰撞

public class RectanglePixelCollisionChecker implements CollisionChecker {

    private static final RectangleCollisionChecker RECTANGLE_COLLISION_CHECKER = new RectangleCollisionChecker();
    /*

          ax,ay ___________ax + a.width
            |                 |
            |                 |
            |  bx, by_________|__ bx + b.width
            |  |(INTERSECTION)|       |
            |__|______________|       |
            ay + height               |
               |______________________|
             by + height
          */
    @Override
    public boolean collide(Collidable collidable, Collidable collidable2) {
        // check if bounding boxes intersect
        if(!RECTANGLE_COLLISION_CHECKER.collide(collidable, collidable2)) {
            return false;
        }

        // get the overlapping box
        int startX = Math.max(collidable.getX(), collidable2.getX());
        int endX = Math.min(collidable.getX() + collidable.getWidth(), collidable2.getX() + collidable2.getWidth());

        int startY = Math.max(collidable.getY(), collidable2.getY());
        int endY = Math.min(collidable.getY() + collidable.getHeight(), collidable2.getY() + collidable2.getHeight());

        for(int y = startY ; y < endY ; y++) {
            for(int x = startX ; x < endX ; x++) {
                // compute offsets for surface
                if((!isTransparent(collidable2.getBufferedImage(), x - collidable2.getX(), y - collidable2.getY()))
                        && (!isTransparent(collidable.getBufferedImage(), x - collidable.getX(), y - collidable.getY()))) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isTransparent(BufferedImage bufferedImage, int x, int y) {
        int pixel = bufferedImage.getRGB(x, y);
        if((pixel & 0xFF000000) == 0x00000000) {
            return true;
        }
        return false;
    }

}

矩形碰撞

public class RectangleCollisionChecker implements CollisionChecker {

    @Override
    public boolean collide(final Collidable c1, Collidable c2) {
        if((c1.getX() + c1.getWidth() < c2.getX()) || (c2.getX() + c2.getWidth() < c1.getX())) {
            return false;
        }
        if((c1.getY() + c1.getHeight() < c2.getY()) || (c2.getY() + c2.getHeight() < c1.getY())) {
            return false;
        }
        return true;
    }

}

可碰撞界面

public interface Collidable {
    boolean collide(Collidable collidable);
    int getX();
    int getY();
    int getWidth();
    int getHeight();
    BufferedImage getBufferedImage();
}

Assuming you are using the ARGB format the highest 8 bits represent the alpha (transparency) channel.
Pixel Perfect Collision

public class RectanglePixelCollisionChecker implements CollisionChecker {

    private static final RectangleCollisionChecker RECTANGLE_COLLISION_CHECKER = new RectangleCollisionChecker();
    /*

          ax,ay ___________ax + a.width
            |                 |
            |                 |
            |  bx, by_________|__ bx + b.width
            |  |(INTERSECTION)|       |
            |__|______________|       |
            ay + height               |
               |______________________|
             by + height
          */
    @Override
    public boolean collide(Collidable collidable, Collidable collidable2) {
        // check if bounding boxes intersect
        if(!RECTANGLE_COLLISION_CHECKER.collide(collidable, collidable2)) {
            return false;
        }

        // get the overlapping box
        int startX = Math.max(collidable.getX(), collidable2.getX());
        int endX = Math.min(collidable.getX() + collidable.getWidth(), collidable2.getX() + collidable2.getWidth());

        int startY = Math.max(collidable.getY(), collidable2.getY());
        int endY = Math.min(collidable.getY() + collidable.getHeight(), collidable2.getY() + collidable2.getHeight());

        for(int y = startY ; y < endY ; y++) {
            for(int x = startX ; x < endX ; x++) {
                // compute offsets for surface
                if((!isTransparent(collidable2.getBufferedImage(), x - collidable2.getX(), y - collidable2.getY()))
                        && (!isTransparent(collidable.getBufferedImage(), x - collidable.getX(), y - collidable.getY()))) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isTransparent(BufferedImage bufferedImage, int x, int y) {
        int pixel = bufferedImage.getRGB(x, y);
        if((pixel & 0xFF000000) == 0x00000000) {
            return true;
        }
        return false;
    }

}

Rectangle Collision

public class RectangleCollisionChecker implements CollisionChecker {

    @Override
    public boolean collide(final Collidable c1, Collidable c2) {
        if((c1.getX() + c1.getWidth() < c2.getX()) || (c2.getX() + c2.getWidth() < c1.getX())) {
            return false;
        }
        if((c1.getY() + c1.getHeight() < c2.getY()) || (c2.getY() + c2.getHeight() < c1.getY())) {
            return false;
        }
        return true;
    }

}

Collidable Interface

public interface Collidable {
    boolean collide(Collidable collidable);
    int getX();
    int getY();
    int getWidth();
    int getHeight();
    BufferedImage getBufferedImage();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文