Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Swoerm

Alter Hase

  • »Swoerm« ist der Autor dieses Themas

Beiträge: 451

Wohnort: 127.0.0.1

  • Private Nachricht senden

1

04.01.2015, 00:06

[C++ & SFML] Kürzester Weg bei einer Rotation

Hallo,

ich bin zur Zeit dabei eine sehr simple "KI" für mein 2D-Spiel zu programmieren. Ich will nun zu nächst einmal das der Bot den Spieler anvisiert d.h. so rotiert das er ihn anvisiert. Dabei gibt es natürlich eine Rotation die der Bot momentan besitzt und eine eine Rotation die er einnehmen will (bei dieser visiert er den Spieler an). Die Rotation die er später besitzen soll berechne ich mit dieser Funktion hier:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void ENEMY::Aim (sf::Vector2f Pos)
{

    float b = Pos.x - x;
    float a = Pos.y - y;

    if (b>0)
        WantedRotation = (atan (a/b) * 180 / M_PI) + 90;
    else
        WantedRotation = (atan (a/b) * 180 / M_PI) + 270;

    if (WantedRotation > 360)
        WantedRotation -= 360;

    if (WantedRotation < 0)
        WantedRotation += 360;


}


Die "WantedRotation" wird auch korrekt berechnet. Nach der Ausführung dieser Funktion wird dann beurteilt in welche Richtung sich der Bot nun drehen muss um den Spieler anzuvisieren. Diese Beurteilung geschiehtr in diesem Code:


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (static_cast<int> (Rotation) != static_cast<int> (WantedRotation))
    {

        if (Rotation < WantedRotation)
            Rotation += GetRotationSpeed ();
        else
            Rotation -= GetRotationSpeed ();

    }

    if (Rotation > 360)
        Rotation -= 360;

    if (Rotation < 0)
        Rotation += 360;


Der Gedanke hinter diesem Code sollte eigentlich selbst erklärend sein. Der Code erfüllt seinen Zweck doch wenn nun z.B. der Zielwinkel aktuell sich bei 350° befindet und sich erhöht bis er schließlich bei 5° angelangt ist, dann erhöht die KI ihren Winkel nicht, um mit einer kleinen Rotation den Spieler anzuvisieren, sondern sie verringert ihren Winkel da ihr Zielwinkel ja nun kleiner ist als ihrer. Dies führt dazu, dass nun die KI fast eine ganze Umdrehung absolviert, obwohl sie eigentlich nur eine kleine Rotation benötigt hätte. Ich hoffe ich konnte mein Problem verständlich veranschaulichen. Nun lautet meine Frage: Wie kann ich der KI "erklären" das sie ihren Zielwinkel auch mit einer kleineren Rotation erreicht?

Viel Dank für eure Hilfe.

C-/C++-Quelltext

1
2
    /* Keep the compiler happy */
    return(0);

FSA

Community-Fossil

  • Private Nachricht senden

2

04.01.2015, 00:46

Vielleicht hilft das Stichwort atan2. Weiß aber gerade nicht, ob es hier anwendbar ist.

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Swoerm

Alter Hase

  • »Swoerm« ist der Autor dieses Themas

Beiträge: 451

Wohnort: 127.0.0.1

  • Private Nachricht senden

3

04.01.2015, 01:44

Ich glaube du verstehst meine Frage nicht ganz. Der "Zielwinkel" wird ja bereits korrekt berechnet es geht nur darum, ob ich mich für den kürzesten Weg dorthin mit oder gegen den Uhrzeigersinn drehen muss.

C-/C++-Quelltext

1
2
    /* Keep the compiler happy */
    return(0);

4

04.01.2015, 02:15

Man muss halt vorher die Zahlen ein wenig hin und her schupsen, dann klappt es auch mit der einfachen Abfrage:

C-/C++-Quelltext

1
2
3
4
Drehwinkel = MeinWinkel - GewünschterWinkel
if(Drehwinkel > 180)
   Drehwinkel -=360
Drehe(Drehwinkel > 0 ? -Drehgeschwindigkeit : Drehgeschwindigkeit)
Lieber dumm fragen, als dumm bleiben!

Swoerm

Alter Hase

  • »Swoerm« ist der Autor dieses Themas

Beiträge: 451

Wohnort: 127.0.0.1

  • Private Nachricht senden

5

04.01.2015, 14:16

Danke für die Antwort. So etwas in diese Richtung hatte ich bereits probiert jedoch trat wie auch bei deinem Code das Problem auf, dass es nur funktioniert wenn sich der Spieler im Uhrzeigersinn dreht, aber nicht wenn er sich gegen den Uhrzeigersinn bewegt. Oder ist meine Implementierung falsch?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (static_cast<int> (Rotation) != static_cast<int> (WantedRotation))
    {

        int Angle = Rotation - WantedRotation;

        if (Angle > 180)
            Angle -= 360;

        if (Angle > 0)
            Rotation -= GetRotationSpeed ();
        else
            Rotation += GetRotationSpeed ();


    }

    if (Rotation > 360)
        Rotation -= 360;

    if (Rotation < 0)
        Rotation += 360;

C-/C++-Quelltext

1
2
    /* Keep the compiler happy */
    return(0);

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

04.01.2015, 15:21

Stichworte: Skalarprodukt, Kreuzprodukt ;)

7

05.01.2015, 04:50

Zum Berechnen des kürzesten Rotationsweg könntest du auch festlegen das deine Aktuelle Rotation immer 0 ° ist.
Dafür must du nur den WantedRotation Winkel anpassen, wie du es ja eigentlich schon machst (ich tausch aber die Werte miteinander) ggf. noch 360° drauf rechnen wenn kleiner 0.

WantedRotation <= 180 gehts in die eine Richtung
WantedRotation > 180 gehts in die andere Richtung

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (static_cast<int> (Rotation) != static_cast<int> (WantedRotation))
    {

        int Angle = WantedRotation - Rotaion;

        if (Angle < 0)
            Angle += 360;
        else if(Angel > 180)
            Angel -= 360

        if (Angle <= 180)
            Rotation += GetRotationSpeed ();
        else
            Rotation -= GetRotationSpeed ();
    }

    if (Rotation > 360)
        Rotation -= 360;

    if (Rotation < 0)
        Rotation += 360;



Gruß Koschi
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »Koschi« (05.01.2015, 06:05)


Swoerm

Alter Hase

  • »Swoerm« ist der Autor dieses Themas

Beiträge: 451

Wohnort: 127.0.0.1

  • Private Nachricht senden

8

05.01.2015, 13:55



Stichworte: Skalarprodukt, Kreuzprodukt


Mit dem Skalarprodukt rechne ich doch den Kosinus des Winkels zwei Vektoren aus, oder? Ich verstehe nicht was es mir bringen soll, da ich den Winkel den die KI einnehmen soll ja bereits korrekt errechne.


@Koschi

Der Code funktioniert soweit, jedoch dreht sich die KI in die falsche Richtung wenn sich der Spieler gegen den Uhrzeigersinn und "über" 0° bewegt (die KI müsste ihre Rotation von z.B. 5° zu 355° ändern).

C-/C++-Quelltext

1
2
    /* Keep the compiler happy */
    return(0);

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

05.01.2015, 13:58

Es müssen negative Winkel erlaubt sein, sonst geht das Vorhaben nicht. Der Code da oben verhindert aber explizit negative Winkel.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

KeksX

Community-Fossil

Beiträge: 2 107

Beruf: Game Designer

  • Private Nachricht senden

10

05.01.2015, 14:15



Ich glaube du verstehst meine Frage nicht ganz. Der "Zielwinkel" wird ja bereits korrekt berechnet es geht nur darum, ob ich mich für den kürzesten Weg dorthin mit oder gegen den Uhrzeigersinn drehen muss.


Du formulierst dein Problem komisch. Du kennst den Zielwinkel eben nicht, da du ja den entsprechenden Deltawinkel suchst.
Und dafür hat dir FSA doch schon das richtige Stichwort gegeben.


atan2(sin(zielwinkel - ausgangswinkel), cos(zielwinkel - ausgangswinkel))
WIP Website: kevinheese.de

Werbeanzeige