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

Tobiking

1x Rätselkönig

  • Private Nachricht senden

11

05.04.2010, 17:07

Als ich davon las dachte ich eher an policy-based design. Aber man kann ja mal einfach alle pattern anschauen um festzustellen welches am besten passt :) .

Oh, da hab ich mich wohl etwas vom Namen fehl leiten lassen. Composing und Composite Pattern ist etwas anders als ich meinte. Policy-based design und strategy pattern wären die richtigen Bezeichnungen. Wobei policy-based design wohl die Methode ist um das strategy pattern in C++ schon zur Compilezeit auswerten zu lassen. Hat wenn ich das richtig überblicke aber auch ein paar Einschränkungen.

Kann mir das vielleicht mal Jemand an einem kleinen Code-Beispiel demonstrieren?

Wikipedia hat da ganz ordentliche Beispiele zu: policy-based: http://en.wikipedia.org/wiki/Policy-base…#Simple_example strategy pattern: http://en.wikipedia.org/wiki/Strategy_pattern#C.2B.2B. Für mehrere Angriffe würde ich auf Anhieb sagen eignet sich das strategy pattern besser. Man würde dann wie schon gesagt wurde statt einem Zeiger auf einen Angriff dann z.B. einen std::vector mit Zeigern auf Angriff nehmen und sich dazu den ausgwählten Angriff noch irgendwie merken.

12

06.04.2010, 22:03

So, hier mein neuer Ansatz, jetzt kann ich zur Laufzeit die Skills so bestimmen wie ich es möchte:

C-/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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <vector>


using namespace std;

class Skill // Basisklasse, nicht abstrakt, weil ich Instanz von ihr brauche
{
public:
virtual void Angriff() {cout << "Skill!!!" << endl;}
};


class Feuerball : public Skill
{
public:
void Angriff() {cout << "Flammmmme!!!" << endl;}
};

class Schwerthieb : public Skill
{
public:
void Angriff() {cout << "Schwerthieb!!!" << endl;}
};

class Eisnova : public Skill
{
public:
void Angriff() {cout << "Eisnova!!!" << endl;}
};


class Spieler 
{
public:
Skill *pSkill;
vector<Skill*> Skills; // Hier werden die Skills reingeschoben

int ID; // Über die ID werden Die Skills aufgerufen

void UseSkill( int ID ) 
{
pSkill = new Skill;
pSkill = Skills[ID];
pSkill->Angriff();
}

};


int main()
{
Feuerball *pFeuerball = NULL;      // Wohin mit den ganzen Skills?
pFeuerball = new Feuerball;        // 

Schwerthieb *pSchwerthieb = NULL;  //
pSchwerthieb = new Schwerthieb;    //

Eisnova *pEisnova = NULL;          //
pEisnova = new Eisnova;            //

Spieler *pSpieler;                 //
pSpieler = new Spieler;            //



pSpieler->Skills.push_back( pFeuerball );
pSpieler->Skills.push_back( pSchwerthieb );
pSpieler->Skills.push_back( pEisnova );


cin >> pSpieler->ID;

pSpieler->UseSkill( pSpieler->ID ); // Skill einsetzen


system("PAUSE");
    return 0;
}


Ist nur ein ganz grober Ansatz, habe keine Feinheiten reingemacht (Konstruktoren etc.). Sieht das denn verünftig aus oder muss ich etwas radikal ändern? Bei den ganzen Skills weiß ich nicht genau wo ich die deklarieren/Speicher anfordern soll. Soll ich die in einen Kontruktor stecken und wenn ja, von welcher Klasse? Oder kommt sowas eher in eine Init() Funktion einer Klasse Game, mit der ich die ganze Logik vom Game handle?

Tobiking

1x Rätselkönig

  • Private Nachricht senden

13

06.04.2010, 23:41

Sieht vom Prinzip schon ok aus. Aber der direkte Zugriff auf Skills ist scheußlich :D

Bei der Verwaltung der Skills kommt es auch etwas darauf an wie umfangreich das ganze werden soll. Das einfachste wäre wohl auf die Wiederverwendung zu verzichten und jeder Spieler bzw. jede Einheit bekommt eine neue Instanz dieses Skills. Wenn so ein Skill nur ein paar Werte besitzt ist der Overhead nicht so groß. Funktionen sollten dabei wenn ich mich nicht irre gar nicht ins Gewicht fallen. Man kann dann auch Werte unabhängig voneinander verstellen, so dass der Feuerball des Spielers andere Stärken hat als der von Einheiten. Die Bereinigung fällt dann auch leicht. Wird die Einheit gelöscht, so löscht diese alle Skills die sie in der Liste hat.

Wenn so ein Skill viele Daten, vielleicht sogar Effekte oder ähnliches enthält und dauernd wiederverwendet wird, könnte man sich einen Manager dafür schreiben. Dieser sorgt dann dafür das von jedem Skill eine Instanz existiert und bietet Funktionen zum holen eines Skills anhand einer ID, eines Namens oder sonstiges. Problematisch ist dabei das der Manager nicht direkt weiß ob jemand noch diesen Skill benutzt. Dafür wären dann wohl smart pointer oder andere Methoden nötig.

14

06.04.2010, 23:44

Vom Ansatz funktioniert das. Teilweise ist Programmieren geschmackssache, ich würde es wohl nicht so machen. Ich lasse mich da eher zu hinreißen die Liste/Vector nicht in der Spielerklasse habe zu müssen und eher einen Zeiger auf eine weiteren "Skillmanager"-Klasse lege. Dieser kann dann eine Liste der Skills halten und das gesamte Skillsystem verwalten. Besonders praktisch ist dabei die Tatsache, dass du nun ohne viel Aufwand auch Gegner mit eigenen Zaubern machen kannst. Diese haben dann auch nur einen Zeiger auf ihre eigenen "Skillmanager" und du müsstest das Ganze nicht doppelt programmieren (vorausgesetzt es ist alles durchdacht :lol: ). Aber da wirst du sicher schnell durchblicken.

15

07.04.2010, 00:03

Zitat

Das einfachste wäre wohl auf die Wiederverwendung zu verzichten und jeder Spieler bzw. jede Einheit bekommt eine neue Instanz dieses Skills.
Ich möchte aber ja nicht zu Beginn dem Spieler alle Skills reinhauen, er hat am Anfang ja vielleicht nur einen und später 10. Deswegen habe ich in meiner Klasse nicht Instanzen der Skills gepackt, sondern nur die Instanz von Skills. Dann sollte ich wohl auf jeden Fall einen Skillmanager benutzen wenn ich nicht direkt über eine Instanz von Skill auf die Skills zugreifen möchte, oder?

Zitat

Dieser kann dann eine Liste der Skills halten und das gesamte Skillsystem verwalten.
Nehmen wir an ich habe 50 Skills (im gesamten Spiel, nicht ein einzelner Spieler), würde ich die dann bei diesem SkillManager in eine Init() Funktion packen und zu Beginn des Spiels werden die alle in eine Liste geschoben? Ich muss noch bevor das Spiel startet für alle Skills mit new Speicher anfordern, oder?

C-/C++-Quelltext

1
2
Feuerball *pFeuerball = NULL;      
pFeuerball = new Feuerball;

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Proggi« (07.04.2010, 00:11)


Tobiking

1x Rätselkönig

  • Private Nachricht senden

16

07.04.2010, 01:54

Das new ist dafür da um während der Programmlaufzeit Instanzen zu erstellen (genauer: Speicher für diese zu reservieren). Das brauchst du nicht zu Beginn des Programms machen. Du musst nur darauf achten, dass die Liste der Skills leer sein kann, oder keinen Feuerball enthält weil dieser erst später dazu kommt.

Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
// Die Funktion levelUp wird immer aufgerufen wenn der Spieler ein Level aufsteigt
void levelUp(int level) {
    if(level == 10) {
        pSpieler->Skills.push_back( new Feuerball() ); // Erstellt den Feuerball und fügt ihn in die Skillliste wenn der Spieler Level 10 erreicht.
    }
}

17

07.04.2010, 11:07

Cool, genau sowas hab ich gebraucht. :)
Wusste nicht dass man Instanzen über den Konstruktor mit new erstellen kann, dachte das muss immer so sein:

C-/C++-Quelltext

1
pFeuerball = new Feuerball;


...deswegen hatte mich das auch immer so verwirrt. :D

the[V]oid

Alter Hase

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

18

07.04.2010, 12:38

wie zur Hölle kann man hier Posts löschen? O.o
<< an dieser Stelle ist eine Signatur verstorben >>

K-Bal

Alter Hase

Beiträge: 703

Wohnort: Aachen

Beruf: Student (Elektrotechnik, Technische Informatik)

  • Private Nachricht senden

19

07.04.2010, 13:04

Das wäre auch eine schöne Anwendung für Scripting. Skills und zugehörige Visualisierung werden nicht im Quelltext definiert sondern außerhalb in Dateien, welche zur Laufzeit geladen werden.

20

08.04.2010, 21:14

Ich bin jetzt dabei mir einen Skillmanager zu erstellen, weiß aber nicht so genau ob die Funktionen UseSkill und levelUp in die Klasse Player oder in den Skillmanager sollen. Wenn ich es so mache ist der Funktionsaufruf ziemlich umständlich irgendwie, hat Jemand eine Idee wie man das besser macht? Sollte nicht zu kompliziert sein und möglichst auf den Beispielcode bezogen.

C-/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
class SkillManager 
{
public:
    Skill *pSkill;
    vector<Skill*> Skills; // Hier werden die Skills reingeschoben

    void UseSkill( int ID ) 
    {
    pSkill = new Skill;
    pSkill = Skills[ID];
    pSkill->Angriff();
    }

    void levelUp(int level) 
    {
    if(level == 10) 
    {
        Skills.push_back( new Feuerball() ); // Erstellt den Feuerball und fügt ihn in die Skillliste wenn der Spieler Level 10 erreicht.
    }
    
    if(level == 20) 
    {
    Skills.push_back( new Schwerthieb() );
    Skills.push_back( new Eisnova() );
    }
    }

};

class Spieler 
{
public:
    SkillManager *pSkillManager;

};


int main () 
{

pSpieler->pSkillManager->levelUp( 20 ); // Das sieht komisch aus

{

Werbeanzeige