Pixel-Perfekte Kollisionserkennung Android

Ok, also arbeite ich an einem Spiel auf Android. Ich muss pixel perfekte Kollisionserkennung implementieren. Ich habe bereits die Bounding-Boxen um jedes der Bilder eingerichtet, jede Bounding-Box wird transformiert, um die aktuelle Rotation des Bildes entsprechen. Das alles funktioniert super. Ich habe auch die Pixeldaten aus jeder in einem Array gespeicherten Bitmap. Kann jemand mir helfen, herauszufinden, die effizienteste Weg, um zu erkennen, ob die Pixel überlappen? Vielen Dank im Voraus für jede Hilfe!

  • Ball Kollision: Bälle Stick zusammen
  • Pixel Perfect Collision Erkennung zwischen einer benutzerdefinierten Ansicht und einem ImageView
  • Um das JNI zu verwenden oder die JNI (Android Performance) nicht zu verwenden,
  • Matrix-Transformationen auf BoundingBox anwenden
  • Kollisionserkennung und Kollisionsreaktion
  • 4 Solutions collect form web for “Pixel-Perfekte Kollisionserkennung Android”

    Die Grundidee besteht darin, eine Bitmaske für jedes Objekt zu erstellen, in der Sie in jedem Pixel angeben, ob das Objekt tatsächlich da ist oder nicht. Dann vergleicht man jedes Pixel der Bitmasken für die beiden Objekte.

    Sie können die Anzahl der Pixel minimieren, die Sie überprüfen müssen, indem Sie den rechteckigen Bereich berechnen, in dem sich die beiden Begrenzungsfelder überlappen. Die Pixel in diesem Bereich sind das, was Sie überprüfen müssen.

    Iterieren Sie durch alle diese Pixel und überprüfen Sie, ob das Pixel in beiden Objekten gefüllt ist. Wenn einer von ihnen ist, dann haben Sie eine Kollision.

    Wenn Ihre Rechtecke mit der x / y-Achse ausgerichtet sind, um die Überlappung zu finden, finden Sie links, rechts, oben und unten der Überlappung. Es würde so etwas aussehen (ich hätte die Randfälle verschlungen haben können, habe das nicht ausprobiert):

    int left = max(obj1.left, obj2.left) int right = min(obj1.right, obj2.right) int top = min(obj1.top, obj2.top) int bottom = max(obj1.bottom, obj2.bottom) for (int x = left; x < right; x++) { for (int y = top; y < bottom; y++) { if (obj1.isFilled(x,y) && obj2.isFilled(x,y)) { return true; } } } 

    Ich habe meinen Code auf Mayra's Beispiel und habe Bitmap Pixel Kollision Handling. Ich hoffe das wird helfen.

     public class CollisionUtil { public static boolean isCollisionDetected(Sprite sprite1, Sprite sprite2){ Rect bounds1 = sprite1.getBounds(); Rect bounds2 = sprite2.getBounds(); if( Rect.intersects(bounds1, bounds2) ){ Rect collisionBounds = getCollisionBounds(bounds1, bounds2); for (int i = collisionBounds.left; i < collisionBounds.right; i++) { for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) { int sprite1Pixel = getBitmapPixel(sprite1, i, j); int sprite2Pixel = getBitmapPixel(sprite2, i, j); if( isFilled(sprite1Pixel) && isFilled(sprite2Pixel)) { return true; } } } } return false; } private static int getBitmapPixel(Sprite sprite, int i, int j) { return sprite.getBitmap().getPixel(i-(int)sprite.getX(), j-(int)sprite.getY()); } private static Rect getCollisionBounds(Rect rect1, Rect rect2) { int left = (int) Math.max(rect1.left, rect2.left); int top = (int) Math.max(rect1.top, rect2.top); int right = (int) Math.min(rect1.right, rect2.right); int bottom = (int) Math.min(rect1.bottom, rect2.bottom); return new Rect(left, top, right, bottom); } private static boolean isFilled(int pixel) { return pixel != Color.TRANSPARENT; } } 

    Ich habe den Code von arcones geändert, also funktioniert die Methode mit Bitmaps anstelle von Sprites.

     import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Rect; public class KollisionsErkennung { /** * @param bitmap1 First bitmap * @param x1 x-position of bitmap1 on screen. * @param y1 y-position of bitmap1 on screen. * @param bitmap2 Second bitmap. * @param x2 x-position of bitmap2 on screen. * @param y2 y-position of bitmap2 on screen. */ public static boolean isCollisionDetected(Bitmap bitmap1, int x1, int y1, Bitmap bitmap2, int x2, int y2) { Rect bounds1 = new Rect(x1, y1, x1+bitmap1.getWidth(), y1+bitmap1.getHeight()); Rect bounds2 = new Rect(x2, y2, x2+bitmap2.getWidth(), y2+bitmap2.getHeight()); if (Rect.intersects(bounds1, bounds2)) { Rect collisionBounds = getCollisionBounds(bounds1, bounds2); for (int i = collisionBounds.left; i < collisionBounds.right; i++) { for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) { int bitmap1Pixel = bitmap1.getPixel(i-x1, j-y1); int bitmap2Pixel = bitmap2.getPixel(i-x2, j-y2); if (isFilled(bitmap1Pixel) && isFilled(bitmap2Pixel)) { return true; } } } } return false; } private static Rect getCollisionBounds(Rect rect1, Rect rect2) { int left = (int) Math.max(rect1.left, rect2.left); int top = (int) Math.max(rect1.top, rect2.top); int right = (int) Math.min(rect1.right, rect2.right); int bottom = (int) Math.min(rect1.bottom, rect2.bottom); return new Rect(left, top, right, bottom); } private static boolean isFilled(int pixel) { return pixel != Color.TRANSPARENT; } } 

    Für meine Bedürfnisse funktioniert es schnell genug.

    Wenn jemand von euch interessiert ist, würde ich gerne den Code teilen, den ich geschrieben habe:

    Wichtig für Sie zu wissen ist, dass Sprite.getWidth () und Sprite.getHeight () einfach die Breite / Höhe der Bitmap zurückgeben, die der Sprite enthält. Sie können ganz einfach den Code für Ihre Bedürfnisse anpassen, sollte es ziemlich einfach zu verstehen, wie der Code funktioniert 🙂

     public static boolean touchesSprite(Sprite s1, Sprite s2) { Bitmap b1 = s1.getBmp(); Bitmap b2 = s2.getBmp(); int xshift = s2.getX()-s1.getX(); int yshift = s2.getY()-s1.getY(); //Test if the Sprites overlap at all if((xshift > 0 && xshift > s1.getWidth()) || (xshift < 0 && -xshift > s2.getWidth())) { return false; } if((yshift > 0 && yshift > s1.getHeight()) || (yshift < 0 && -yshift > s2.getHeight())) { return false; } //if they overlap, find out in which regions they do int leftx, rightx, topy, bottomy; int leftx2, topy2; if(xshift >= 0) { leftx = xshift; leftx2 = 0; rightx = Math.min(s1.getWidth(), s2.getWidth()+xshift); } else { rightx = Math.min(s1.getWidth(), s2.getWidth()+xshift); leftx = 0; leftx2 = -xshift; } if(yshift >= 0) { topy = yshift; topy2 = 0; bottomy = Math.min(s1.getHeight(), s2.getHeight()+yshift); } else { bottomy = Math.min(s1.getHeight(), s2.getHeight()+yshift); topy = 0; topy2 = -yshift; } //then compare the overlapping regions, //if in any spot both pixels are not transparent, return true int ys = bottomy-topy; int xs = rightx-leftx; for(int x=0; x<xs; x++) { for(int y=0; y<ys; y++) { int pxl = b1.getPixel(leftx+x, topy+y); int pxl2 = b2.getPixel(leftx2+x, topy2+y); if(!((pxl & 0xff000000) == 0x0) && !((pxl2 & 0xff000000) == 0x0)) { return true; } } } return false; } 
    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.