Schnarschalarm: Funktions optimierung
-
Hi,
ich hab eine Pixelgenaue Kollsionsabfrage für D3D, doch die könnte mal eine neue Polierung gebrauchen, denn sie ist sehr groß und lam
bool SM_DDraw7_Collision(int x1, int y1, // Pixelgenaue Kollisionsabfrage RECT &rect1, IDirect3DTexture9* lpDDSurf1, int x2, int y2, RECT &rect2, IDirect3DTexture9* lpDDSurf2) { bool collide = false; // Kollision ? static int breite; // Wie breit muss getestet werden static int hoehe; // Wie hoch muss getestet werden static int xg1, yg1, xg2, yg2; // Grössen der Sprite-Ausschnitte static int pitch1, pitch2; // Pitch-Grösse static int xOffset1 = 0; // xOffset in Surface1 wenn alle 0 sind, static int yOffset1 = 0; // yOffset in Surface1 heisst das, dass die static int xOffset2 = 0; // xOffset in Surface2 Objekte die gleichen static int yOffset2 = 0; // yOffset in Surface2 Koordinaten haben static DWORD *vram1; // Zeiger auf Grafikdaten von Objekt 1 static DWORD *vram2; // Zeiger auf Grafikdaten von Objekt 2 static D3DLOCKED_RECT d3drect_; // Surface-Beschreibung // Grösse der Sprite-Ausschnitte festlegen (weil der Wert recht oft vorkommt) xg1 = rect1.right - rect1.left; xg2 = rect2.right - rect2.left; yg1 = rect1.bottom - rect1.top; yg2 = rect2.bottom - rect2.top; // Also gut, BoundingBox-Kollision war erfolgreich (separate Funktion), // jetzt schauen wirs uns genauer an. // Zuerst müssen wir die Positionen zueinander checken, um die Offsets in den // einzelnen Surfaces zu errechnen if(x1<x2) // Objekt1 ist Links von Objekt2 xOffset1 = x2-x1; else if(x1>x2) // Objekt1 ist Rechts von Objekt2 xOffset2 = x1-x2; if(y1<y2) // Objekt1 ist oberhalb von Objekt2 yOffset1 = y2-y1; else if(y1>y2) // Objekt1 ist unterhalb von Objekt2 yOffset2 = y1-y2; // Die Surfaces der zwei Sprites locken und die Zeiger holen ZeroMemory(&d3drect_, sizeof(d3drect_)); // Objekt 1 lpDDSurf1->LockRect (0, &d3drect_, NULL, 0); vram1 = (unsigned long*)d3drect_.pBits; pitch1 = (int)(d3drect_.Pitch>>2); // Objekt 2 lpDDSurf2->LockRect (0, &d3drect_, NULL, 0); vram2 = (unsigned long *)d3drect_.pBits; pitch2 = (int)(d3drect_.Pitch>>2); // Die zu prüfende Grösse des Rechteckes ermittlen, damit wir NUR den Bereich // prüfen, der auch notwendig ist (klappt noch nich so ganz :-D) if(xg1<xg2) breite = xg1; else breite = xg2; if(yg1<yg2) hoehe = yg1; else hoehe = yg2; // Und dann testen wir endlich die Kollision Pixel für Pixel for(int i=0; i<breite; i++) for(int j=0; j<hoehe && collide == false; j++) { if((xOffset2+i < xg2) && (yOffset2+j < yg2) // noch im testbaren Bereich ? &&(xOffset1+i < xg1) && (yOffset1+j < yg1)) if((vram1[rect1.left + xOffset1 + i +(rect1.top + yOffset1+j)*pitch1] != COLOR_ARGB2(0,255,0,255)) && (vram2[rect2.left + xOffset2 + i +(rect2.top + yOffset2+j)*pitch2] != COLOR_ARGB2(0,255,0,255))) { collide = true; break; } } // Surfaces wieder freigeben (egal, ob Kollision oder nicht) lpDDSurf2->UnlockRect(0); lpDDSurf1->UnlockRect(0); return (collide); }
Hat jemand ideen?
-
ich würde die logik von der bildschirmausgabe trennen, also nicht die pixel im speicher vergleichen. sowas ist nur bei kleinen displays schnell genug.
-
Halt Dir zu jedem Sprite noch eine Bitmap, die die Form des Sprites enthaelt. Ueberall, wo das Sprite ein sichtbares Pixel hat, hat die Bitmap eine 1, sonst 0. Eine zweite Bitmap enthaelt eine Zeile, in der alle Zeilen der Maske ODER-verknuepft sind. Die einzeilige Maske kann man benutzen, um eine Grobpruefung zu machen, bevor die Feinpruefung gemacht wird. Bei Letzterem wird der Bereich der Bitmaske der beiden Sprites, die sich ueberlageren, UND-vernkuepft. Sind alle Bits des Ergebnisses 0, sind die Sprites nicht kollidiert, ansonsten sind sie es.
-
Ich meinte eher codeoptimierungen, bitmasken werd ich schon reintuen, aber mir gehts momentan mehr um den code, denn wie ihr seht ist der sehr dirty