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

StephanD87

Frischling

  • »StephanD87« ist der Autor dieses Themas

Beiträge: 2

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

1

02.12.2011, 21:45

Programmdesign bei Spielen (im speziellen)

Hallo liebe Spielerprogrammierer-Gemeinde,

Zuerst eine kurze Einleitung [kann auch übersprungen werden]

Ich bin hier im Forum neu, habe es heute eher zufällig im Web entdeckt. Ich programmiere gerne Spiele als Hobby. Habe bisher mit BlitzBasic3D (imperativ-prozedual) so kleine spielchen wie (Bomberman 2d, Malefiz) und auch ein Manager für Formel 1 programmiert, beim F1 Manager bin ich dann auch bereits sehr früh an die grenze der Sprach gestoßen und habe mir nun BlitzMax zugelegt, quasi das gleiche mit OOP erweiterung. und paralell mit OOP projekten angefangen,und stieß bisher schnell an die grenzen von meinem können. (Was unteranderem auch dem Ziel - ein Civilization Klon zu erstellen - verschuldet ist). Bisher hatte es auch immer gereicht die projekte im "extreme programming" durchzuführen, da sie klein waren. Nun will ich aber gleich richtig anfangen. Dazu habe ich mir vor monaten Galileo Computing Objekt Orientierte Programmierung geholt. Soweit so schön.

Nun etwas konkreter zur Frage:

Ich habe mir vorgenommen erstmal ein sehr simples Tower Defence Game auf Grundlage der Objekt orientierten Programmierung zu programmieren. ich habe mir mal auf einem Blatt Papier erstmal alle Gegenstände notiert -> Ich stell mir diese dann als Klassen vor, richtig? z.B "CWelt" <- sie zeichnet das Spielbrett (als TilemapEngine),lässt dabei Platz für die "Informationen" der im spiel angewählten Objekte und in ihr befinden sich alle weiteren Gegenstände : CSpieler (vorerst nur man selbst), CTower <-diese werden vom Spieler durch Anklicken eines Icons aktiviert (wichtig für meine weitere Frage), sie haben gewisse Methoden die sie ausführen können (suche Ziel,feuer rakete ab ...) einige von ihnen haben auswirkungen auf andere Objekte ... , damit kommen wir zu den "CGegnern", da bin ich mir gerade nicht sicher wo sie genau hingehören, als Liste zu einem Spieler zugeordnet? oder gleich zur Welt? ... sie haben ebenfallsmethoden (laufe Weg (werde ich vorerst mit einer Waypoint Liste machen),sterbe,mache Aura , was auch immer). Dazu stell ich mir vor das die Gegner auch Unterklassen haben (Flugeinheit,Renneinheit,Boss ...). Mein problem nun, ich weiß irgendwie immer noch nicht genau, wie ich diese Klassen / Objekte am besten miteinander interagieren lasse... hab da sowas von Eventhandler oder Manager Objekt gelesen. aber an welche stelle gehört das in das System? Und kann mir jemand vielleicht ein Buch oder tutorial empfehlen was sich im spezielleren auf die entwicklung von spielekonzepten konzentriert? In den Büchern die ich bisher gelesen habe waren zwar auch gut ausgewählte Beispeile, aber immer leider auch sehr sehr abstrakt und speziell, w.z.b. "Stellen sie sich for sie sind Kunde einer Firme, diese Firma hat Mitarbeiter, Manager ... hier ein diagramm welche objekte sie benötigen bla bla bla...", ihr wisst worauf ich hinaus will. Also bei mir haperts noch so ein bisschen bei der Analyse der Beziehung und Findung von Objekten untereinander. Ich schätze mal für einfache Hobby spiele werde ich mich nicht extra in der Erstellung von UML2.0 konformen diagrammen einarbeiten müssen, oder? Also son bisschen versuche ich bereits mit Blatt und papier die Objekte zu zeichnen und pfeilen zu versehen, ohne dabei auf richtigkeit nach standard XY zu achten. Ich schätze mal, das selbst zb. die Raketen später von sagen wir Raketenwerfern Objekte sein werden ... --> muss ich also eine Klasse Waffe def. die zu den Türmen gehört, die wiederum den Gegnern schadet? oder doch lieber direkt indem der Turm sagen wir periodisch ein gewissen "schaden" von seinem Ziel abzieht? da gibts ja quasi beliebig viele Möglichkeiten (demzufolge beliebig komplex). Wie schafft man es nun sein Projekt auch nicht ganz so komplex werden zu lassen? das war vorallem früher in der reinen prozeduralen programmierweise Motivationskiller #1 !!! Mit Abstand.

Falls das jetzt noch wichtig sein sollte, wir reden hier von einem SIMPLEN TD Game, keine aufwendige Grafik (2d Grafik ist mit Blitzmax sehr sehr einfach, also dass ist kein Problem an dieser stelle). Ich würde gerne aber auch versuchen es etwas erweiterbarer zu gestalten (kA wie schwer dass dann wird) -> evtl. als Multiplay, indem nun 2 Spieler enthalten sind und gegen einander ..., oder ein Computergestützer Gegner ...

Ich hoffe das war jetzt nicht zu viel. ansonsten bereits lieben dank für eure an und bemerkungen ^^

mfG Stephan

2

02.12.2011, 22:15

Kein Denglisch.
Also kein CTower und dafür ein CGegner. Dann schon CTower und CEnemy, bei den Kommentaren kannst du für dich ruhig Deutsch bleiben.
Doch dieses Denglisch ist kein guter Stil. ;)
Das als Randbemerkung.

MfG
Check

AlexK

1x Rätselkönig

Beiträge: 30

Wohnort: Bielefeld

Beruf: Software-Entwickler

  • Private Nachricht senden

3

13.12.2011, 09:47

Soo, da bisher noch niemand sich hier thematisch zu geäußert hat, werd ich mal meinen Senf dazugeben...

zuerst vorweg: ein paar Absätze hätten dem Text (also dem konkreten Fragenblock) gut getan... ;) wäre ein wenig leichter zu lesen gewesen... aber das ist erstmal nur meine Meinung.
Die Meinung von Checkmateing kann ich übrigens nur unterstützen: entweder komplett Deutsch oder komplett Englisch, so n Mittelding sieht nach gewollt aber nicht gekonnt aus und lässt sich schwerer lesen.
Zudem würde ich die "C" am Anfang weglassen... dass es Klassen sind weißt du ja auch so und sollte sich auch im Code ohne Probleme erkennen lassen.

Zu den eigentlichen Fragen (werd erstmal nicht auf alle eingehen, hab grad nicht so viel Zeit):

Zitat

ich habe mir mal auf einem Blatt Papier erstmal alle Gegenstände notiert -> Ich stell mir diese dann als Klassen vor, richtig?
Joa, schon mal ein guter Ansatz. Lässt sich nicht unbedingt immer verallgemeinern, da man nicht für jeden Gegenstand eine eigene Klasse benötigt. Aber für ein simples TD-Spiel ein guter Anfang.

Zitat

damit kommen wir zu den "CGegnern", da bin ich mir gerade nicht sicher wo sie genau hingehören, als Liste zu einem Spieler zugeordnet? oder gleich zur Welt?
Zur Welt. Sie sind Elemente der Welt, nicht des Spielers. Die Welt muss über alle Elemente aus der Welt Bescheid wissen, der Spieler braucht nur "seine" Sachen zu kennen, wie z.B. seinen Punktestand.

Zitat

Mein problem nun, ich weiß irgendwie immer noch nicht genau, wie ich diese Klassen / Objekte am besten miteinander interagieren lasse... hab da sowas von Eventhandler oder Manager Objekt gelesen. aber an welche stelle gehört das in das System?
Das gehört mehr oder weniger in den Game Loop. Ob du das noch in eine oder mehrere Klassen verpackst, ist deine Sache. Der Game Loop prinzipiell muss alles anstoßen.
Also z.B. in der Reihenfolge:
1. Durchlaufe alle Geschosse (z.B. Raketen) und prüfe, ob ein Gegner getroffen wurde
1a. Aktualisiere Geschoss (und evtl. Gegner, Punktestand des Spielers etc.)
2. Durchlaufe alle Türme der Welt und schaue, ob ein Gegner in Schußnähe ist
2a. Kann der Turm grade schießen? ->Ja: Feuer... (erzeuge ein Objekt vom Typ Rakete mit Ziel Gegner)
3. Durchlaufe alle Gegner und aktualisiere deren Position
4. Zeichne alle Objekt

Und das solange bis entweder die Siegbedingung oder die Niederlagenbedingung eingetreten ist.

Ich hoffe, ich konnt ein wenig weiterhelfen...

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

4

13.12.2011, 12:02

wie bereits geschrieben: es ist sehr löblich, dass du dich erst mit dem Entwurf für die Implementierung auseinandergesetzt hast

auch wenn du meinst, dass du für dein kleines Progrämmchen keine UML-Diagramme brauchst:
ich empfehle dir, dich mit solchen auseinander zu setzen
allerdings sollten für dich Klassendiagramme vollkommen ausreichend sein
auch werden am Anfang die verschiedenen Arten von Beziehungen, die sich in einem UML-Diagramm modellieren lassen, wie Kompositionen und Aggregationen weniger relevant sein
wenn du dich also nur mit einem Teil von UML rumschlägst, hast du nicht die gesamte Komplexität der verschiedenen Diagrammarten und es dürfte wesentlich einfacher sein
der Vorteil ist, dass es bereits einige kostenlose Programme gibt, mit denen man UML-Diagramme bearbeiten kann
solltest du an deinem Modell etwas ändern wollen, so sind diese Änderungen leichter einzuarbeiten, als auf einem Blatt Papier


Eventhandler, Managerklassen und die Main Loop sind 3 verschiedene Dinge, die sich problemlos kombniniert verwenden lassen

ein Eventhandler ist das, was auf ein Event reagiert
die Implementierung kann sich von Sprache zu Sprache unterscheiden
in Java wäre der Beste (und fast einzige) Weg, ein Interface zu definieren, welches von den konkreten Eventhandlern implementiert wird (ein Eventhandler ist somit ein Objekt einer Klasse)
in C# gibt es (zusätzlich zu der Variante in Java) dank Delegates die Möglichkeit, Methodenreferenzen zu übergeben, die nur noch einem bestimmten Muster (Parameterliste) entsprechen müssen (ein Eventhandler ist somit eine Methode)
in Python ist es so, dass man an Methoden und Funktionen aufrufbare Objekte (Objekte, die __call__() implementieren, Methoden oder Funktionen) oder Objekte mit ganz bestimmten Methoden übergeben kann
wie du in BlitzMax vorgehen musst, kann ich nicht sagen, da ich noch nie damit gearbeitet habe

Managerklassen sind Klassen, deren einziger Zweck die Verwaltung von ganz bestimmten Objekten ist (beispielsweise die Verwaltung der Gegner oder die Verwaltung der Projektile)
für die Gegner könnte beispielsweise eine Managerklasse angelegt werden, allerdings denke ich, dass die Gegner von der Welt verwaltet werden sollten, in der sie sich befinden
ich halte reine Managerklassen für unnötig, allerdings will ich deswegen nicht sagen, dass diese es tatsächlich immer sind

die Main Loop ist meist eine Schleife, die die grundlegenden Dinge des Spiels durchläuft - Auswertung der Eingabe, Berechnung der Spielszene, Zeichnen der Spielszene und ggf. Warten bis zum nächsten Durchlauf
es kann durchaus sein, dass das Zeichnen parallel zum Berechnen durchgeführt werden soll, allerdings ist dies in der Regel wesentlich komplizierter, da beispielsweise konkurrierunde Zugriffe vermieden werden müssen (siehe dazu Framerate-unabhängige Spiellogik)
die einzelnen Aufgaben sollten in jedem Fall auf andere Methoden, Funktionen oder Klassen aufgeteilt werden (XNA erzwingt dies beispielsweise, da man keinen Zugriff auf die Main Loop hat, sondern nur auf die Methoden Update() und Draw())


irgendwann wirst du auch das Bedürfnis nach einem Menü haben
dafür empfiehlt sich ein Spielzustands-Automat
bis du das Menü implementierst, solltest du dabei bleiben, die Spielszene so zu initialisieren, als hättest du über das Menü ein neues Spiel gestartet


es gibt noch einige weitere Dinge, die man bei der Implementierung beachten kann (ich hoffe, dass andere diese noch ergänzen können)


@AlexK:
es ist äußerst ungünstig, erst auf eine Kollision zu prüfen und dann die Bewegung durchzuführen
ich denke, man sollte erst überprüfen, ob es nach der Bewegung zu einer Kollision kommen kann und dann erst die Bewegung durchführen
ich habe mal ein Spiel gesehen, bei dem man in eine Wand rein laufen konnte und dann wort wörtlich aus ihr heraus sprang - das beruht auf einer falschen Kollisionsprüfung
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

AlexK

1x Rätselkönig

Beiträge: 30

Wohnort: Bielefeld

Beruf: Software-Entwickler

  • Private Nachricht senden

5

13.12.2011, 13:47

Zitat

es ist äußerst ungünstig, erst auf eine Kollision zu prüfen und dann die Bewegung durchzuführen
ich denke, man sollte erst überprüfen, ob es nach der Bewegung zu einer Kollision kommen kann und dann erst die Bewegung durchführen
Hmm... hast natürlich völlig Recht, daran hatte ich in meinem Beispiel gar nicht gedacht.

Nochmal zum Anfangspost:

Zitat

muss ich also eine Klasse Waffe def. die zu den Türmen gehört, die wiederum den Gegnern schadet? oder doch lieber direkt indem der Turm sagen wir periodisch ein gewissen "schaden" von seinem Ziel abzieht?
Es gibt keinen einzigen "richtigen" Weg, das bleibt eigentlich dir überlassen. Ich empfände aber einen periodischen Schaden als unrealistisch, wenn der Turm z.B. Raketen verschießt.

Du könntest eine Klasse Waffe definieren, die eine Methode "feuer" hat, die ein Objekt vom Typ Geschoss erzeugt. Jeder Turm hat dann eine Liste von Waffen-Objekten und könnte dann so z.B. aufgerüstet werden, indem man ein weiteres Waffenobjekt hinzufügt.

Du könntest andererseits auch ganz statisch sein und einfach ganz viele verschiedene Turm-Ableitungen erzeugen (z.B. Feuerturm, Raketenturm...), die gar nichts von einer Waffe wissen, sondern eine "feuer" Methode haben und dann selbst entscheiden, was für Geschosse sie abfeuern. Ist allerdings recht unflexibel diese Lösung.

Das sind nur 2 Möglichkeiten, wie du das machen könntest, gibt noch unzählige andere Varianten, denke ich...

StephanD87

Frischling

  • »StephanD87« ist der Autor dieses Themas

Beiträge: 2

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

6

14.12.2011, 19:02

Danke

Sehr vielen Dank für die zahlreichen Anregungen.

Mit dem Denglisch, okay, werd ich mir abgewöhnen.

Das mit dem kennzeichnen der Klassen hat praktische Vorteile für die IDE von BMax. (Highlighting ...)

Ich hab mir jetzt mal den GameManager und die Gamestates genauer angeguckt und versucht auf mein Spiel anzuwenden. Die Wiki aus diesem Forum dazu war äußerst hilfreich, außer das ich die States (vorerst?) nicht in Listen speichere, sondern es gibt nur GENAU EIN GameState gleichzeitig.
So, wenn ich dann als nächstes das Prinzip richtig verstanden habe, ersetzt jetzt mein Gamestate
"TGS_RUN_SingePlayer" die ehemalige Klasse CWelt, da sie halt mit .process() und .draw() alle methoden besitzt die benötigt werden um alle Objekte innerhalb des spiels durchzugehen

so sieht jetzt inetwa ein Gamestate aus:

Quellcode

1
2
3
4
5
6
7
8
Type TGameState Abstract

Method Enter() Abstract 'Einstieg in den Gamestate 
Method Process:Int() Abstract '"Mainloop" 
Method Leave() Abstract 'Beenden des Gamestates 
Method Draw() Abstract 'Zeichenfunktion 

EndType
...
Von außen wird das ganze nun so gesteuert:

Quellcode

1
2
3
4
5
Gamemanager.init()
repeat 
     Gamemanager.idle()
until ...
Gamemanager.terminate()

die .idle() ruft immer Gamestate.process() auf bzw. kümmert sich ggf. um das aufrufen eines neuen gamestates wenn die .process() einen anderen Wert als "0" liefert.
Momentan alles noch Frame und Zeitunabhängig. Auf die Gamestates kann man nun mit .process() zugreifen (Abarbeiten der Spielelogik). zusätzlich gibt es noch .Draw(), also das was dann innerhalb der Gamestates gezeichnet werden soll.
Euren Aussagen zufolge, und dr Tutorials die ich noch gelesehen habe ist es nun also wichtig a) in welcher Reihenfolge process (Render + Benutzereingabe) und Draw() (reines darstellen auf dem Bildschirm) benutzt werden und b) welche "art" von Zeitkontingent man den jeweiligen Methoden vergibt. So wäre es jetzt besser die Spielelogik nach festen Zeitschritten und die Zeichnung so schnell wie möglich laufen zu lassen (allerdings nur, wenn das bild vorher fertig aufgebaut werden konnte (siehe VSync?), ja ?
Das mit dem Zeitkontingent muss ich mir nochmal genauer anschauen, bin mir gerade etwas unsicher, ob man schon die "Gamemanager.idle()" in der Hauptschleife nur nach einer bestimmten zeit aufrufen sollte, oder die "idle" so schnell wie der PC schafft und dann innerhalb nur den Process/Draw bremsen. Ist grade doof zu erklären. ich werds einfach selber probieren müssen.
mfG
und vielen Dank nochmal an euch!

buggypixels

Treue Seele

Beiträge: 125

Wohnort: Meerbusch

Beruf: Programmierer

  • Private Nachricht senden

7

15.12.2011, 15:10

Als erstes eine kurze Anmerkung: Verwende niemals deutsche Begriffe im Code. Weder für Klassennamen noch Methoden. Niemals. Und niemals Denglisch!
Sonst wirst Du es später im Berufsleben sehr schwer haben.

Also Deinen letzten Beitrag verstehe ich nicht so ganz. Am Anfang fragst Du nach passenden Klassen etc. und nun bist Du schon bei GameStates.
Das sind 3 Schritte voraus. Schau erst einmal, dass das Spiel läuft. GameStates wirst Du brauchen, wenn Du dann mal ein Startmenü, Highscoreliste, Einstellungen oder
was auch immer hinzufügen willst. Das sind einzelne GameStates. Ich denke mal, dass Du derzeit nur EINEN GameState hast, nämlich Dein Spiel.
Das sollte erst einmal laufen, dann geht es die nächsten Schritte.

Das mit dem Zeitkontingent hört sich schräg an. Aber vielleicht verstehe nur ich es nicht.
Generell mußt Du natürlich in jedem Frame alles zeichnen. Die Logik dahinter muß ja eventuell nicht jeden Frame aktualisiert werden.
Man läßt zum Beispiel gerne mal die eigentlich Logik mit festen Zeitschritten laufen. Man schaut also in der Hauptschleife, ob es denn wieder mal Zeit wird,
die Logik aufzurufen. Dazu bremst man natürlich nirgends das Spiel. Sondern man hat eine Variable mit der man die jeweils vergangene Zeit hochzählt und
dann halt schaut, ob man denn die Logik aufrufen muß.
In Deinem Beispiel würde es ja ausreichen, wenn ein Tower nur einmal pro Sekunde kontrolliert, ob er einen neuen Gegner anvisieren muß.

Bevor Du auch anfängst, den GameStateManager aus dem Wiki zu verwenden, lies vorher die Kommentare. Zurecht sind nicht alle mit dem Design einverstanden.
Außerdem gibt es ein paar grobe Designschnitzer in dem Code. Also besser erst einmal abwarten.

Werbeanzeige