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

Fred

Supermoderator

  • »Fred« ist der Autor dieses Themas

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

1

21.03.2011, 22:35

Freund oder Feind: Spielobjekte in Strategiespielen

Guten Abend zusammen,

ich habe mir in den letzten Tagen ein paar Gedanken über Spiel-Objekte in einem Strategiespiel gemacht und bin schließlich auf das Problem gestoßen, wie ich bestimme, welches Objekt zu welchem Spieler gehört.
Also meine grobe Struktur sieht so aus, dass ich eine Klasse für das Laden der Map habe, in der wird die Map-Datei geladen, alle Speilobjekte, werden erstellt und verwaltet(nicht von der Klasse selbst, aber sie kümmert sich darum), es werden die Spielinformationen geladen etc.. Diese Klasse bildet also quasi das Bindeglied zwischen meinen Objekten und allen Spielinformationen. Dann existieren noch ein paar Basisklassen für Objekte, die sich darum kümmern, dass bestimmte Objekte zerstörbar oder anwählbar etc. sind. All das findet sich eben in verschiedenen Klassen wieder und die eigentlichen Spielobjekte erben von den Klassen, die sie benötigen.
Jetzt habe ich bei den Objekten aber das Problem, dass sie einem Spieler zugeordnet werden sollen. Der Einfachheit halber seien er mal nur 2(Wobei es bei mehr Spielern natürlich noch komplexer würde und noch mehr Probleme gäbe). Nun habe ich mir überlegt, der Object-Klasse einfach ein enum zu verpassen, welches bestimmt, ob das Objekt Freund, Feind oder Neutral ist. Im Grunde wäre das kein Problem nur wäre da eben der Nachteil, dass sich in den Objekten große If-Blöcke befinden, da ein feindliches Objekt ja ganz anders zu handhaben ist als ein eigenes(auf ein feindliches Gebäude sollte man bspw. nicht klicken können und Einheiten bauen ;)). Problematisch wäre evtl. auch, dass es innerhalb der Objekte dann ggf. »Unterobjekte«(Also Buttons zum erstellen der Einheiten oder Gesundheitsanzeigen oder Spezialfähigkeiten...) gibt, die nur von eigenen Einheiten benötigt werden. Bei feindlichen Objekten wären diese Objekte aber eben einfach in der Klasse und würden Speicher verbrauchen.
Eine andere Möglichkeit, die ich mir überlegt habe war, dass man jedes Objekt nochmals unterteilen könnte in Freund oder Feind. Also beispielsweise wäre die Klasse obj_soldier dann Basisklasse für obj_enemy_soldier und obj_own_soldier. Das Problem hierbei wäre nur, dass man dann ja unglaublich viele Klassen hat, die man alle verwalten muss und wenn man jetzt bspw. wie in AoEII die gegnerischen Einheiten mit Mönchen bekehren kann(nicht, dass ich das jetzt vorhätte, aber es geht ums Prinzip), ist das ja auch nicht so einfach aus einer Gegner-Klasse mal eben einen Freund zu machen ;).

Meine Frage nun an euch, ob euch Techniken geläufig sind, die mir nun gar nicht in den Sinn gekommen sind. Wie würdet es ihr machen? Habt ihr vllt. so etwas in der Art schon einmal umgesetzt und könnt mir hierbei Tipps geben?

Vielen Dank für eure Antworten
Fred

babelfish

Alter Hase

Beiträge: 1 222

Wohnort: Schweiz

Beruf: Informatiker

  • Private Nachricht senden

2

21.03.2011, 23:32

Ich würd ganz klar ne Klasse "Player" machen, und diese für jeden Spieler + Computergegner instanzieren.
Dann jedem Objekt den genauen Spieler als Pointer mitgeben.

Bekehren ist dann nichts weiteres als "this->ControllingPlayer = CPU2" :D

Um herauszufinden, wer Freund oder Feind ist verwendest du dann am besten Funktionen welche die Allianzen zwischen den Mitspielern vergleichen.
Es ist für die KI später sicher auch nützlich zu wissen, wer Freund oder Feind ist. Ich würde das nicht zu stark vom Hauptspieler aus ansehen.

3

22.03.2011, 00:39

Ich würde für größere Spielprojekte immer einen komponentenbasierten Ansatz wählen. Schau dir mal an wie das z.B. bei Unity gemacht wird http://unity3d.com/support/documentation…ameObjects.html
Spielobjekte sind einfach eine Liste von Komponenten. Komponenten sind als Schnittstelle definiert. Es gibt eine Komponente die definiert eine Funktion bool isHostile(Spieler s). Klickt man auf ein Objekt wird das Objekt nach der Komponente durchsucht und wenn die Komponente gefunden wurde, wird die Funktionen aufgerufen - ansonsten wird false angenommen. Um die Komponente einem Objekt anzuhängen muss man sie mit einem Verweis auf ein Spielerobjekt initialisieren.
Beispiel:

Quellcode

1
2
3
4
5
6
class ControlledByPlayerComponent : Component {
 Player getOwner()
 bool isHostile(Player p)
 bool changeOwner(Player p)
 bool canBeControlledBy(Player p)
}

Das schwierigste "Problem" bei diesem Ansatz ist wohl, wie die Komponenten für ein Spielobjekt auf Anfrage herausgesucht werden.

Ein Link zum "Game object component system" http://cowboyprogramming.com/2007/01/05/…-your-heirachy/

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »Chromanoid« (22.03.2011, 01:13)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

22.03.2011, 07:56

Jetzt wäre erstmal die Frage über was genau Du redest. Über den kontrollierenden Server oder den Client? Der Client braucht die meisten dieser "IF-Blöcke" ja gar nicht, da er nur Requests sendet und da wäre ein enum durchaus nicht ganz verkehrt, da sich der Status (hostile/neutral/etc) ja auf den Spieler vor dem Bildschirm bezieht und nicht als Relation zwischen zwei Objekten.

Der Server, welcher die Logik ausführt, der wäre mit einem Ansatz von Chromanoid sicherlich gut beraten (auch wenn ich das Suchen der Komponenten für überflüssig halte), was aber wie schon gesagt zu diesen "IF-Blöcken" führen könnte. Um das zu umgehen kannst Du natürlich versuchen die kontrollierende Logik in "AI"-Klassen auszulagern und nur diese kontrollieren das Verhalten der Objekte (manche reagieren also auf Eingaben des Spielers oder automatisch auf Anwesenheit gegnerischer Objekte und andere nicht). Somit würde Polymorphie das Problem verwalten und die "IF-Blöcke" wären weg. Allerdings braucht jedes Objekt wohl mehrere dieser KIs, da ein Objekt ja nie "hostile" oder "neutral" von sich aus ist, sondern immer nur in Bezug auf ein anderes Objekt. Die richtige KI zu liefern wäre dann die einzige Methode, welche ein IF, bzw. switch bräuchte.
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]

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

5

22.03.2011, 09:04

Wie Babelfisch schon sagte, ist das ganze doch gar kein Problem wenn du einfach jedem Spieler eine Allianz zuordnest. Spieler können dann dynamisch im Spiel einer Allianz beitreten oder austreten und so zu potentiellen Feinden werden. Alle neutralen Spieler gehören einfach der "Neutralen Allianz" an, die zu allen anderen immer befreundet bzw. neutral ist. (Je nachdem ob es hier im Spiel semantische Unterscheide gibt.)

Jedes Objekt im Spiel hätte so einen Zeiger auf den Spieler den das Objekt gehört und diese Klasse hätte einen weiteren Zeiger auf dessen Allianz. So kannst du bequem die verschiedensten Szenarien durchspielen und bekommst ein einfaches aber dennoch ausreichendes System.

Das mit den Komponenten ist sicher eine gute Idee, gehört aber eher in die Entwurfsphase einer Engine. So ein System in einem Spiel zu integrieren ist ihmo Overkill und würde Mächtigkeit bringen, die nur bedingt sinnvoll ist.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

22.03.2011, 10:15

jo, koschka, aber bei der Lösung kommst du ohne zusätzliche Maßnamen nicht um gewalltige IF-Blöcke für die Behandlung verschiedener Klassifikationen rundrum.
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]

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

7

22.03.2011, 11:40

Ja, aber das liegt nicht an dem Vorschlag mit den Allianzen, sondern kommt daher, dass hier nicht sauber genug objektorientiert getrennt wurde. Mir persönlich gefällt diese Klasse hier nicht, die das Anwählen verarbeitet. Dieses Anwählen würde ich eventuell in ein Interface auslagern und das eigentliche Anwählen erst in der Einheiten-Klasse implementieren. So kann man sehr einfach prüfen, ob ein anwählen akzeptiert wird (abhängig vom Spieler, Allianz, etc.). Spezialisierungen einzelner Einheitenkategorien sind durch ein simples Überschreiben dieser Methode möglich.

Klassen für die Anzeige von Lebensanzeigen würde ich nicht bereitstellen, Klassen machen hier ihmo wenig Sinn, da die Lebensanzeige direkt mit einer Einheit zusammenhängt. So gibt es keine Kardinalitäten, da jede Einheit genau nur eine Lebensanzeige hat. Diese Funktion würde ich direkt in die Einheiten-klasse (evtl. auch abstrakt) integrieren.

Gewaltige If-Blöcke sehe ich da nicht, da das eine ja rein gar nichts mit dem anderen zu tun hat - oder habe ich etwas vergessen?

Beispielimplementierung, die das gesagte vielleicht etwas verdeutlicht

C#-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
    /// <summary>
    /// Inherit from this interface, if you want to 
    /// handle a Select by a Player
    /// </summary>
    public interface ISelectable
    {
        void OnSelect(Player sender);
    }

    /// <summary>
    /// General Unit Class
    /// </summary>
    public class Unit : ISelectable
    {
        public Player myOwner;
        public Ally myAlly;

        public Unit(Player owner)
        {
            myOwner = owner;
            myAlly = owner.Ally;
        }

        private void DrawHealthBar()
        { ... }

        private void Draw()
        { 
            ...
            DrawHealthBar();
            ...
        }

        /// <summary>
        /// Select Unit
        /// </summary>
        /// <param name="sender"></param>
        public void OnSelect(Player sender)
        {
            // Select, if unit is no enemy
            if (myAlly.isEnemy(sender))
                return;
        }
    }

    public class SpecialUnit : Unit
    {
        public override void OnSelect(Player sender)
        {
            // This Unit will never be selected
            return;
        }
    }

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »koschka« (22.03.2011, 11:49)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

22.03.2011, 11:57

Mir persönlich gefällt diese Klasse hier nicht, die das Anwählen verarbeitet. Dieses Anwählen würde ich eventuell in ein Interface auslagern und das eigentliche Anwählen erst in der Einheiten-Klasse implementieren. So kann man sehr einfach prüfen, ob ein anwählen akzeptiert wird (abhängig vom Spieler, Allianz, etc.). Spezialisierungen einzelner Einheitenkategorien sind durch ein simples Überschreiben dieser Methode möglich.

Diese Prüfung ist ja aber doch wieder ein IF. Und diese IF-Unterscheidung hättest Du dann überall ;)

Ich stimmt aber mit Dir überein, dass das nicht passieren würde, bei sauberer Trennung der Logik und mit tiefergehender Objekt-Orientierung.
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]

Fred

Supermoderator

  • »Fred« ist der Autor dieses Themas

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

9

22.03.2011, 13:19

Vielen Dank für eure Antworten.
Ich denke ich werde auf jeden Fall mal so ein »Player«-Konzept versuchen zu verwirklichen. Habe mittlerweile einen Ansatz, der funktionieren sollte.
Der Komponentenansatz klingt grundätzlich interessant, aber da muss ich mir mal noch ein sinnvoll funktionierendes Konzept überlegen, um das auch wirklich einmal zu verwenden. Für mein derzeitiges Vorhaben, sollte aber erstmal der konventionelle Ansatz ausreichen.

koschka: Vielen Dank für deinen Code, aber das ist im Grunde genau das, was ich mache. Vielleicht ist es bei meiner Beschreibung irgendwie falsch verstanden worden, aber egtl. arbeitet mein System genauso, wie du es beschreibst.
Aber nur zur Klarstellung: ich lagere nicht die Lebensanzeige aus, sondern ich lagere alles aus, was mit Lebensenergie zu tun hat. Und zwar aus objekt-orientieren Ansätzen. Denn nicht jedes Objekt ist automatisch zerstörbar - also braucht auch nicht jedes Objekt eine Lebensanzeige(ob sie nun angezeigt wird oder nicht).

BlueCobold: Danke für deine Tipps. Wenn ich irgendwann mal wieder Zeit und Muse habe, werde ich glaube ich mal eine kleine Server-Client-Engine mit Component-basierten Ansatz schreiben. Aber wie koschka schon sagte: Das in ein Spiel zu implementieren ist nicht unbedingt gut. Allerdings habe ich durch deine Hinweise einige Ideen, wie ich das ganze grundsätzlich handhaben könnte. Mal sehen, was ich daraus machen kann ;).

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

22.03.2011, 14:12

Nun, wenn Dein Spiel Multiplayer ist, wirst Du das eh machen müssen. Sonst könnte ja jeder Client diktieren, wo er wie viel Einheiten oder Resourcen hat (WoW lässt grüßen).
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]

Werbeanzeige