JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=99e44e037c195e692cee9ff8a6e3e3cbMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Pixelgenaue Kollisionserkennung

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> DirectX, OpenGL
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 22:38    Titel: Pixelgenaue Kollisionserkennung Antworten mit Zitat

Hi all Smile
entwickle gerade an einem einfachen Shooter Spiel in 2d.
ich verwende eigentlich 1 zu 1 die Klassen wie sie im Buch angelegt wurden, also die Spriteklasse und den Ressourcen Manager. Jetzt brauche ich irgend eine Möglichkeit pixelgenau kollisionen abzufragen ( das mit der optimierung vorher das man nur naheliegende Frames abfrägt krieg ich schon gebacken ) ich hab nur keine ahnung wie ich auf die frames sprites selbst zugreifen
kann.

kann mir jemand helfen?

RayJunx
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 22:41    Titel: Antworten mit Zitat

Eigentlich ganz einfach, die Surface/Textur locken, jeden Pixel auslesen, damit einen Bitmaskenvergleich durchführen und gucken wo es übereinstimmungen gibt.

Das hier ist noch aus einer Nebel-Nacht Aktion und NICHT Fehlerfrei, aber zeigt die veranschaulichung einfach mal gut:
CPP:
bool collision (int x1, int y1, ::RECT &rect1, ::IDirect3DTexture9* texture1,
                int x2, int y2, ::RECT &rect2, ::IDirect3DTexture9* texture2)
{

    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 unsigned long    *vram1;                 // Zeiger auf Grafikdaten von Objekt 1
    static unsigned long    *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
    texture1->LockRect (0, &d3drect_, NULL, 0);
    vram1  = reinterpret_cast<unsigned long*>(d3drect_.pBits);
    pitch1 = static_cast<int>(d3drect_.Pitch >> 2);

        // Objekt 2
    texture2->LockRect (0, &d3drect_, NULL, 0);
    vram2  = reinterpret_cast<unsigned long*>(d3drect_.pBits);         
    pitch2 = static_cast<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++)
        {
                // Noch im Testbaren Bereich?
            if ((xOffset2+i < xg2) && (yOffset2+j < yg2)
              &&(xOffset1+i < xg1) && (yOffset1+j < yg1))
            {     
                    // Pixel genau testen!
                if ((vram1[rect1.left + xOffset1 + i +(rect1.top + yOffset1+j)*pitch1] != COLOR_ARGB(0,255,0,255))
                && (vram2[rect2.left + xOffset2 + i +(rect2.top + yOffset2+j)*pitch2] != COLOR_ARGB(0,255,0,255)))
                {
                    collide = true;
                    break;
                }
            }
   
        }
    }

        // Texturen wieder freigeben (egal, ob Kollision oder nicht)
    texture2->UnlockRect(0);
    texture1->UnlockRect(0);

    return (collide);
}

_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
PeaceKiller
JLI Master


Alter: 35
Anmeldedatum: 28.11.2002
Beiträge: 970

Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 22:43    Titel: Antworten mit Zitat

Im Fighter-Beispiel wird doch auch pixelgenaue Kollisionserkennung benützt.
_________________
»If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.«
– Robert X. Cringely, InfoWorld magazine
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 22:48    Titel: leider nicht Antworten mit Zitat

beim fighter program ist es nur eine bounding box routine.leider
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 22:49    Titel: danke Antworten mit Zitat

und danke für die promte antwort!
ich werde den code gleich morgen austesten
gruß
rayjunx
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 22:50    Titel: Antworten mit Zitat

Wie schon gesagt, es läuft aber nicht immer richtig. Benutze diese sowieso nicht mehr, aber zu Lernzwecken solte diese ausreichen.
_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Christian Rousselle
Site Admin


Alter: 47
Anmeldedatum: 19.07.2002
Beiträge: 1630

Medaillen: Keine

BeitragVerfasst am: 16.01.2006, 23:08    Titel: Re: leider nicht Antworten mit Zitat

RayJunx hat Folgendes geschrieben:
beim fighter program ist es nur eine bounding box routine.leider


JLIFighter ist pixelgenau.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
philipp_boeing
JLI'ler


Alter: 34
Anmeldedatum: 26.07.2003
Beiträge: 188

Medaillen: Keine

BeitragVerfasst am: 17.01.2006, 07:01    Titel: Antworten mit Zitat

Patrick hat Folgendes geschrieben:
Wie schon gesagt, es läuft aber nicht immer richtig.

aus welchem grund sollte es nicht immer richtig laufen?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 17.01.2006, 08:45    Titel: Antworten mit Zitat

Christian hat schonmal im Forum sein Beispielprogramm für Pixelgenaue Kollisionserkennung gepostet. Das ist eigentlich leicht zu verstehen und beschränkt sich auf das nötigste. Ich weiß aber nur noch das es im Thread "Fragen und Antworten.." war.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 17.01.2006, 18:14    Titel: antwort Antworten mit Zitat

also jli fighter verwendet erst eine bounding box und danach eine umriss kollisionsberechnung. Steht auch so im buch beschrieben. dort werden zeile für zeile punkte an der textur markiert und der bereich verglichen. das müßte aber bei mehrfachhinterschneidungen probleme geben ( man stelle sich ein U vor in das von oben ein objekt HINEINFLIEGT ). das programm für die pixelgenaue Kollisionsberechnung wird im buch verwießen fehlt aber
auf der cd. habe bereits nachgefragt, und es existiert, nur keine ahnung wer es hat. Hoffe es wird bald wieder gepostet. Nach "christians" lösung werde
ich auch mal ein auge werfe. Werde jetzt erstmal testen ob ich mit den bisherigen infos schonmal weiterkomme.
vielen dank für die codes und infos!

gruß
Rayjunx
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 17.01.2006, 23:03    Titel: Fast geschafft Antworten mit Zitat

Hi Patrick,
danke für dein Beispiel,
ich habe es gleich eingebaut und die einbindung ging ohne fehlermeldungen.
habe es direkt in meine sprite in meine direct3d klasse eingebettet.

jetzt hab ich nur ein paar fragen zur verwendung und vorallem zum
ausruf. ich weiß nicht genau wo ich die parameter zur eingabe finde.
also:

x1 x2 y1 y2 stehen für die position der texturen oder? ist es egal wo sie
liegen? ich meine in welchem wertebereich? ob beide irgendwo links
oben bnahe 100,100 liegen oder im anderen eck? denke mal das
spielt keine rolle. Vielleicht am rande, es gibt die linke obere ecke an
oder? nicht die mitte...

wie sieht die eingabe für den ::RECT &rect1 parameter aus? und
was muß ich als ::IDirect3DTexture9* texture1 (und2) angeben.

ich weiß das da die grafiken rein müssen aber in welcher
form? sicher nicht wie über den ressourcen manager über
den dateinamen so ala "raumschiff.png" Wink

ich habe mal hier anbei die wesendlichen auszüge über die klassen
in meinem program, vom resourcen manager und der spriteklasse.

glaubst du du kannst mir nur mal in nem beispiel nen ausruf
für deine collisions funktion schreiben? der zwei texturen in
die in meinem manager gespeichert sind verwendet? bzw
die textur des jeweiligen Spritelements weiterleiten.

apropo soll/kann ich die collisionsfunktion in die sprite
klasse schieben? wäre besser oder?

vielen dank schonmal! und eine gute Nacht,

Rayjunx

<edit>
Hier der Code, hatte ihn vergessen, sorry

CPP:
// Konstruktor - Initialisierungen
CSprite::CSprite(void)
{
    m_Rotation = 0;

    m_StepX    = 0;
    m_StepY    = 0;

    m_Width    = 0;
    m_Height   = 0;

    m_AnimationSpeed = 0;

    m_CurrentImage   = 0.0f;

    m_lpDevice = NULL;                 
    m_lpSprite = NULL;
}



// Sprite kreiern
void CSprite::Create(LPDIRECT3DDEVICE9 lpDevice, float AnimationSpeed)
{
    m_lpDevice = lpDevice;
   
    m_AnimationSpeed = AnimationSpeed;
   
    D3DXCreateSprite(m_lpDevice, &m_lpSprite);
   
    m_vScale = D3DXVECTOR2(1.0f,1.0f);

    m_StepX = 10.0f;
    m_StepY = 10.0f;
}


// Textur für das Sprite festlegen
void CSprite::AddTexture(LPDIRECT3DTEXTURE9 lpTexture)
{
    // Beschreibung des zu Grunde liegenden Surfaces
    D3DSURFACE_DESC desc;

    lpTexture->GetLevelDesc(0,&desc);
   
    // Breite und Höhe speichern
    m_Width  = desc.Width;
    m_Height = desc.Height;

   m_vRotationCenter = D3DXVECTOR2((float)m_Width/2, (float)m_Height/2);
   
    // Zeiger auf die Textur speichern
    m_AnimationVec.push_back(lpTexture);
}


// Sprite zeichnen
void CSprite::Draw(void)
{
    // Sprite in der passenden Animationsstufe zeichnen
    m_lpSprite->Draw(m_AnimationVec[m_CurrentImage],
                     0,
                     &m_vScale,
                     &m_vRotationCenter,
                     m_Rotation,
                     &m_vPosition,
                     0xFFFFFFFF);
}

///////////////////////////////



// Textur suchen und ggf. zurückgeben
LPDIRECT3DTEXTURE9 CResourceManager::GetTexture(LPCSTR lpTextureName)
{
    // Iterator für die Suche in der Map
    map<string,LPDIRECT3DTEXTURE9>::iterator result;

    // Nach dem Namen der Textur suchen
    result = m_MapTextures.find(lpTextureName);

    // wenn der Name nicht in der Map vorhanden ist
    // NULL zurückgeben
    if(result == m_MapTextures.end())
    {
        return NULL;
    }

    // sonst den Zeiger auf die Textur zurückgeben
    return result->second;
}

// Textur hinzufügen
void CResourceManager::AddTexture(LPCSTR lpFileName)
{
    // testen, ob die Textur bereits vorhanden ist
    LPDIRECT3DTEXTURE9 lpTexture = GetTexture(lpFileName);

    // wenn sie nicht vorhanden ist, wird sie wie
    // gewohnt erzeugt
    if(!lpTexture)
    {
        D3DXIMAGE_INFO ImageInfo;
        D3DXGetImageInfoFromFile(lpFileName,&ImageInfo);

        D3DXCreateTextureFromFileEx(m_lpD3DDevice,
                                    lpFileName,
                                    ImageInfo.Width,
                                    ImageInfo.Height,
                                    1,0,
                                    D3DFMT_UNKNOWN,
                                    D3DPOOL_MANAGED,
                                    D3DX_FILTER_NONE,
                                    D3DX_FILTER_NONE,
                                    0,0,0,
                                    &lpTexture);

        // und in die Map unter ihrem Namen eingefügt
        m_MapTextures[lpFileName] = lpTexture;
    }
}


Edit(Kampfhund): Bitte statt den "code"-Tags die "cpp" Tags verwenden. Ich habs mal geändert.
Edit(TLoP): RayJunx, bitte nächstes mal den -Button verwenden, anstatt einen neuen Beitrag zu schreiben.

</edit>
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 18.01.2006, 19:59    Titel: frage an patrick Antworten mit Zitat

hey was macht eigentlich "zensiert" II ?
ich mein raptor?
hab mir eben das erste geladen Wink die alpha zum austesten.
und tust du mir nen gefallen und schreibst mir noch was zur anwendung deines kollisionsprogs
wäre mir seeehr wichtig. danach habe ich nämlich alles was ich brauche.
von ein wenig mausgeärgere mal abgesehen und avi abspielen ist aber nicht so wichtig.
gruß
Rayjunx
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Patrick
Dark JLI Master



Anmeldedatum: 25.10.2004
Beiträge: 1895
Wohnort: Düren
Medaillen: Keine

BeitragVerfasst am: 18.01.2006, 20:10    Titel: Antworten mit Zitat

RayJunx
Raptor macht nix mehr, musste es ja einstellen. Aber egal

Zur Funktion
CPP:
bool collision (int x1, int y1, ::RECT &rect1, ::IDirect3DTexture9* texture1,
                int x2, int y2, ::RECT &rect2, ::IDirect3DTexture9* texture2)

x1 und y1 ist die Position von Objekt 1.
x2 und y2 ist die Position von Objekt 2.

rect1 beschreibt den Ausschnitt auf der Bitmap den Objekt 1 benutzt.
rect2 beschreibt den Ausschnitt auf der Bitmap den Objekt 2 benutzt.

texture1 ist die Textur die für Objekt 1 benutzt wird.
texture2 ist die Textur die für Objekt 2 benutzt wird.

Wie schon gesagt: SEHR verbuggt aber zum Rumtüfteln reicht es.
_________________
'Wer der Beste sein will muss nach Perfektion streben und jede Gelegenheit nutzen sich zu verbessern.' - KIA
[ German Game Dev | Boardsuche hilft sehr oft | Google rockt | Wie man Fragen richtig stellt | ICQ#: 143040199 ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
RayJunx
JLI'ler


Alter: 43
Anmeldedatum: 16.01.2006
Beiträge: 130
Wohnort: Bayern
Medaillen: Keine

BeitragVerfasst am: 18.01.2006, 21:05    Titel: Danke Antworten mit Zitat

danke,
ein wenig hat es mir geholfen, ich werde damit rumspielen bis es hinhaut.
hab jetzt auch endlich das mausproblem gelöst, jetzt kann ich mich ganz auf diese letzte große hürde konzentrieren.
gruß
Rayjunx
_________________
Just a Freak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> DirectX, OpenGL Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum