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();
}
精彩评论