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

1

01.06.2010, 17:43

Kommunikation zwischen Objekten auf einer Karte (Designfrage)

Hey,
ich wollte mal fragen, wie ich am besten mehrere Objekte "kommunizieren" lasse... Welches Design dafür am besten wäre.
Im Moment mach ich das immer so in der Art:

eine Map-Klasse, die eine Liste mit allen Objekten enthält

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
class Map
{
public:
    // Blabla

std::list<Object*>& GetObjects()
{
    return mObjets;
}

private:
    std::list<Object*> mObjects;
};


und eben die Object-Klasse, mit einem Pointer zu der Map-Instanz

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Object
{
public:
    // Blabla

void SayHello() const
{
    // Zufälliges Object "ansprechen"... Alles nur symbolisch gemeint
    std::list<Object*>& objects = mMap->GetObjects();
    objects[rand(objects.size())]->Hello(*this);
}

private:
    Map* mMap;
};


Ist das so okay? Soll ich einfach jedem Objekt einen Pointer zur Map-Klasse übermitteln?
stɪl traɪ tuː θɪŋk ˈpɒzətɪv

idontknow

unregistriert

2

01.06.2010, 18:44

Also würde mal mit meiner Mini-Erfahrung bezüglich UML (Unified Modelling Language oder so ähnlich eben Programm Design wenn msn sehr grob nimmt ^^) sagen, dass das prinzipiell funktionieren mag designtechnisch aber keine schöne Lößung ist!

Du musst dich einfach fragen, was genau Object A jetzt aus der Map braucht, denn ein "Objekt" sollte sofern perfekt Designed nur mit anderen Objekten zutun haben mit denen es zu tun haben _muss_ und nicht schlicht und ergreifend mit allen!

Selber mache ich das oft genua wie du aber designtechnisch ist das eigentlich nicht sonderlich schöön bzw nur in AUsnahmefällen schätze ich mal :).

3

02.06.2010, 05:43

Das was du dort machst ist eine Abart von Observern. Generell müsste man erstmal wissen was für Objekte das sind. Beispielsweise ein SceneManager braucht theoretisch keine Mega Liste in der alle Objekte (Nodes) drin sind. Bei einem SceneManager setzt man besser auf eine art Tree. Deine Methode ähneld dieser sehr, jedoch würde ich nicht jedem Objekt die Map klasse als Member geben, sondern eher, dass die Objekt-Klasse von der Map Klasse erbt.

C-/C++-Quelltext

1
2
3
4
while(true)
{
    printf("Schon wieder aufgehangen!?");
}

4

02.06.2010, 12:54

Hey,
die Objekte wären in dem Fall Charaktere (spielbare, NPCs und Gegner).

Zitat von »Potatoman«

Bei einem SceneManager setzt man besser auf eine art Tree.
Ist std::map nicht eine Art Tree? Kannst du mir mal ein Beispiel nennen?

Zitat von »Potatoman«

jedoch würde ich nicht jedem Objekt die Map klasse als Member geben, sondern eher, dass die Objekt-Klasse von der Map Klasse erbt.
Klingt interessant.
Aber woher weiß die Objekt-Klasse welche Map-Instanz ich meine? Kannst du auch hier wieder ein Beispiel machen? :whistling:
stɪl traɪ tuː θɪŋk ˈpɒzətɪv

5

02.06.2010, 13:49

Die Objekt Klasse wird dann selbst zur Instanz. Optimal wäre es dann noch, wenn du die Methoden der Map-Klasse als virtual deklarierst, dadurch kann die Objekt, klasse, diese anpassen. Außerdem hast du durch die vererbung die möglichkeit, mehrere Verschiedene Objekt Klassen unter einem Hut zu verpacken.

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
class Map
{
public:
    virtual void Do()
    {
        // Lass alle Children auch was machen
        for(int i = 0; i < Children.GetLength(); ++i)
            Children[i]->Do();
    }

    virtual void Sleep()
    {
        Sleep(500);
    }

    virtual void AddChild(Map* child)
    {
        Children.Add(child);
    }

private:
    Array<Map*> Children;
};

// ObjektA erbt von Map
class ObjectA : public Map
{
public:
    void Do()
    {
        // Lass alle Children auch was machen
        for(int i = 0; i < Children.GetLength(); ++i)
                Children[i]->Do();
    }

    void Sleep()
    {
        Sleep(123445);
    }
};

// ObjektB erbt von Map
class ObjectB : public Map
{
public:
    void Do()
    {
        // Alle Children von ObjektB dürfen mal ne Pause machen.
    }

    void DoSomeOther()
    {
        // Mach was anderes
    }
};


Der Vorteil ist nun der, das man sich ein Child raus suchen kann, ihn was machen lassen kann, und automatisch deren Childs auch was machen. Ist natürlich nicht immer anwendbar, aber gerade bei NPCs und KI kann man soetwas (in verbindung mit Grafik) sehr gut einsetzen. Außerdem ist dort ein wenig Polymorphi (oh gott, hoofentlich hab ich das jetzt auch richtig geschrieben) dabei. Das ist genauso wie die polymorphi bei den alten araban, wo man 50 Frauen hatte. Hier kann nun eine Map Klasse viele andere Klassen representieren, solange diese von der Map Klasse erben. Du kannst nun alle klassen die davon erben, in einem Array Packen, und deren vorgegebenen Methoden aufrufen.

C-/C++-Quelltext

1
2
3
4
while(true)
{
    printf("Schon wieder aufgehangen!?");
}

idontknow

unregistriert

6

02.06.2010, 14:04

Wäre aber aus deisgner Sicht eine imo undenkbare Lößung weil ein Objekt ("is-a"-Beziehung!) keine Map ist!

7

02.06.2010, 14:08

Natürlich sollte man nen anderen Namen wählen ;)

C-/C++-Quelltext

1
2
3
4
while(true)
{
    printf("Schon wieder aufgehangen!?");
}

8

02.06.2010, 14:17

Hab ich so nicht unnötig viel Speicherverbrauch? Wenn in jedem Objekt ein Array mit allen (?) anderen Objekten ist.
stɪl traɪ tuː θɪŋk ˈpɒzətɪv

idontknow

unregistriert

9

02.06.2010, 14:25

Nein, da du soweiso Pointer verwenden solltest d.h. du hast ine Array dessen Größe ca. 4 Byyte * ArraySize ist ;)

10

02.06.2010, 14:59

Aber sonst bräuchte ich nur 4 bzw. 8 (wenn 64bit) Bytes für jedes Objekt. :D
Vorteil ist, soweit ich verstanden hab, dass ich die Objekte individuell interagieren lassen kann, stimmts?
Ich teste mal ein wenig damit rum.
stɪl traɪ tuː θɪŋk ˈpɒzətɪv

Werbeanzeige