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

Aktuelle Zeit: Sa Jul 05, 2025 12:48

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



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mi Apr 01, 2009 00:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Mär 30, 2009 14:40
Beiträge: 30
hallo

ich bin gerade dabei einen horizontalen scroll-shooter zu programmieren.
das heisst der spieler steuert ein raumschiff am unteren bildschirmrand, und von oben kommen nun ständig feindliche schiffe die man abschießen muss.
dargestellt wird das ganze in 3d, aber berechnungen finden 2d statt (auf einer ebene, y-wert bleibt immer 0)

so weit so gut, im prinzip ist das kein problem.
nun sollen die feindlichen schiffe aber ja nicht einfach von oben nach unten fliegen, sondern es sollen (wie bei dieser art spiel üblich) ganze gegnerformationen irgendwelche kunstvollen "muster" fliegen. ich denke ihr wisst was ich meine: zum beispiel sollen 10 schiffe der reihe nach eine schleife fliegen, am höchsten punkt einen schuss abgeben, und dann im zickzack nach unten fliegen, oder irgendwie sowas. die muster können dabei relativ kompliziert sein (viele richtungswechsel/kurven etc..). jeder gegnertyp sollte seine eigene route haben.

wie kann ich solche "vorbestimmten routen" am einfachsten machen ? ich habe mir überlegt ob ich vielleicht die flugroute in form einer liste (array) von x/z werten ausdrücken kann, und die dann für den jeweils nächsten bewegungsschritt durchgehe:

beispiel : ((0,1)(0,1)(0,1)(0,0)(0,-1))
hier würde der feind erst 3 zeitschritte lang nach vorne fliegen, dann einen stillstehen, dann einen zurück

die arrays könnte man für die verschiedenen gegnertypen per hand erstellen.

ist diese methode halbwegs vernünftig oder wie wird sowas eigentlich gemacht ? es entstehen halt doch einige mehr oder weniger lange arrays dabei...

ich hoffe übrigens, dass ich das richtige unterforum gewählt habe, es hat ja nichts direkt mit openGL zu tun..


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 06:14 
Offline
DGL Member

Registriert: Mo Mär 16, 2009 10:22
Beiträge: 26
Prinzipiell hört es sich schon ganz sinnvoll an. Nur keine Arrays an sich, sondern Listen verwenden. Am besten Listen, deren Ende mit dem Anfang verknüpft sind, welches dann beim durchlaufen der Liste eine endlose Bewegung ergibt.

Dann könnte man z.B. für jeden Bewegungstyp jeweils nur 1 Liste verwalten, die jeweiligen Objekte haben selbst auch nur einen Zeiger auf das jeweils von ihnen ausgeführten Element der Liste, nach ausführen des "Flugkommandos" am Listenelement wird dann einfach das nächste Element der Liste genommen. So hält sich dann auch der Aufwand in Grenzen, wenn viele Objekte mit demselben Flugmuster zu sehen sein sollen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 09:18 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Für die Flugbahnen selbst, könnte das vielleicht helfen.
Man gibt also nur ein paar Punkte auf der Flugbahn vor. Der Rest wird interpoliert. Um die Gegner nun hintereinander herfliegen zu lassen, muss man nur den Zeitpunkt festlegen wann er auf die Flugbahn an T=0 gesetzt wird. Mit ein paar Faktoren bzw leichten modifikationen an der Formel würden so auch schöne Flugformationen machbar sein.

Die Arrays würde ich auf jeden Fall nicht hardcoden. Lieber in eine Textdatei speichern und im Programm die Möglichkeit zum neuladen einbauen. Jedesmal neukompilieren und zu dem Levelabschnitt springen an dem dieser eine bestimmte Gegner auftaucht wird auf Dauer keinen Spass machen.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 09:42 
Offline
DGL Member

Registriert: Mo Mär 16, 2009 10:22
Beiträge: 26
Naja interpolieren muss er auf jeden Fall, damit die Objekte nicht von einem Punkt der Flugbahn zum nächsten springen, aber ad hoc sehe ich ausser der linearen Interpolation zwischen den Punkten keine besonders sinnvolle Möglichkeit ohne viel Zusatzaufwand und Speicher. Vielleicht noch die Hermite-Interpolation. Cos-Interpolation macht schlechte gerade Strecken, die meisten anderen kann man sehr schlecht für beliebig lange Flugbahnen nehmen.
Es geht aber eher darum, wie die Flugpunkte selbst verwaltet werden, glaube ich.
Zitat:
Man gibt also nur ein paar Punkte auf der Flugbahn vor. Der Rest wird interpoliert. Um die Gegner nun hintereinander herfliegen zu lassen, muss man nur den Zeitpunkt festlegen wann er auf die Flugbahn an T=0 gesetzt wird. Mit ein paar Faktoren bzw leichten modifikationen an der Formel würden so auch schöne Flugformationen machbar sein.


Irgendwie fehlt mir da Inhalt. Wie interpoliert? Wie speichert man die Flugbahn jetzt? Welche Faktoren/Modifikationen an was für einer Formel?

Zitat:
Die Arrays würde ich auf jeden Fall nicht hardcoden. Lieber in eine Textdatei speichern und im Programm die Möglichkeit zum neuladen einbauen. Jedesmal neukompilieren und zu dem Levelabschnitt springen an dem dieser eine bestimmte Gegner auftaucht wird auf Dauer keinen Spass machen.


Siehe mein Beitrag. Eine Liste, deren Ende mit dem Anfang verknüpft ist. Objekte haben nur einen Zeiger auf ein Element dieser Flugbahn-Punkte-Liste, und iterieren sich durch. Mehrere Objekte die hintereinander eine Flugbahn ausführen bzw. in Formation fliegen, lassen sich leicht realisieren, indem man den Objekten unterschiedliche Anfangspositionen gibt, sie aber am Anfang auf dasselbe Listenelement zeigen lässt.
Laden/Speichern ist sicherlich praktisch, um die Daten aus dem Quellcode auszulagern und vernünftig mit den Flugbahnen zu experimentieren.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 11:15 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
Ich würde da so herangehen, das ich eine "Auftragsliste" erstelle die verschiedene Aufträge verwaltet, wie zum Beispiel:

1. eine bestimmte Zeitspanne an der aktuellen Position des Gegnes warten
2. zu einer bestimmten Stelle vom Gegner aus gesehen bewegen
3. an aktueller Position einen Schuß in eine bestimmte Richtung abgeben

Damit sollte man das wichtigste an Aufgaben für so einen Gegner abgedeckt haben. Die AuftragsListe ist jetzt so wie bereits vorher erklärt einfach eine Liste die diese Ereignisse in gewünschter Reihenfolge mit gewünschten Werten speichert und die Gegner bekommen einfach eine solche Liste als Pointer in die Hand gedrückt und machen sich nach dem sie erstellt wurden an die Arbeit und klappern die Punkt nacheinander ab, sind sie am Ende angekommen, dann einfach von vorne (denk daran, dass Gegner die nach unten den Bildschirm verlassen zerstört werden sollten um den Arbeitsspeicher nicht zu überlasten). der nächste Punkt in der List wird natürlich erst verarbeitet, wenn der vorherige Punkt erfolgreich abgearbeitet wurde, oder nicht abgearbeitet werden konnte (einen schuß abgeben, obwohl der Gegner nicht schießen kann).

Ein zweites Objekt was du unbedingt brauchst ist ein Emitter für Gegner, also ein Objekt das eine gewisse Anzahl von Gegnern in bestimmten Zeitabständen an einer Stelle deiner Karte produziert, sobald sich der Spieler entsprechend genähert hat. Jeder Gegner der von so einem Emitter erstellt wird bekommt den Pointer einer vorher generierten Auftragsliste zugewiesen und dieser macht sich dann fleißig auf die Socken das Ding abzuarbeiten.

für die Auftragsliste solltest du eine eigene Klasse schreiben, damit du Spezialfälle der Auftragsbearbeitung abfangen kannst. Um die Aufträge zur Laufzeit zu speichern, lege einfach eine "keinAutrag"-Klasse an und leite die 3 oben beschriebenen Typen davon ab. Auf diese Weiße kannst du sie dann einfach in eine Liste speichern, ohne dir gedanken über die kompatibiliät machen zu müssen.

Jeder gegner muss dann natürlich nen Zeiger auf eine Auftragsliste und den aktuellen Auftrag speichern können und in der Lage sein sich frei zu bewegen (rotation,translation, evtl. sogar mit Beschleunigung) um die Zielpunkte der Auftragsliste erreichen zu können.

Im Programm selbst macht es Sinn, sich eine Liste von Auftragslisten zu halten inklusive einer Funktion solche Auftragslisten aus Dateien zu laden. Dann hast du die Möglichkeit einen Editor zu schreiben in dem du die Auftragslisten bastelst und abspeicherst und im Spiel nur noch laden brauchst.

das wäre so mein Ansatz, ist natürlich schon etwas aufwendiger, aber ich denke es lohnt sich und ist im nachhinein sehr komfortabel. Außerdem sammelt man dabei ne Menge Erfahrung über Fileloading/writing und OOP

_________________
Klar Soweit?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 11:50 
Offline
DGL Member

Registriert: Mo Mär 16, 2009 10:22
Beiträge: 26
Hehe naja dass das ganze OO und entsprechend abgekapselt sein soll, wollte ich mal dem Threadersteller überlassen.

Die Idee mit der Auftragsliste ist gut, und beinhaltet ja auch die Idee des Threaderstellers, nur dass dort ausser Flugpunkten auch noch andere Aufträge gespeichert werden können, also nicht nur die Flugbahn, sondern im Prinzip die komplette AI der Gegner beinhalten. Da kommts jetzt drauf an, was das Spiel können muss, und was der Threadersteller wissen wollte *hint*. Letzendlich kann aber auch eine trennung von AI und Flugbahn sinnvoller sein- z.B. würde ich bei so einem Spiel
-3. an aktueller Position einen Schuß in eine bestimmte Richtung abgeben-
nicht unbedingt in eine Auftragsliste geben, sondern einem Objekt eine/mehrere Waffen zuordnen die regelmäßig/ oder bei bestimmter Position zum Spieler abfeuern. Ich denke mal das ist aber vom Design des Spiels abhängig.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 11:52 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Mär 30, 2009 14:40
Beiträge: 30
hmm vielen dank, da waren doch schon mal ein paar nützliche hinweise dabei..

ich werd mich da ma ein bisschen einarbeiten (interpolation hab ich noch nie gemacht), dann sollte das schon klappen.


Zitat:
(denk daran, dass Gegner die nach unten den Bildschirm verlassen zerstört werden sollten um den Arbeitsspeicher nicht zu überlasten)

das sollte kein problem darstellen, ich habe bereits die schüsse des spielers implementiert, und da ist es ja dasselbe. ich könnte ja einfach ans ende der auftragsliste den auftrag "sich selbst löschen" setzen.

Zitat:
Ein zweites Objekt was du unbedingt brauchst ist ein Emitter für Gegner, also ein Objekt das eine gewisse Anzahl von Gegnern in bestimmten Zeitabständen an einer Stelle deiner Karte produziert

da hab ich mir auch bereits gedanken darüber gemacht. ich würde das so machen, dass jeder gegner der neu erscheint die zeit angibt, die vergeht bis sein nachfolger erscheint.. dann könnte ich einfach per timer alle gegner erscheinen lassen bis das level zu ende ist


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 22:29 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Zitat:
Irgendwie fehlt mir da Inhalt. Wie interpoliert? Wie speichert man die Flugbahn jetzt? Welche Faktoren/Modifikationen an was für einer Formel?


Nächstes mal werde ich dann eine vollständige Lösung posten.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 23:18 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Mär 30, 2009 14:40
Beiträge: 30
Zitat:
Nächstes mal werde ich dann eine vollständige Lösung posten.


ich nehme jetzt mal ganz stark an, dass das ironie war, denn eine vollständige lösung will/brauche ich nicht.

jedenfalls danke für die antworten, jetzt dürfte das ganze kein problem mehr für mich darstellen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 01, 2009 23:52 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
übrigens das mit der Bewegung und dem interpolieren kann man sich so vorstellen:

du hast zwei punkte: A = der aktuelle punkt deines Objektes und B = der Zielpunkt (beides vektoren im R2 in deinem Fall)

dein Objekt bewegt sich mit einer Geschwindigkeit v bei eine rendertime r. Die Bewegungsrichtung ist B-A. Desweiteren sollte man eine Toleranz e(Epsilon) haben.
v ist dabei die Anzahl an OpenGl Einheiten pro Sekunde und r die zeit die du zum Zeichnen der Szene brauchst (kehrwert der fps). Als erstes musst du also herrausfinden, wie viel dein Objekt sich pro render bewegt, dazu einfach v*r rechnen und schon haste die Distanz die das Objekt zurück legen muss. anschließend musst du die Richtung normieren, also die beiden werte x,y der Richtung durch die Länge der Richtung teilen und dann x,y mit der eben errechneten distanz multiplizieren. so, jetzt wissen wir um welche Strecke ausgedrückt als Vektor sich das Objekt bewegt. Diesen Vektor einfach auf die aktuelle Position des Objektes drauf rechnen. anschließend prüfst du den Abstand zwischen Ziel und neuer Objektposition, ist sie kleiner als e+Objektradius, ist das Ziel erreicht. e musst du natürlich wählen wie du lustig bist, aber nicht zu klein, da das Objekt sonst einfach dran vorbei fliegt wenn es zu schnell ist. Man kann auch e = v*r*2 nehmen, dann klappt es eigentlich immer.

Edit: das ist weniger ein Interpolieren als ein stümperhaft zusammen gekitteter physikalischer Ansatz von einfacher Bewegung

_________________
Klar Soweit?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 02, 2009 08:43 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Zitat:
ich nehme jetzt mal ganz stark an, dass das ironie war, denn eine vollständige lösung will/brauche ich nicht.

jedenfalls danke für die antworten, jetzt dürfte das ganze kein problem mehr für mich darstellen.


Sicher war das Ironie. Und das war auch nicht auf deine Beiträge bezogen. :)

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Apr 02, 2009 09:34 
Offline
DGL Member

Registriert: Mo Mär 16, 2009 10:22
Beiträge: 26
damadmax hat geschrieben:
Zitat:
Irgendwie fehlt mir da Inhalt. Wie interpoliert? Wie speichert man die Flugbahn jetzt? Welche Faktoren/Modifikationen an was für einer Formel?


Nächstes mal werde ich dann eine vollständige Lösung posten.


Naja, ich glaube du redest an mir vorbei. Ich wollte damit nur sagen, dass das, was du schriebst, nämlich
Zitat:
Man gibt also nur ein paar Punkte auf der Flugbahn vor. Der Rest wird interpoliert. Um die Gegner nun hintereinander herfliegen zu lassen, muss man nur den Zeitpunkt festlegen wann er auf die Flugbahn an T=0 gesetzt wird. Mit ein paar Faktoren bzw leichten modifikationen an der Formel würden so auch schöne Flugformationen machbar sein.

Insbesondere der letze Satz ist komplett inhaltslos. Ich kann eigentlich auf jede Frage im Forum
"Mit ein paar Faktoren bzw leichten modifikationen an der Formel würden das machbar sein."
schreiben, ohne dabei irgendwo zu erwähnen, was für Faktoren, welche Formel und was für Modifikationen ich überhaupt meine.

Zum Thema:

@Sellman: Im Prinzip ist das Interpolation von hinten aufgeknüpft. Man kann das auch etwas einfacher und eher Richtung Intepolation so berechnen:
Wenn in der Liste steht, bewege dich um den Vector (x,y), hat man sich auch irgendwann überlegt, in welchem Zeitraum t diese Bewegung erfolgen soll (z.b. hat man festgelegt, dass jede Sekunde das nächste Element in der Flugbahn aufgerufen wird). Dann würde man einfach bei jedem Zeitschritt dt (die vergangene Zeit seit dem letzen Frame) die Position um (x,y)*dt/t ändern. Das wäre halt sowas wie" lineare Interpolation", weil man sich linear (es wird einfach nur mit einer Potenz von 1 multipliziert) direkt von einem Punkt zum nächsten bewegt. Interessant ist bei der Lösung, dass die Geschwindigkeit mit in der Liste mit der Flugbahn gespeichert ist; damit kann man die Objekte dann einfach mal langsamer fliegen lassen, auch mal stehen lassen, abwechelnd schnell - langsam, was interessantere Bewegungsmuster ergeben kann, und Gegnertypen, die damit kniffliger wären, als welche, die nur fliegen und an der Stelle bleiben können.
Wenn keine Zeit festgelegt ist, sondern von einem Ort zum anderen geflogen wird, wäre der Lineare (und kürzeste Weg) die Gerade zum Ziel. Das kann man wie Sellmann es erklärt berechnen, was aber auf jeden Fall aufwendiger ist (und wesentlich mehr berechnen muss), aber im Endeffekt dasselbe bringt (bis auf die Anpassung der Geschwindigkeit -> dazu müsste man diese auch noch in der Liste speichern und berücksichtigen, was das ganze komplizierter macht).

Das Problem an beiden Lösungen ist jedoch der abrupte Wechsel der Bewegungsrichtungen (und abruptes Stoppen/Losfliegen). Eine spontane Lösung wäre dabei z.B. einfach immer 2 Flugkommandos gleichzeitig abzuarbeiten, diese aber unterschiedlich zu gewichten, mit fließendem Übergang.

Ich versuche das mal zu erklären:
Man hat eine Liste mit Flugkommandos, die irgendwie so aussieht:
(x0,y0) -> (x1,y1) -> (x2,y2) -> (x3,y3) -> ....-> (x0,y0)->......

Jedes dieser Kommandos soll in insgesamt 2s abgearbeitet sein.

Ein Objekt wird irgendwie erstellt und bekommt nen Zeiger auf den Anfang der Liste.
Intern hat das Objekt 2 zusätzliche Gleitkommazahlen A und B, die anfangs beide 0 sind. Diese werden um eine Sekunde versetzt zwische 0 und 1 hin und herpendeln, und zwar linear mit einer Periode von 2s (das ergibt, würde man die Zahlen auf einer Achse gegen die Zeit auftragen, dass die Fläche unterhalb des Graphens innerhalb zwei Sekunde 1 beträgt -> das ergibt dann, dass die in der Liste angegebene Positionsveränderung auch erreicht wird). Diese Zahlen sind die Faktoren, die die Bewegung gemäß eines Flugkommandos gewichten.

Das Flugkommando (x0,y0) bewirkt damit dann( ähnlich wie oben beschrieben) eine Veränderung der Position um (x0,y0)*dt/t*A (wobei t=2 ist), die ersten 2 Sekunden lang. Gleichzeitig, ab der 1 Sekunde, wird das Flugkommando (x1,y1) benutzt und bewirkt 2 Sekunden lang eine Veränderung der Position um (x1,y1)*dt/t*B.
Immer, wenn eine der beiden Faktoren A oder B dann 0 ist, bekommt dieser das nächste Flugkommando zugewiesen, also alternierend.

Insgesamt bewirkt es, dass sich die Objekte nicht mehr gleichförmig und abrupt bewegen, sondern sanft schneller bzw. langsamer werden und ihre Richtung ändern.
Sind z.B. zwei aufeinanderfolgende FLugkommandos (1,0) und (0,1), dann fliegt es eine sanfte Kurve. Da die Summe von A und B aber immer 1 ist, fliegt das Objekt z.b. trotzdem gleichförmig geradeaus, wenn aufeinanderfolgende Flugkommandos gleich sind,also z.b. (1,0)->(1,0)->(1,0)...
Ich bastel mal eben eine kleine Graphik dazu...
Bild


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 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:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 15 Queries | GZIP : On ]