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/
|
|
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:
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..
--
|
|
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/
|
|
Profil || Suche
|
003
13.10.2002, 18:04
chriss
|
haste mal probiert den schläger in 3 teile zu teilen?
links mitte oben?
--
|
|
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.
--
|
|
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/
|
|
Profil || Suche
|
006
13.10.2002, 20:27
chriss
|
jo, wie gesagt.. ich kenn mich damit net so aus ;)
--
|
|
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*
#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
|
|
Profil || Suche
|
008
17.10.2002, 14:27
Mazze
|
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/
|
|
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.
|
|
Profil || Suche
|
010
18.10.2002, 14:59
Mazze
|
Oh...thx Werd's mal versuchen so zu implementieren.
--
BattleTech-MOD: http://bthl.unitedgaming.net/
|
|
Profil || Suche
|
011
19.10.2002, 17:29
Mazze
|
Es funktioniert!
Thx an alle, die was gepostet haben!
--
BattleTech-MOD: http://bthl.unitedgaming.net/
|
|
Profil || Suche
|