Jump n Run: Kollision funzt nicht



  • Hi @ all ^^.
    Ich versuche mich grad an einem Jump and Run. Bis jetzt hab ich nen Spieler und ein Object. Den Spieler kann man einfach per Tastatur steuern nur nun habe ich ein Problem. Die Map besteht aus Pointern auf Instanzen der Klasse Geometry. Die Klasse Quad hier im geposteten Code ist von Gemoetry vererbt. Sie soll mit dem Aufruf checkCollision prüfen, ob eine Kollision mit dem Objekt stattfindet. Wenn jemand ne bessere Methode kennt: Lass es mich bitte wissen ^^.

    Also nun zum Code. Ich überprufe erst, ob einer der 4 Eckpunkte des Objektes (ein Object besteht als Rechteck) innerhalb des Quads ist. Der Array m_c ist vom Typ Vector (hier als Vertex missbraucht) und enthält die Eckpunkte des Quads (im Uhrzeigersinn). Die Methoden von Object sollten sich selbst erklären :).

    Das Problem: Es passiert gar nichts. Der Spieler kollidiert nicht. Der auskommentierte Codeabschnitt ist eine frühere Version auf die Kollision zu reagieren, aber ich fand diese Reaktion zu ungenau und nur störend. Nun sollte das Object vernümpftig kollidieren (macht es aber nicht :/)

    Der Code:

    bool Quad::checkCollision(Object *object)
    {
        bool collision = false;
    
        Vector c[4];
        c[0] = Vector(object->getXPos(), object->getYPos() - object->getHeight());
        c[1] = Vector(object->getXPos() + object->getWidth(), object->getYPos() - object->getHeight());
        c[2] = Vector(object->getXPos() + object->getWidth(), object->getYPos());
        c[3] = Vector(object->getXPos(), object->getYPos());
    
        // Für alle Punkte, mit Seiten des Quads Richtung des Punktes berechnen
        for(int i=0; i<4; i++)
        {
            collision = false;
            for(int j=0; j<4; j++)
            {
                Vector s = m_c[j] - c[i];
                Vector r = m_c[(j+1)%4] - m_c[j];
    
                if(s.y * r.x > s.x * r.y) 
                {
                    collision = false;
                    break;
                }
    
                collision = true;
            }
    
            if(collision)
            {
                // Geradengleichung der Form ax + by = c berechnen
                float gla, glb, glc;
                gla = (object->getYPos() - object->getYPos()-object->getVY()) / (object->getXPos() - object->getXPos()-object->getVX());
                glb = 1.0f;
                glc = (object->getYPos()-object->getVY()) - gla * object->getXPos()-object->getVX();
    
                // Jetzt alle 4 Seiten überprüfen, dazu erstmal deren Geradengleichung aufstellen
                for(int g=0; g<4; g++)
                {
                    float eqa, eqb, eqc;
                    eqa = (m_c[(i+1)%4].y - m_c[i].y) / (m_c[(i+1)%4].x - m_c[i].x);
                    eqb = 1.0f;
                    eqc = m_c[i].y - gla * m_c[i].x;
    
                    // Jetzt haben war alle Gleichungen nun auf Kollision prüfen
                    float D = eqa * glb - eqb * gla;
    
                    // Keine Kollision mit dieser Seite ? 
                    if(D < -0.001f || D > 0.001f) continue;
    
                    // Schnittpunkt berechnen
                    float Sx = (eqc * glb - glc * eqb) / D;
                    float Sy = (eqa * glc - gla * eqc) / D;
    
                    // Liegt der Schnittpunkt auf beiden (!) Geraden ?
                    switch(g)
                    {
                    case 0:
                        if(Sx < m_c[i].x || Sx > m_c[(i+1)%4].x || Sy != m_c[i].y) continue;
                        break;
    
                    case 1:
                        if(Sy < m_c[i].y || Sy > m_c[(i+1)%4].y || Sy != m_c[i].x) continue;
                        break;
    
                    case 2:
                        if(Sx < m_c[(i+1)%4].x || Sx > m_c[i].x || Sy != m_c[i].y) continue;
                        break;
    
                    case 3:
                        if(Sy < m_c[(i+1)%4].y || Sy > m_c[i].y || Sx != m_c[i].x) continue;
                        break;
                    }
    
                    // Ok. Er liegt schonmal auf der Seite des Quads
                    // Jetzt überprüfen, ob der Schnittpunkt auf der Bewegungslinie des Objectes ist
                    Vector objvec  = Vector(object->getXPos(), object->getYPos());
                    Vector objvec2 = Vector(objvec.x-object->getVX(), objvec.y-object->getVY());
                    Vector schnitt = Vector(Sx, Sy);
    
                    float dist  = getDistance(objvec, objvec2);
                    float dist2 = getDistance(objvec, schnitt);
    
                    // Wenn der Vektor gar nicht lang genug ist, dann zur nächsten Seite
                    if(dist2 > dist) continue;
    
                    // So. Es fundet also eine Kollision statt, jetzt nur noch entsprechend reagieren :)
                    if(g == 1 || g == 3)
                    {
                        object->setXPos(object->getXPos()-object->getVX());
                        object->setVX(0.0f);
                    }
                    else if(g == 0)
                    {
                        object->setYPos(object->getYPos()-object->getVY());
                        object->setVY(0.0f-environment.getGravity());
                    }
                }
            }
            break;
        }
    
        /*
        if(collision)
        {
            object->setXPos(object->getXPos()-object->getVX());
            object->setYPos(object->getYPos()-object->getVY());
            object->setVY(0.0f);
            object->setFalling(false);
        }
        */
    
        return collision;
    }
    

    Bitte helft mir.
    Bitte 😞 .

    cu
    Squolly

    [ Dieser Beitrag wurde am 02.01.2003 um 00:12 Uhr von Squolly editiert. ]



  • aber da wird dir bestimmt niemand weiterhelfen können. das ist doch viel zu kompliziert.



  • Hi @ all nochmal ^^.
    Macht euch blos keine Gedanken um mein Problem *g+. Bekomm das schon selber hin .) Hab schon n paar Fehler gefunden und auch korrigiert. Die Kollision funktioniert zwar noch nicht vernümpftig, aber das wird schon 🙂
    @sorry : 🙂 wer auch immer du bist *g*. Ich denke hier sind sehr sehr viele Leute, die das nicht mal ansatzweiße kompliziert finden :). Hm zugegeben. Die Kommentare an einigen Stellen sind Falsch (z.B. // Liegt der Schnittpunkt auf beiden (!) Geraden ? (sollte natürlich Strecken heißen, dass er auf beiden liegt ist ja offensichtlich)) Ach egal ^^. Beim nächsten mal werd ich erstmal selber versuchen es zum laufen zu bringen und erst, wenn ich kurz vor dem Besuch der Männer mit den weißen Jacken bin, fragen 🙂

    cu ^^
    Squolly 🕶



  • http://www.fh-merseburg.de/~roesch/trash/geraden.jpg

    Wenn das deine Geraden sind, dann stelle die Geraden als x = A1 + t(A2-A1) dar. Für die zweite Gerade entsprechen x = B1 + r(B2-B1). Jetzt setzt du beide gleich um den Schnittpunkt zu erhalten. Das ist ein LGS mit 2 unbekannten und 2 Gleichungen, also simpel zu lösen. liegt t und r im Intervall (0,1) so gibts ein Schnittpunkt der beiden Strecken. Wie genau soll das Objekt dann abprallen?



  • Hier erstmal n frühe frühe Version davon. Die Spieler, Objecte und Map Geometrys sind untexturierte Quads. Damit man die Map von dem Spieler unterscheiden kann hab ich sie rot gemacht.

    [url] http://mitglied.lycos.de/Squolly/game10.zip [/url]

    TGGC: Es sollte so reagieren, dass die Objekte nicht durch die Map durchfliegen. Außerdem find ich das umstellen des LGS gar nicht so einfach. Deshalb hab ich erstmal die andere Version beiehalten.

    Vielleicht bringt das jemanden auf ne Idee 🙂



  • Nicht durchfliegen ist klar, aber soll es einfach anhalten, zurückgeworfen werden oder mit Einfalls=Ausfallswinkel abprallen.

    x = A1 + t(A2-A1)
    x = B1 + r(B2-B1)

    A1 + t(A2-A1) = B1 + r(B2-B1)

    t(A2-A1) = B1 + r(B2-B1) - A1

    t(A2-A1) - r(B2-B1) = B1 - A1 //(also das fand ich jetzt schon einfach)

    Das ist die allgemeine Form die du entweder per gauss. Verf. oder Determinanten lösen kannst.

    Bye, TGGC



  • P.S: Download geht nicht



  • PS: Download geht nur wenn man http://mitglied.lycos.de/Squolly/ als Referer im Download-Manager eingibt. Ich versteh garnicht. Testet der seinen Link noch nichtmal? 😕 🕶 😡



  • http://mitglied.lycos.de/Squolly/game10.htm
    Da sollte man die ältere Version runterladen können. Die neuere funktioniert i
    irgendwie nicht, aber wahrscheinlich liegt das an DAP.

    @TGGC:
    Ach so ^^. A1, A2, B1 und B2 sind gar keine Punkte sondern x bzw. y Koordinaten ? Also A1 == x-Koordinate von Punkt 1 usw ? Scheint so, denn dann funzt alles bei mir.
    y berechne ich dann mit:

    y = (B2-B1) * t / (A2-A1) + B1

    Stimmts so ? Jedenfalls merk ich schon das der Spieler kollidiert. Nur noch nicht so richtig *g*.

    Zur Reaktion auf die Kollision:
    Es sollte im Prinzip schon Einfalls = Ausfallswinkel sein. Dazu bräucht ich wohl die Normale der Gerade und muss dann den Winkel zwischen der Normale und dem Bewegungsvektor berechnen. Und dann ?

    cu
    Squolly



  • Original erstellt von Squolly:
    A1, A2, B1 und B2 sind gar keine Punkte

    Es sind Vektoren.

    y = (B2-B1) * t / (A2-A1) + B1

    Wie du auf die Gleichhung kommst weisst ich nicht, sieht ziemlich unsinnig aus.



  • Wieos unsinnig :)?

    Eigentlich:

    y - ya = m * (x - xa);

    Das hab ich dann nach y aufgelöst und weil ich ja dachte A1 == xa, A2 == xb, B1 == ya, B2 == yb

    kam dann

    y = (B2-B1) * (x-xa)/(A2-A1) + ya

    und weil x-xa == t:

    y = (B2-B1) * t / (A2-A1) + ya



  • Original erstellt von Squolly:
    Wieos unsinnig 🙂

    Weil man einen Skalar (t) nicht durch einen Vektor (A2-A1) teilen kann.



  • hm ok 🙂 Kann man nicht. Aber wie soll man an y kommen ?

    [ Dieser Beitrag wurde am 03.01.2003 um 20:34 Uhr von Squolly editiert. ]



  • Original erstellt von Squolly:
    **hm ok 🙂 Kann man nicht. Aber wie soll man an y kommen ?

    [ Dieser Beitrag wurde am 03.01.2003 um 20:34 Uhr von [qb]Squolly** editiert. ][/QB]

    Was ist denn y?

    Hab mir das Teil jetzt mal angeschaut, ist ja ziemlich buggy, schreibs besser nochmal neu.



  • Is echt ganz schön komisch, wenn man in der ersten Demo ganz schnell gegen das Hinternis "rennt", fliegt die "Figur" voll hoch. In der zweiten Demo klettert er die nächste Stufe erst hoch, wenn er von der davor runterfällt. Meine Vermutung: Du testest die Kollision in der Art nacheinander, dass er immer nur mit einem Objekt kollidieren kann. N ähnliches Problem hab ich auch grad. Ach nochwas: Wenn du nur Hindernisse aus Strecken parallel zu den Achsen hast, dann sollte es möglich sein, die Funktion um einiges zu vereinfachen. Wenn dem der Fall ist, wirst du hier sicher schnell Hilfe bekommen...

    mfG
    D1B



  • Hi @ all :).
    Auf der o. g. Seite kann man jetzt die neuste Version der exe runterladen. Ich bin dort mit der Kollisionsabfrage eigentlich schon zufrieden, aber wenns noch besser geht bitte sagen 🙂

    @TGGC : Schon gut 🙂 *g*. Mir schon klar das es hier kein y gibt.

    @D1BAKEL : Nicht jedes Hinderniss wird aus Strecken parallel zu den Achsen bestehen, aber zurzeit soll ja erstmal die Kollision mit einem Rechteck vollendet werden. Würd gerne wissen, wie du das mit dem vereinfachen meinst. Eigentlich sind die Strecken dann sozusagen Gitterlinien, weil sie ja paralel zu den Achsen liegen. Dass heißt dann ja, dass die Geraden entweder die vorm x = a haben (falls parallel zur y-Achse) oder y = b (falls parallel zur x-Achse) meinst du dass ich die Gleichungen auf diese Weise optimieren oder vereinfachen sollte? 🙂 ? Bin gespannt. Später sollen aber auch Schrägen, Virtelkreise usw eingebaut werden. Aber das erst später .) Erstmal nur Rechtecke.

    Mit welchen Geraden oder Strahlen sollte man die Kollision prüfen? Ich benutze zurzeit Geraden die durch die alte und neue Posiiton gehen. Solte man lieber die Geschwindigkeitsvektoren dazu nehmen? Ich denke nicht, da man mit alter + neuer Position genauer abfragt. Schaut euch mal die neuere Version an und kritisiert mich .)

    cu



  • Was ist das überhaupt für ein krasses Spiel? Entweder läuft das nur bei mir nicht richtig oder da ist überhaupt keine Logik drin in dem Ganzen. 😃 😮



  • Warum dürfen hier eigentlich Leute antworten die nicht registriert sind? Find ich nich so gut. 😃 😮



  • Hast du was gegen mich? *g*
    Ich bin doch ganz lieb. Hatte nur eine Frage. 🙂



  • Ich hab nichts gegen dich. Finds nur nich gut wenn Leute z.B unter verschiedenen Namen posten können was sie wollen (wenns dann beispielsweise Müll is), jetzt mal ganz davon abgesehn was du geschrieben hast.

    War also nichts gegen dich, sondern eher allgemein gemeint.


Anmelden zum Antworten