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 😞


Anmelden zum Antworten