Am meisten hat mir als ich frisch angefangen habe für Teeworlds zu entwickeln, war eine Übersicht über die Source: Ich konnte zwar programmieren, aber wo ich was finde und wie die einzelnen Komponenten und Klassen zusammenarbeiten war denkbar unklar.
Ich werde hier versuchen einen kleinen Überblick zu bieten. Dabei werde ich nur auf das absolute Front-End der Serversource eingehen, da es danach komplex wird und mehr als absoluter Anfänger so oder so nicht mehr wissen benötigt wird. Die nachfolgenden Informationen werden sich also fast ausschließlich auf den Code in src/game/server beziehen.
Okay, also vielleicht sollten wir zu nächst einige Begrifflichkeiten klären, um Missverständnisse auszuschließen.
Ein "Entity"
Sollte jeder zumindest vom mappen her schon mal vernommen haben.
Allerdings ist die Bedeutung hier etwas anders, wir sprechen nämlich nicht etwa von den kleinen Symbolen aus der "entities.png" Datei, sondern viel mehr von Entities im ursprünglichen Sinne.
Ein Entity ist ein "physisches" Objekt, das eindeutig von der Karte, also der Welt, abgegrenzt werden kann. Ein Tee ist also auch ein Entity, ebenso wie Projektile, Pickups (Herzen, Schilde, Waffen) und der Laser.
Der "Character"
Wie oben angedeutet ein Entity, ihr kennt es vermutlich besser als euren Tee. Also der physische part eines Spielers, sprich die Spielfigur.
Gut, den Rest sollte man sich eigentlich mit gesundem Menschenverstand und Kenntnis im Bereich Programmieren herleiten können, sollte ich was vergessen haben, meldet euch!
Was ist jetzt mit dem Aufbau?
Grundsätzlich würde ich gerne mit dem Gamecontroller anfangen, also der CGameController Klasse in der gamecontroller.cpp. Wie der Name bereits vermuten lässt wird hier das Spiel "kontrolliert", ferner heißt das, dass hier sozusagen die Spielregeln aufgestellt werden.
Die Klasse wird in den meisten Spieltypen durch eine Klasse erweitert, die sich in einer Datei in game/server/gametypes befindet, für CTF wäre das dann logischer Weise die ctf.cpp mit der CGameControllerCTF Klasse, aus der in der CGameController Klasse von oben dann ein Objekt erzeugt wird, dass zusätzliche Spielregeln und auch Dinge wie den Namen der Modus festlegt, zum Beispiel bei CTF das scoring durch Flaggen erobern.
Für weiteres Management, was nur im entfernteren direkt etwas mit dem Spiel zu tun hat gibt es dann die CGameContext Klasse in der gamecontext.cpp. Chat, Votes und Broadcast um nur einige Verwaltungsaufgaben der Klasse zu nennen.
So, jetzt wird es ein wenig Spannender. Weiter oben haben wir bereits den Character kennengelernt. Wir erinnern uns: Der physische part des Spielers, der Tee. Sind wir also tot oder Spectator, gibt es keinen Character, dies sollten wir uns im Hinterkopf behalten um Nullpointern aus dem Weg zu gehen. Naja, aber wenn wir tot sind, sind wir ja trotzdem noch auf dem Server. Es muss also noch etwas geben, dass sozusagen über dem Character steht: Den Player, erzeugt aus der CPlayer Klasse in player.cpp! Den Player gibt es für jeden Spieler auf dem Server, und zwar zu jeder Zeit.
Vielleicht habt ihr ja schon mal von "Client IDs" gehört, diese dienen dazu einen Player eindeutig zu identifizieren und ihm damit auch einen Slot zuzuweisen und auf ihn zuzugreifen. In der CGameContext Klasse finden wir das Attribut "m_apPlayers", wie wir anhand der Notation schon vermuten können handelt es sich um ein Array mit Pointern auf alle Spieler. Aus den meisten Klassen heraus kann man glücklicherweise sehr leicht auf das CGameContext Objekt zugreifen, nämlich mit GameServer()->. Also, um zum Beispiel aus einem for-loop auf einen Player zuzugreifen können wir einfach einen auf GameServer()->m_apPlayers[ClientID] machen, wenn ClientID der enumerator ist (Natürlich immer auf Nullpointer checken!) .
Anhand des Players bzw. des Characters das jeweilige andere Objekt zu erhalten ist nicht schwer. Dafür werden die Funktionen GetCharacter() und GetPlayer() bereitgestellt.
Offensichtlich befinden sich alle Entity Klassen unter game/server/entities. Diese erben jeweils von der Überklasse CEntity aus entity.cpp, das ist eine von den Datein, die ihr nur in ganz wenigen Fällen editieren müsst/solltet.
Zum Schluss bleibt noch die Erzeugung der anderen Entities.
Die Projektile aus der CProjectile Klasse werden in CCharacter erzeugt (FireWeapon()), ebenso wie der Laser aus CLaser.
Die Pickups werden sehr simpel aus CPickups (pickups.cpp) gemanaged.
Ich hoffe ihr konntet anhand dieser Infos die Front-End Serversource ein wenig besser verstehen.
- metzgerlin
Ich werde hier versuchen einen kleinen Überblick zu bieten. Dabei werde ich nur auf das absolute Front-End der Serversource eingehen, da es danach komplex wird und mehr als absoluter Anfänger so oder so nicht mehr wissen benötigt wird. Die nachfolgenden Informationen werden sich also fast ausschließlich auf den Code in src/game/server beziehen.
Okay, also vielleicht sollten wir zu nächst einige Begrifflichkeiten klären, um Missverständnisse auszuschließen.
Ein "Entity"
Sollte jeder zumindest vom mappen her schon mal vernommen haben.
Allerdings ist die Bedeutung hier etwas anders, wir sprechen nämlich nicht etwa von den kleinen Symbolen aus der "entities.png" Datei, sondern viel mehr von Entities im ursprünglichen Sinne.
Ein Entity ist ein "physisches" Objekt, das eindeutig von der Karte, also der Welt, abgegrenzt werden kann. Ein Tee ist also auch ein Entity, ebenso wie Projektile, Pickups (Herzen, Schilde, Waffen) und der Laser.
Der "Character"
Wie oben angedeutet ein Entity, ihr kennt es vermutlich besser als euren Tee. Also der physische part eines Spielers, sprich die Spielfigur.
Gut, den Rest sollte man sich eigentlich mit gesundem Menschenverstand und Kenntnis im Bereich Programmieren herleiten können, sollte ich was vergessen haben, meldet euch!
Was ist jetzt mit dem Aufbau?
Grundsätzlich würde ich gerne mit dem Gamecontroller anfangen, also der CGameController Klasse in der gamecontroller.cpp. Wie der Name bereits vermuten lässt wird hier das Spiel "kontrolliert", ferner heißt das, dass hier sozusagen die Spielregeln aufgestellt werden.
Die Klasse wird in den meisten Spieltypen durch eine Klasse erweitert, die sich in einer Datei in game/server/gametypes befindet, für CTF wäre das dann logischer Weise die ctf.cpp mit der CGameControllerCTF Klasse, aus der in der CGameController Klasse von oben dann ein Objekt erzeugt wird, dass zusätzliche Spielregeln und auch Dinge wie den Namen der Modus festlegt, zum Beispiel bei CTF das scoring durch Flaggen erobern.
Für weiteres Management, was nur im entfernteren direkt etwas mit dem Spiel zu tun hat gibt es dann die CGameContext Klasse in der gamecontext.cpp. Chat, Votes und Broadcast um nur einige Verwaltungsaufgaben der Klasse zu nennen.
So, jetzt wird es ein wenig Spannender. Weiter oben haben wir bereits den Character kennengelernt. Wir erinnern uns: Der physische part des Spielers, der Tee. Sind wir also tot oder Spectator, gibt es keinen Character, dies sollten wir uns im Hinterkopf behalten um Nullpointern aus dem Weg zu gehen. Naja, aber wenn wir tot sind, sind wir ja trotzdem noch auf dem Server. Es muss also noch etwas geben, dass sozusagen über dem Character steht: Den Player, erzeugt aus der CPlayer Klasse in player.cpp! Den Player gibt es für jeden Spieler auf dem Server, und zwar zu jeder Zeit.
Vielleicht habt ihr ja schon mal von "Client IDs" gehört, diese dienen dazu einen Player eindeutig zu identifizieren und ihm damit auch einen Slot zuzuweisen und auf ihn zuzugreifen. In der CGameContext Klasse finden wir das Attribut "m_apPlayers", wie wir anhand der Notation schon vermuten können handelt es sich um ein Array mit Pointern auf alle Spieler. Aus den meisten Klassen heraus kann man glücklicherweise sehr leicht auf das CGameContext Objekt zugreifen, nämlich mit GameServer()->. Also, um zum Beispiel aus einem for-loop auf einen Player zuzugreifen können wir einfach einen auf GameServer()->m_apPlayers[ClientID] machen, wenn ClientID der enumerator ist (Natürlich immer auf Nullpointer checken!) .
Anhand des Players bzw. des Characters das jeweilige andere Objekt zu erhalten ist nicht schwer. Dafür werden die Funktionen GetCharacter() und GetPlayer() bereitgestellt.
Offensichtlich befinden sich alle Entity Klassen unter game/server/entities. Diese erben jeweils von der Überklasse CEntity aus entity.cpp, das ist eine von den Datein, die ihr nur in ganz wenigen Fällen editieren müsst/solltet.
Zum Schluss bleibt noch die Erzeugung der anderen Entities.
Die Projektile aus der CProjectile Klasse werden in CCharacter erzeugt (FireWeapon()), ebenso wie der Laser aus CLaser.
Die Pickups werden sehr simpel aus CPickups (pickups.cpp) gemanaged.
Ich hoffe ihr konntet anhand dieser Infos die Front-End Serversource ein wenig besser verstehen.
- metzgerlin
1338 - the next level