Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 19:54

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mi Nov 23, 2016 16:06 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Hallo,
in vielen Computerspielen steuert man einen Charakter, der eine große Zahl an Animationen ausführen kann, um sich angepasst an seine Umgebung zu bewegen. Diese Animationen werden oft mit ein und der selben Taste vom Spieler (oder sogar komplett automatisch) ausgelöst. Der Computer erkennt irgendwie, welche Animation gerade passt.

Beispiel: Der Charakter springt in die Luft und landet irgendwo. Ist dies an einem Mauervorsprung, so hält er sich mit beiden Händen fest und lässt die Beine nach unten baumeln. Landet er hingegen an einer Leiter, hält er sich mit jeder Hand an einer Stufe fest und auch die Beine stellt er auf zwei verschiedene Stufen der Leiter. Springt der Charakter hingegen an ein senkrecht an einer Wand angebrachtes Rohr (z.B. ein Regenablaufrohr), so umklammert er dieses mit Händen und Füßen. Endet der Sprung an der Oberkante eines Zauns, so wird eine Animation ausgeführt, bei der sich der Charakter elegant über den Zaun schwingt.

Ich denke es ist klar, dass man hier noch zig weitere Fälle aufzählen könnte, was der Charakter tun könnte, wenn er nach dem Sprung bei x landet. Doch wie erkennt der Computer, welche Animation zur aktuellen Situation passt? Ich bin mir ziemlich sicher, dass diese Berechnung i.d.R. komplett dynamisch abläuft. Sie kommt ja auch in OpenWorld-Titeln vor.

Mein naiver Ansatz sähe so aus, dass ich für jede mögliche Animation definieren würde, wo eine Kollision stattfinden muss (ggf. noch mit welchem Material) und wo es keine Kollision geben darf. Damit sich ein menschlicher Charakter an einem Mauervorsprung festhalten kann, muss es also unter den Händen einen Bereich geben, an dem die Kollisionsabfrage an die Welt positiv ist und einen weiteren Bereich, wo nur Luft ist, damit dort Platz für den restlichen Körper des Menschen ist. Diese beiden Bereiche könnte man also großzügig mit zwei Quadern beschreiben.

Nun sind zwei Box-Kollisionsabfragen an die Spielewelt kein Problem. Jedoch geht es ja nicht darum festzustellen, ob der Charakter bereits am Mauervorsprung hängt, sondern ob er dies in den nächsten x Millisekunden oder Frames tun könnte. Also ob der Spieler gerade auf einen Mauervorsprung zuspringt. In meinem Ansatz würde man nun also die Boxen in verschiedenen Abständen - sagen wir mal mit einer Schrittweite von fünf Zentimetern - vor dem Spieler platzieren, und schauen ob dort die eine Box gar nicht und die andere Box mit einem festen Material kollidiert. Wenn man dies für einen Bereich von 50 cm prüft, sind dies (50cm/5cm) * 2 Boxen = 20 Kollisionsabfragen.

Doch halt! Was ist, wenn der Spieler nicht gerade, sondern etwas schräg an die Wand springt? In diesem Fall würde die Kollisionserkennung nicht mehr korrekt funktionieren. Der Computer müsste noch herausfinden, um welchen Winkel der Charakter gedreht werden muss, damit er sich tatsächlich mit beiden Händen am Vorsprung festhalten kann und nicht eine Hand in der Luft schwebt. Natürlich kann man die Boxen für den Kollisionstest auch in 1°-Schritten von -30° bis +30° oder so rotieren. Dadurch würde sich die Anzahl der Schritte jedoch nochmal versechzigfachen! Und es gibt ja wie gesagt noch mehr Fälle als den Mauervorsprung. Mit diesem naiven Ansatz kommt man schnell auf tausende Kollisionsabfragen pro Frame. Das ist offensichtlich extrem ineffizient und ich glaube kaum, dass in Videospielen so vorgegangen wird. :?

Weiß jemand, wie stattdessen vorgegangen wird? Habe schon diverse Suchmaschinen befragt, aber anscheinend fehlen mir auch die richtigen Stichworte. Vielleicht gibt es ja einen Fachbegriff für dieses Richtige-Animation-anhand-intelligenter-Kollisionserkennung-auswählen. Die Königsklasse wäre es natürlich, die Animation selbst noch dynamisch anzupassen, so dass die Spielfigur je nach Bedarf den Arm mehr oder weniger lang ausstreckt oder so. Aber das halte ich für seeehr kompliziert. Ich würde mich bereits damit zufrieden geben, wenn man die Figur ein paar Zentimeter bzw. Grad transliert und rotiert, so dass die vorgegebene Animation passt.

Es wäre toll, wenn mir jemand mal einen Denkanstoß geben könnte. Vielen Dank schonmal!

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Nov 24, 2016 08:53 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Puh, frickelig. Ich hab über sowas nur am Rande (pun intended) mal nachgedacht.

Bei nicht-open-world ist ein Ansatz offenbar, das im Editor zu taggen. Dann kann man mit ner Sphäre den Punkt, an dem der Charakter in N Frames sein wird schauen ob’s da was zum Festhalten gibt. Analog auch für andere Dinge, z.B. Treppen oder so.

Für OpenWorld stell ich mir vor, dass man sowas bei Änderungen bzw. Generieren der Geometrie detektieren kann, also die Tags maschinell erzeugt. Das müsste auf vereinfachter Geometrie arbeiten, damit die Erkennungsalgorithmen irgendwie feasible werden.

Ob das so wirklich gemacht wird – keine Ahnung. Zumindest bei nicht-OpenWorld titeln würde ich mal in die Richtung GTA schauen, zumindest von den älteren Titeln weiß ich, dass die relativ umfangreich gemoddet wurden. Da findet man sicher Infos wie das implementiert wurde.

viele Grüße,
Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Nov 24, 2016 16:24 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Jun 05, 2013 15:12
Beiträge: 165
Wohnort: Glinde
Programmiersprache: Delphi 7
Hallo,

tatsächlich habe ich vor langer Zeit mal so etwas gelesen. :D Kann aber die Seite nicht mehr finden. :(

Wenn ich mich Recht erinnere gibt es 2 wichtige/banale Dinge zu beachten.
1. Von der realen Welt abgeschaut:"Die Hände befinden sich beim Sprung bereits in Flugrichtung (also Vorne oder nach oben)".
Niemand der in der realen Welt, an einen Mauer springt will, hat die Hände auf dem Rücken.
Das Ergebnis wäre nämlich schmerzhaft. Dieses Verhalten sieht man vor allem bei älteren Spielen, wie den ersten Lara Croft Teilen. Die Figur steht still -> der Spieler drückt "space" -> da keine vorwärtsbewegung vorhanden und nur "space" gedrückt wurde. Reißt Lara die Hände übertrieben nach OBEN auch wenn keine Stange oder XYZ sich in der nähe befindet.
Anmerkung: haben viele Spieler gar nicht gemerkt, da Lara's andere Körperteile oft interesanter waren. :shock:

2. Du brauchst genau 2 Punkt im korrdinaten System. Die von den Händen deiner Figur und die vom Absatz(Mauer, Stange etc.).
Sobald der Spieler springt bewegen ich die Hände zum DICHTESTEN vorhanden Punkt. In 2D heißt das, wenn Kordinate X1(Hände) unterhalb von X2(absatz) sind. Bewegen sich die Hände(X1) nach oben. Keine Hitbox und keine massive vorberechnung. Nur wenn kleiner als dann größer und wenn größer als dann kleiner machen. Bis sich die Punkte treffen. Dann klebt die Figur.

Bild

Soll heisen nur:
+ NUR wenn gesprungen wird, müssen die berechnungen laufen und die Hände in richtung mögliche Ziel gestreckt werden.
+ Du musst nur wissen, welches der dichteste kontaktpunkt ist.
+ Eventuell kann man auch die Kontaktflächen berecnung von Finalspace benutzen, die aus seiner Videoreihe Leverman Devlog.

Übrigends auch ein Handlauf kann man so animieren.
Spieler befindet sich auf einer Treppe.
1: Spieler ist in griff reichweite von Handlauf -> greift sofort an die dichteste Möglichkeit.(von der Hand aus gesehen)
2: Spieler läuft Trepp runter -> die Hand bewegt sich hinter den Körper. Kann nicht mehr zu packen. (loslassen)
3: Hand vor den Körper bewegen lassen.
Es folgt schritt ^1.

Liebe Grüße :wink:

_________________
幸福は笑う人に来て ~~ koufuku wa warau hito ni kite
Das Glück kommt zu denen die lachen


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Nov 24, 2016 18:47 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Vielen Dank erstmal euch beiden für die Antworten!

@Polarwolf: Deine Erklärung ist sehr schön erläutert und nachvollziehbar. Du gehst aber davon aus, dass ich bereits weiß, wo es Mauern/Seile/whatever zum Festhalten gibt. Also dass entweder der Level-Designer die Stellen als solche markiert hat oder eine Vorberechnung dies ergeben hat (wie von Horazont angeregt).

Meine Frage zielte darauf ab, wie man es ohne dieses Vorwissen realisieren kann. Ich möchte durch Kollisionsabfragen erkennen: "Vor dem Spieler befindet sich eine Leiter. Die entsprechende Greifanimation (feste Folge von KeyFrames) passt, wenn der Spieler geringfügig um x transliert und um y rotiert wird."

Auch wenn es ganz ohne Vorberechnungen vielleicht nicht geht, sind ja selbst die Vorberechnungen an sich alles andere als trivial. Schon bei einer Welt von 100*100*10 m³ und eine Abtastdichte von 10 cm müsste man ja Milliarden von Kollisionsabfragen machen, selbst wenn man sich auf die vier Haupthimmelsrichtungen beschränkt.

Nun besteht die Welt in meinem Fall aus Objekten, von denen oft mehrere Instanzen existieren. Ein etwas intelligenterer Ansatz bestünde darin, an diesen Objekten Kollisionstests für alle Animationen zu machen und die Ergebnisse entsprechend der Transformationsmatrizen der einzelnen Instanzen in die Welt zu übertragen. Die Objekte sind ja i.d.R. deutlich kleiner als die Welt und daher vom Rechenaufwand handhabbarer. Zudem könnte man ganz kleine Objekte mit Abmessungen von weniger als einem Meter komplett von der Berechnung ausnehmen.

Dennoch erscheint es mir notwendig, irgendwie analytisch an das Problem heranzugehen, statt brute-force den Raum alle x Zentimeter und Grad abzutasten. Das heißt, man könnte beispielsweise Oberflächennormalen oder die Richtung von Dreieckskanten als Quelle für mögliche Ausrichtungen heranziehen. Das ist aber nur eine sehr vage Idee.

Ich werde mich mal auf die Suche nach entsprechenden GTA-Mods machen. Allerdings befürchte ich, dass dort wahrscheinlich einfach auf Funktionalität der Gameengine zurückgegriffen wird, welche natürlich closed-source ist.

Weitere Ideen sind willkommen.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Nov 24, 2016 19:34 
Offline
DGL Member

Registriert: Fr Mai 11, 2012 13:25
Beiträge: 229
Programmiersprache: c++, c, JavaScript
Dazu fällt mir Tony Hawk Pro Skater ein.
Da kann man ganz gut sehen, wie der Skater einfach etwas verschoben wird, wenn er in die Nähe eines Dinges kommt, wo irgendeine Aktion passt.
Wenn es zu viele Abfragen werden: Mach doch erstmal ein paar simple Distancetests.
Evtl. auch komponentenweise, um Multiplikationen zu vermeiden, bin allerdings nicht sicher ob das was bringt.

Du könntest auch für die verschiedenen Winkel Schwellenwerte vorberechnen, innerhalb der Du dann die Positionsabfrage machen musst.
Z.B. dein Spieler darf um max 10 Grad gedreht werden, um eine Aktion auszulösen und dadurch sind die Hände maximal 30 cm vor, zurück, runter oder hoch verschoben.

Wenn Du maximale Geschwindigkeiten von Objekten annehmen kannst, brauchst Du für die meisten Objekte den Verlauf auch gar nicht zu tracen und im vorhinein die meisten ausschließen.

_________________
"Pixel, ich bin dein Vater."
-Darf Shader


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Nov 24, 2016 22:50 
Offline
DGL Member

Registriert: Fr Mai 11, 2012 13:25
Beiträge: 229
Programmiersprache: c++, c, JavaScript
glAwesome hat geschrieben:
Meine Frage zielte darauf ab, wie man es ohne dieses Vorwissen realisieren kann. Ich möchte durch Kollisionsabfragen erkennen: "Vor dem Spieler befindet sich eine Leiter. Die entsprechende Greifanimation (feste Folge von KeyFrames) passt, wenn der Spieler geringfügig um x transliert und um y rotiert wird."

Auch wenn es ganz ohne Vorberechnungen vielleicht nicht geht, sind ja selbst die Vorberechnungen an sich alles andere als trivial. Schon bei einer Welt von 100*100*10 m³ und eine Abtastdichte von 10 cm müsste man ja Milliarden von Kollisionsabfragen machen, selbst wenn man sich auf die vier Haupthimmelsrichtungen beschränkt.


Wenn Du jetzt annimmst, dass Du den Character nur um y rotieren kannst, wie gewöhnlich, und dass der Griff des Characters und somit er selbst ja eh parallel zur Leiter sein muss.
Dann könntest Du in Bezug auf den Winkel sagen, dass die Aktion nur möglich ist wenn die Winkeldifferenz kleiner irgendwas ist und den Chracter dann um die Differenz drehen, dann schauen, ob die nötige Translation kleiner irgendwas ist, und wenn ja, den Character translieren und die Action starten, und wenn nicht, ihn wieder zurückdrehen und die Action abbrechen.
Weil Du kannst ja im vorhinein rausfinden, wie weit der Character sich vom Beginn der Animation bis zum Erreichen des Griffs bewegt.
Also bräuchtest Du hier gar nix abtasten.
Solange die Leiter nicht beschleunigt wird während die Animation abläuft jedenfalls.
Oder überseh ich da was?

_________________
"Pixel, ich bin dein Vater."
-Darf Shader


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Nov 25, 2016 16:16 
Offline
DGL Member

Registriert: Fr Mai 11, 2012 13:25
Beiträge: 229
Programmiersprache: c++, c, JavaScript
Ups, sorry, glaube ich habe das Hauptproblem hier vernachlässigt.
Du hast eine Geometrie und willst erstmal herausfinden, ob diese als Leiter oder anderer Angriffspunkt verwendet werden kann, bzw. genauer gesagt, wo die Geometrie als Angriffspunkt verwendet werden kann.

Bsp: Du hast nen Teapot vor Dir und willst rausfinden, ob sich der Spieler dran festhalten kann, wenn er hochspringt. Richtig?
Also dann würde ich die Geometrie im vorhinein analysieren, und für die möglichen Aktionen ein Array anlegen, mit Positionen wo die Actionen möglich sind.
Ansonsten könntest Du auch eine Ultra-low-poly-version von den Objekten anfertigen oder berechnen lassen, und dann irgendwas anhand der Normalen machen.
Aber das könnte "glitchig" werden ;)

_________________
"Pixel, ich bin dein Vater."
-Darf Shader


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Nov 25, 2016 20:06 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Vinz hat geschrieben:
Du hast eine Geometrie und willst erstmal herausfinden, ob diese als Leiter oder anderer Angriffspunkt verwendet werden kann, bzw. genauer gesagt, wo die Geometrie als Angriffspunkt verwendet werden kann.
Ja.
Vinz hat geschrieben:
Bsp: Du hast nen Teapot vor Dir und willst rausfinden, ob sich der Spieler dran festhalten kann, wenn er hochspringt. Richtig?
Ganz genau.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Nov 26, 2016 17:31 
Offline
DGL Member

Registriert: Fr Mai 11, 2012 13:25
Beiträge: 229
Programmiersprache: c++, c, JavaScript
Was mir dazu einfällt:
Falls es ein ausgedehnter Angriffspunkt ist, wie z.B. eine Mauer, die man entlang einer Linie anspringen könnte.
Man kann mit wenigen Rechenschritten die Entfernung von einem Punkt zu einer Linie oder auch von einer Linie zu einer anderen Line rausfinden. Mit Dreiecken und Quads sollte es auch gehen.

Du könntest also auch Bereiche in Form von Linien oder Dreiecken, evtl. auch Quads, bestimmen oder vorberechnen, für die spezielle Animationen funktionieren und jeweils noch den benötigten Winkelbereich hinzufügen.
Dann könntest Du diese Bereiche analytisch abfragen ohne abtasten zu müssen.

Solche Funktionen hab ich mir mal rausgesucht für ein paar Raytracing-Experimente.
Eine glm-artige Lib hierfür wäre praktisch, so dass man Sie möglichst auch in glsl leicht verwenden kann.
Kennt da jemand was? Wäre hierbei sicherlich auch hilfreich.

_________________
"Pixel, ich bin dein Vater."
-Darf Shader


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Nov 26, 2016 17:38 
Offline
DGL Member

Registriert: Fr Mai 11, 2012 13:25
Beiträge: 229
Programmiersprache: c++, c, JavaScript
Hab grad gesehen, es gibt da sogar ein paar glm experimentelle extensions in die Richtung:
https://glm.g-truc.net/0.9.5/api/a00203.html

_________________
"Pixel, ich bin dein Vater."
-Darf Shader


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 23 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.079s | 17 Queries | GZIP : On ]