Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
13.10.2002, 13:50
Mazze



Hi!

Ich programmiere grad einen simplen Pong-Klon und eigentlich geht auch alles. Nur beim Kollisionscode hab ich noch ein paar Probleme.

Wenn der Ball auf den Schläger trifft, dann wird er abgelenkt. Wenn er oben auftrifft wird er nach oben abgelenkt, wenn er an die Seite trifft zur Seite.

Zu testen, ob sich 2 Rechtecke (Ball, Schläger) schneiden ist ja nicht sonderlich schwer.
Nur wie krieg ich am elegantesten raus, ob sie sich an der seite oder oben schneiden?
Da ist mir jetzt noch keine einfache Lösung eingefallen!

Wär nett, wenn ihr mir da auf die Sprünge helfen könntet. Steh sicher nur auf dem Schlauch!

thx
Matze

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
001
13.10.2002, 15:15
chriss



ich kenne mich mit dem ganzen zeug nicht so aus ;) aber ich hab zufällig das hier entdeckt:

Quellcode:Pixelgenaue Kollision testen (by Eiswuxe)

// -------------------------------------------------------
// ------ Pixelgenaue Kollision testen (by Eiswuxe) ------
// -------------------------------------------------------
//
bool DDraw7_Collision(int x1, int y1,
                   RECT &rect1,
                   LPDIRECTDRAWSURFACE7 lpDDSurf1,
                   int x2, int y2,
                   RECT &rect2,
                   LPDIRECTDRAWSURFACE7 lpDDSurf2)
{

   bool   collide = false;            // Kollision ?
   int       breite;                        // Wie breit muss getestet werden
   int       hoehe;                        // Wie hoch muss getestet werden
   int       xg1, yg1, xg2, yg2;            // Grössen der Sprite-Ausschnitte
   int       pitch1, pitch2;                // Pitch-Grösse
   int       xOffset1 = 0;                // xOffset in Surface1       wenn alle 0 sind,
   int       yOffset1 = 0;                // yOffset in Surface1       heisst das, dass die
   int       xOffset2 = 0;                // xOffset in Surface2       Objekte die gleichen
   int       yOffset2 = 0;                // yOffset in Surface2       Koordinaten haben
   USHORT            *vram1;                // Zeiger auf Grafikdaten von Objekt 1
   USHORT            *vram2;                // Zeiger auf Grafikdaten von Objekt 2
   DDSURFACEDESC2 ddsd;                // 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;

   // Bounding-Box Abfrage
   if ((x1 > x2+xg2 ) || (y1 > y2+yg2)
   ||(x1+xg1 < x2 ) || (y1+yg1 < y2))
       return false;

   // Also gut, BoundingBox-Kollision war erfolgreich,
   // 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(&ddsd, sizeof(ddsd));
   ddsd.dwSize = sizeof(ddsd);

   // Objekt 1
   lpDDSurf1->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
   vram1 = (USHORT *)ddsd.lpSurface;        
   pitch1 = (int)(ddsd.lPitch>>1);

   // Objekt 2
   lpDDSurf2->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
   vram2 = (USHORT *)ddsd.lpSurface;        
   pitch2 = (int)(ddsd.lPitch>>1);

   // Die zu prüfende Grösse des Rechteckes ermittlen,
   // damit wir NUR den Bereich prüfen, der auch notwendig ist

   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; 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] != COLORKEYFARBE)
           && (vram2[rect2.left + xOffset2 + i +(rect2.top + yOffset2+j)*pitch2] != COLORKEYFARBE))
               collide = true;
  
       }

   // Surfaces wieder freigeben (egal, ob Kollision oder nicht)
   lpDDSurf2->Unlock(NULL);
   lpDDSurf1->Unlock(NULL);

   if(collide == true) return true;                    // Wenn Kollision, dann auch zurück
   return false;                                        // liefern, wenn nich, dann nich :)
}

[url="http://www.poke53280.de/tutorials/tutorials_kollisionabfrage.php"]Quelle[/url]

ka ob dir das weiterhelfen kann..

--

zum Seitenanfang zum Seitenende Profil || Suche
002
13.10.2002, 15:23
Mazze



Eher weniger.
Ich brauch gar nicht Pixelgenau zu testen, denn ich hab ganz primitive Rechtecke.
Und ich weiß ja, _dass_ sie sich schneiden. Mein Problem ist ich weiß nicht wo...

trotzdem Danke!

Ich hab mir schon überlegt, ob das irgendwie mit Vektoren geht, aber da kenn ich mich nicht wirklich aus...

Matze

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
003
13.10.2002, 18:04
chriss



haste mal probiert den schläger in 3 teile zu teilen?

links mitte oben?

--

zum Seitenanfang zum Seitenende Profil || Suche
004
13.10.2002, 18:18
Rockefeller



Man kann auch sehr gut die Ecken als Rundungen simulieren. Dann einfach so ne Art Kugelkollision durchführen.

--

zum Seitenanfang zum Seitenende Profil || Suche
005
13.10.2002, 19:44
Mazze



@NoX:
jo.
Das Problem dabei ist, dass es passieren kann, dass es sowohl z.b. mit links als auch mit oben kollidiert!

@Rockefeller:
Hm...jo.
Das hört sich gar nicht so blöd an. Mal schaun, ob ich da was darüber finden kann!

cu
Matze

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
006
13.10.2002, 20:27
chriss



jo, wie gesagt.. ich kenn mich damit net so aus ;)

--

zum Seitenanfang zum Seitenende Profil || Suche
007
13.10.2002, 22:47
the_viking



Machst du das in 2D oder 3D? ( "Simpler Pong-Klon" => 2D?!)

Musst du immer in 1-Pixel schritten testen, auch wenn der Ball jedesmal 5 oder mehr Pixel zurücklegt! RECT {0,0,10,10} => Wenn der Ball von unten kommt und bei der Kollision zwischen Ober- und Unterkante des Balkens liegt, ist er entweder vorne oder hinten mit ihm Kollidiert. Sonst wenn ball.x > balken.top ist, ist er garantiert unten Kollidiert und sonst oben.

So. Ich hoffe, du hast das verstanden *g*

Quellcode:

#define UNTEN 1
#define LINKS 2
#define OBEN 3
#define RECHTS 4
#define NOT_COLLIDED -1

int TestCollision(RECT* balken, RECT* ball)
{
if(!RectInRect(balken,ball))
  return NOT_COLLIDED;

// Rechts oder links?
if(ball->right >= balken->right)
{
  // Links
  // Oben oder unten?
  if(ball->bottom > balken.top)
  {
     // Oben
  }
  else
  {
     // Unten
  }
}
else
{
  // Rechts
  // Oben oder unten?
  if(ball->bottom > balken.top)
  {
     // Oben
  }
  else
  {
     // Unten
  }
}

}

// So sollte das in etwa aussehen, hab ich eben schnell hingetippt. Keine
// Performance-Besserungen enthalten! Vollständige ausführung gewünscht!

--

thx, cu, MfG the_viking

(( My =]=H=O=M=E=> Page! ))
Coder bei Brainshock-Interactive und bei Z-Software
My ICQ: #160959446

zum Seitenanfang zum Seitenende Profil || Suche
008
17.10.2002, 14:27
Mazze



Zitat:

Musst du immer in 1-Pixel schritten testen, auch wenn der Ball jedesmal 5 oder mehr Pixel zurücklegt

Genau das ist mein Problem!
Wenn der Ball nur 1 Pixel/Frame zurücklegen würde, wäre der test kein Problem, aber das kann ich ja nicht machen.

cu
Matze

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
009
17.10.2002, 15:15
Prefect



1-Pixel-Schritte müssen nicht sein, siehe: http://www.thewall.de/forum/showtopic.php?threadid=31203&time=1034860265

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
010
18.10.2002, 14:59
Mazze



Oh...thx
Werd's mal versuchen so zu implementieren.

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
011
19.10.2002, 17:29
Mazze



Es funktioniert!

Thx an alle, die was gepostet haben!

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche