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

1

07.05.2015, 00:23

2D Auto Pfad verfolgen

Hallo zusammen!

Ich experimentiere momentan ein wenig mit den von Mobile-Games bekannten "Pathdrawing-Games". Das einfache Verfolgen eines Pfades eines Objektes ohne Regeln, sprich nur mit einer bestimmten Geschwindigkeit, ist mir bereits gelungen und auch nicht all zu schwer.

Was ich nun vor habe, ist es ein Auto zuverlässig einen Pfad folgen zu lassen und dieses dabei physikalisch korrekt darzustellen. Sprich die Position der Vorder- und Hinterräder wird korrekt berechnet und das Auto verfolgt den Pfad basierend auf dem Zentrum der Vorderreifen. Das habe ich soweit auch schon hinbekommen:




Die Position und Rotation des Autos berechne ich dabei folgendermaßen (Code-Tags ruinieren leider die Formatierung bei mir):

Javascript-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Update positioning
var frontWheelX = this.pos.x + this.wheelDistance/2 * Math.cos(this.rotation);
var frontWheelY = this.pos.y + this.wheelDistance/2 * Math.sin(this.rotation);

var backWheelX = this.pos.x - this.wheelDistance/2 * Math.cos(this.rotation);
var backWheelY = this.pos.y - this.wheelDistance/2 * Math.sin(this.rotation);

backWheelX += this.speed * tick * Math.cos(this.rotation);
backWheelY += this.speed * tick * Math.sin(this.rotation);

frontWheelX += this.speed * tick * Math.cos((this.steerAngle + this.rotation));
frontWheelY += this.speed * tick * Math.sin((this.steerAngle + this.rotation));

this.pos.x = (backWheelX + frontWheelX) / 2;
this.pos.y = (backWheelY + frontWheelY) / 2;

this.rotation = Math.atan2(frontWheelY - backWheelY, frontWheelX - backWheelX);

Mein Problem ist nun, dass das ganze leider

a) nicht immer funktioniert, da oftmals die Winkel einfach viel zu groß sind und mit dieser "Auto-Physik" einzelne Pfadpunkte einfach übersprungen werden, da ich den SteerAngle entsprechend des Winkels des nächsten Pfades und der aktuellen Position des Autos (den rot eingezeichneten Punkt) vergebe. Das könnte man nun lösen, indem man beim Pfad-Zeichnen nur gewisse Winkel erlaubt. Allerdings geht das ganze bei einem Linedrawing-Game nur schlecht, da dadurch das ganze Zeichnen unterbrochen werden würde.

b) sehr künstlich wirkt. Ich habe überlegt, dass ich hier mit steering behaviours arbeiten könnte, allerdings bringen die mir ja nicht sehr viel, da ich weiterhin gerne auf dem Pfad bleiben wollen würde (ich gehe davon aus, dass das Spiel von der exakten und reproduzierbaren Verfolgung des Pfades lebt, also zu viel "Interpolierung" dem Spiel schadet).

Meine Frage ist nun, ob es hier irgendwelche Techniken gibt, wie ich das Auto den Pfad ohne Probleme realistisch verfolgen lassen könnte. Ich habe bereits Beispiele gefunden, die so eigentlich ganz gut zu funktionieren scheinen. Eines davon wäre folgendes: https://www.youtube.com/watch?v=_XKphuYviE0 . Nur wüsste ich nicht, wie das ganze umgesetzt ist und ob es mit längeren Autos auch noch so realistisch aussehen würde. Sprich ob die hinteren Reifen den vorderen Folgen. Das ganze scheint ja von der Geschwindigkeitsanpassung zu leben. Der Vorteil in der Simulation ist da wäre natürlich, dass es nur sehr wenige Pfadpunkt gibt, also zwischen einzelnen Pfadpunkten viel Platz zum interpolieren. Bei mir würde das so eher nicht klappen.

Edit: Ich kriege den Code hier nicht ordentlich rein kopiert, warum auch immer.
Edit2: Das img-tag scheint auch nicht zu funktionieren.
»Thurien« hat folgendes Bild angehängt:
  • auto_pfad.JPG

Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von »Thurien« (07.05.2015, 09:41)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

07.05.2015, 06:03

Für Code, benutze bitte den Quellcode-Modus, nicht den Editor-Modus. Das ist ein Tab oberhalb der Eingabebox.
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]

3

07.05.2015, 09:41

Danke, die Formatierung klappt nun ;)

Was ich mir noch als Möglichkeit überlegt habe wäre, dass ich die Physik der Autos ein wenig unechter gestalte und dem Bewegungspunkt (de rote Punkt auf dem die Pfadverfolgung basiert) immer den Pfad folgen lasse, mittels steering behaviours dann so, dass garantiert immer der nächste Punkt erreicht wird. Um es dann wieder realistischer zu machen würde ich dann den hinteren Teil des Autos (die Hinter-Räder) immer nur nachziehen lassen, also fast so wie es nun bereits ist nur dass ich ohne steeringAngle arbeite und die Position des Autos komplett vom Pfad abhängig mache.

Meine Frage wäre nun aber wie ich dieses "Hinterherziehen" programmieren könnte. Mir fällt dazu leider kein Suchbegriff ein und die Lösungen die mir bisher eingefallen sind haben alle nicht funktioniert. Im Grunde müsste ich ein träges Hinterteil haben welches vom Bewegungspunkt ja gezogen wird?!

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Thurien« (07.05.2015, 10:45)


Slotpunch

Frischling

Beiträge: 44

Wohnort: kiel

Beruf: Softwareentwickler

  • Private Nachricht senden

4

07.05.2015, 12:01

Google mal nach "steering behaviors arrival". Das könnte evtl. ein neuer Ansatz sein. Wenn der Winkel zu gross für Entfernung und Geschwindigkeit wird, passt sich die Geschwindigkeit an, ansonsten würde man über den zielpunkt hinausschießen. Sollte eigentlich gut realistische Ergebnisse liefern.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

07.05.2015, 12:43

Arrive alleine tut das allerdings nicht. Dabei würde der Agent je näher er dem Punkt kommt bremsen um auf dem Punkt zu halten. Erst danach würde er neu beschleunigen um jetzt zum nächsten Punkt zu gelangen. Das könnte man aber sicherlich abwandeln um damit ein brauchbares Ergebnis zu bekommen. Es gibt bei den Steering Behaviors meine ich aber auch Path Following. Dabei sollte dein Problem vermutlich gelöst werden auch wenn ich das grad genau nachgesehen habe.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

6

07.05.2015, 23:53

Ich habe das ganze nun mal folgendermaßen umgesetzt:

Javascript-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
      seek: function() {

            if (this.target != null) {

                this.steeringForce = _uv2.subtractVectors(this.target, this.drivingFocus);
                this.steeringForce = _uv2.normalize(this.steeringForce);
                this.steeringForce = _uv2.multiplyScalar(this.steeringForce, this.maxSpeed);
                this.steeringForce = _uv2.subtractVectors(this.steeringForce, this.velocity);

            }

        },

        arrive: function() {

            if (this.target != null) {

                this.steeringForce = _uv2.subtractVectors(this.target, this.drivingFocus);

                var distance = _uv2.length(this.steeringForce)

                if (distance > 0) {
                    var speed = distance * 1.5 * 0.5;
                    speed = Math.min(speed, this.maxSpeed);
                    this.steeringForce = _uv2.subtractVectors(_uv2.multiplyScalar(this.steeringForce, (speed/distance)), this.velocity);
                }

            }

        },

        calculateSteeringForce: function() {

            this.steeringForce = {x: 0, y: 0};
            this.arrive();

        },

        /**
         * Updates the car
         */
        update: function() {

            //Calculate steering forces
            this.calculateSteeringForce();

            //Update velocity
            this.velocity.x += this.steeringForce.x * tick;
            this.velocity.y += this.steeringForce.y * tick;

            //Check if current speed is not bigger than this.maxSpeed
            var currentSpeed = Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y);
            if (currentSpeed > this.maxSpeed) {
                this.velocity.x = this.velocity.x / currentSpeed * this.maxSpeed;
                this.velocity.y = this.velocity.y / currentSpeed * this.maxSpeed;
            }

            //Calculate new front-wheel position
            this.pos.x += this.velocity.x * tick;
            this.pos.y += this.velocity.y * tick;


        }


Was mir nun auffällt (dort nun bei arrive) ist, dass die Position des nächsten Pfades sicher und korrekt angenähert wird (sofern ich den Faktor in

Quellcode

1
var speed = distance * 1.5 * 0.5;
klein genug halte, bei 1*0.5 klappt alles wunderbar und perfekt. Problem ist aber, dass das ganz nun elendig langsam ist und nicht wirklich flüssig. Wenn ich jedoch nur seek nehme, ist das Auto schön in fahrt, überspringt aber gerade bei größeren Steigungen gerne mal Punkte und fährt zurück, was ich aber auf gar keinen Fall möchte, da der Pfad "reliable" sein sollte. Gibt es nun eine Möglichkeit, wie ich beides miteinander verbinde? Also quasi stets schnellstmöglichstes Pfadverfolgen, jedoch mit exaktem durchkreuzen der Pfadpunkte?

Vorgeschlagen wurde mir von Schorsch ja Pathfollowing, welches allerdings (die Versionen die ich gefunden habe) lediglich auf Seek mit variablem target basiert, also quasi was ich nun habe. Ich hätte aber gerne eine Mischung aus Seek und Arrive :?: In dem Beispiel hier https://www.youtube.com/watch?v=_XKphuYviE0 scheint es ja auch eine Mischung aus Pathfollowing und Arrive zu sein. Allerdings sieht es bei geraden Strecken eher nach Seek aus. Die Frage ist nun wie man den Faktor berechnet, mit welchem die Geschwindigkeit beeinflusst wird, wenn die Position beim nächsten Target auszuscheren zu droht.

Werbeanzeige