开发者

per-pixel collision using getRGB of a BufferedImage (Java2D Api)

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


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 :).


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();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜