2016-07-06 20 views
2

Ich habe in letzter Zeit an einem einfachen Spiel mit C++ und SFML neueste Version gearbeitet, aber ich hatte ein Problem, dass die Kollisionserkennung nicht so gut ist, zum Beispiel der Spieler stirbt, auch wenn der Feind ihn noch nicht berührt hat , aber nur in seiner Nähe. Hier ist der Code des Spielers Klasse mit der Move-Funktion und Kollisionserkennung Code und die Bewegungen des Feindes Klasse:Die Kollision in SFML ist nicht so gut, wie man es verbessert?

`Klasse SpielerA: public CircleShape { public:

//Constructor: 
    PlayerA(float xposition, float yposition, float radius, float s) 
    { 
     setRadius(radius); 
     setFillColor(Color::Yellow); 
     setOutlineColor(Color(00,80,00)); 
     setOutlineThickness(-2); 
     setPointCount(3); 
     setSpeed(s); 
     setPosition(xposition,yposition); 
    } 

    //Movements of the player: 
    void up() 
    { 
     move(0,-10*speed); 
    } 
    void down() 
    { 
     move(0,10*speed); 
    } 
    void right() 
    { 
     move(10*speed,0); 
    } 
    void left() 
    { 
     move(-10*speed,0); 
    } 
    void checkA(ObsA *obs1=NULL,ObsA *obs2=NULL, ObsA *obs3=NULL, ObsA *obs4=NULL, ObsA *obs5=NULL) 
    { 
     if(obs2==NULL) 
     { 
      if(getGlobalBounds().intersects(obs1->getGlobalBounds())) 
      { 
       relevel(); 
      } 
     } 
    private: 
     float speed=0.00; 

    void obs() 
    { 
     if(speed > 0) 
     { 
       rotate(0.5*speed); 
     } 
     else 
     { 
       rotate(0.5*speed); 
     } 
    } 


private: 
    float speed = 0.00; 


    void obs() 
    { 
     if(speed > 0) 
     { 
       rotate(0.5*speed); 
     } 
     else 
     { 
       rotate(0.5*speed); 
     } 
    } 


private: 
    float speed = 0.00; 

Ist etwas nicht in Ordnung mit dem Code, wie das Problem zu beheben, danke!

+3

Mögliche Duplikat [SFML Bounding Box Collision Detection] (http://stackoverflow.com/questions/27280264/sfml-Bounding-Box-Kollisionserkennung) – Conduit

Antwort

6

Die intersects Funktion überprüfen Sie einfach, ob zwei Rechtecke sich schneiden. Wenn Sie in SFML eine pixelgenaue Kollisionserkennung wünschen, müssen Sie dies selbst schreiben.

Grundsätzlich mit intersects starten, wenn es wahr ist, dann erhalten die schneidenden Rechteckes und prüfen, ob alle Pixel, die darin von beiden ursprünglichen Rechtecken enthalten relevante Pixel overlaping.

+0

Danke! Das ist das Beste, was ich denke. – QApps

0

Verwenden Sie einen Kreis? Wenn ich mich richtig erinnere, wird der Kreis eine rechteckige Hitbox haben. Wenn dies der Fall ist, kann es zu Kollisionen zwischen den Ecken des unsichtbaren Rechtecks ​​kommen.

Wenn Sie einen Kreis verwenden, ändern Sie vielleicht die Klasse in ein quadratisches Rechteck und prüfen Sie, ob die Kollision korrekt funktioniert. Oder versuchen Sie die Kollision direkt auf einer x- oder y-Achse mit Ihren Kreisen zu testen; d.h. sie sich in einer geraden Linie aufeinander zu bewegen, wobei sie nur eine Achse ändern. (Die Kante des Kreises ist die gleiche wie die Kante des Rechtecks ​​an den linken, rechten, oberen und unteren Abschnitten).

Wenn Sie eine bessere Kollision für Kreise benötigen, ist möglicherweise bereits eine in SFML integriert. Aber ich denke nicht, dass es zu viel wäre, um Ihre eigene Logik zu schreiben, indem Sie den Radius Ihrer zwei Kreise, das Zentrum Ihrer zwei Objekte und den Winkel zwischen den Zentren verwenden. detection.Its eine grundlegende ein

+0

Ja, du hast Recht, ich werde es versuchen. Danke für Ihre Hilfe! – QApps

+0

"Der Winkel zwischen den Zentren". Ich empfehle, die Hypotenusenlänge des rechtwinkligen Dreiecks zu verwenden, das durch die Mittelpunkte gebildet wird, und dies gegen Radius1 + Radius2 zu überprüfen, anstatt zu versuchen, eine Projektion auf einem Winkel durchzuführen. War das was du beabsichtigst? (tut mir leid, wenn ich ärgerlich pedantisch bin) –

0

Sie diese Funktion nutzen zu können bessere Kollision durchzuführen, aber funktioniert gut

bool circleTest(const sf::Sprite &first, const sf::Sprite &second) 
{ 
    sf::Vector2f firstRect(first.getTextureRect().width, first.getTextureRect().height); 
    firstRect.x *= first.getScale().x; 
    firstRect.y *= first.getScale().y; 

    sf::Vector2f secondRect(second.getTextureRect().width, second.getTextureRect().height); 
    secondRect.x *= second.getScale().x; 
    secondRect.y *= second.getScale().y; 

    float r1 = (firstRect.x + firstRect.y)/4; 
    float r2 = (secondRect.x + secondRect.y)/4; 
    float xd = first.getPosition().x - second.getPosition().x; 
    float yd = first.getPosition().y - second.getPosition().y; 

    return std::sqrt(xd * xd + yd * yd) <= r1 + r2; 
} 
+0

Anstatt eine Seite zu quälen, solltest du die andere Seite quadrieren. Es läuft viel schneller und liefert die gleichen Ergebnisse. Ich stimme auch nicht zu, dass dies "besser" ist - nur anders. Es ist immer noch nicht pixelgenau (was wichtig oder nicht wichtig ist) und ist viel langsamer als ein Achsen-ausgerichteter Begrenzungsbox-Schnitttest. –