Klasse-Eigenschaft greift auf Hauptklasse zu
-
Hallo
der Betreff ist etwas komisch, aber hoffentlich verständlich.
Falls nicht:
Ich habe gerade mit einem kleinem rundenbasiertem Strategiespiele alá "Schiffeversenken mit beweglichen Schiff" begonnen.
Das Spielfeld soll durch 2 Arrays/Vectors dargestellt werden, eins für das Gelände und eins für die Einheiten, was dann in etwa (gekürzt) so aussieht:class Unit { int health; int player; ... };
class Tile { int slow_down; bool is_passable; };
class Battlefield { public: vector<vector<Tile> > tile; vector<vector<Unit> > unit; Battlefield (int width, int height) //von [0][0] bis einschliesslich [width][height] { tile.resize (width); unit.resize (width); for (int i = 0; i < width; i++) { tile[i].resize(height); unit.resize (width); } } int unit_move (int x1, int y1, int x2, int y2); int unit_fire (int unit_x, unit_y, int target_x, int target_y); ... void show(); };
Ich denke, ich würde das so umsetzen können, allerdings habe ich zwei Fragen:
- das
int unit_move(int x1, y1, int x2, int y2);
gefällt mir nicht so wirklich, stattdessen würde ich gerne
unit[x][y].move_to (int x, int y);
schreiben können.
Aber dazu muss die Klasse Unit ja irgendwie auf die Klasse Battlefield zugreifen können, um zu erkennen ob der Weg evtl. versperrt oä. ist.
(Also sozusagen das "Gegenteil" von http://c-plusplus.net/forum/viewtopic.php?t=70028) Und da liegt mein Problem, da ich nichts finde wie man das hinbekommen soll bzw. ob es überhaupt möglich ist (?)- Ist
unit[x][y].move_to (int x, int y)
auch euer Meinung nach besser als
int unit_move(int x1, y1, int x2, int y2);
?
Oder ist das völlig egal?
-
sorry, eigentlich wollte ich unter "C++" posten, aber irgendwie waren noch andere Fenster auf und ich bin etwas vom rechten Pfad abgekommen
Wäre nett, wenn ein Mod den Thread verschieben könnte...
-
Hallo,
ich würde Deiner Unit eine Variable für ihre derzeitige Position hinzufügen. Dann weiß die Unit selbst, wo sie ist und Du brauchst ihr nur den Befehl geben sich nach (x,y) zu bewegen.
Wie sie den Weg dorthin berechnet, bleibt ihr überlassen.
Alle Units werden dann in einem Container gespeichert, so dass Du sagen kannst:unit[1].moveto(6,9)
Gruß,
MTE.
-
Alle Units werden dann in einem Container gespeichert
An dieese Möglichkeit habe ich auch schon gedacht und das Array/vector wäre auch nicht so gross (und grösstenteils leer) wie bei mir, aber ich dachte mir:
-wenn man wissen möchte, ob eine Unit an [x][y] steht kann man einfach Unit[x][y] abfragen und muss nicht das unit-array mit for (...) { unit[i] } durchgehen.
-Man spart sich die Überprüfung ob zwei Units vielleicht auf dem gleichen Feld sitzen.Es gibt ja dann auch immernoch das Problem, wie
unit[1].moveto(6,9)
erkennt, ob zB der Weg blockiert ist.
Eine Lösung wäre Battlefield als Parameter zu übergeben, aber das ist ja nicht so toll...
-
Nun, grundsätzlich ist ein Objekt aber selbst dafür verantwortlich, zu wissen, wo es ist und den Weg dorthin zu finden, wo es hinwill.
Aber Du solltest vielleicht sowieso noch ein Array mit den einzelnen Feldern Deines Battlefields haben. Da können die Units sich dann anmelden wenn sie das Feld besetzen. Du kannst dann die einzelnen Felder fragen, ob auf ihnen eine Unit sitzt.
Außerdem könnten die Units dann den Weg zu ihrem Ziel berechnen wenn Du ihnen eines gibst und dann bei jedem Feld, das auf dem Weg liegt (insofern sie unendliche Sichtweite haben) anfragen, ob dieses Feld belegt und somit der Weg versperrt ist und dann eine entsprechende Alternativroute berechnen.Gruß,
MTE.
-
Hi,
habe mir gerade mal Deinen Code oben genauer angesehen.
unit_move und unit_fire sollten auf jeden Fall Methoden der Klasse Unit sein und nicht der Klasse Battlefield. Das Battlefield ist ja nicht dafür verantwortlich, Units zu bewegen.
Deine Tile-Klasse braucht dann eine Abfragemethode, die zurückgibt, ob das Feld besetzt ist.Unit::calculate_route(int target_x, int target_y) { // hier route berechnen // dann für jedes tile auf dem Weg zum Ziel ausführen: if (tile[x,y].getBlocked) { // Alternativroute berechnen } }
So ungefähr würde ich mir das Vorstellen.
-
unit_move und unit_fire sollten auf jeden Fall Methoden der Klasse Unit sein und nicht der Klasse Battlefield. Das Battlefield ist ja nicht dafür verantwortlich, Units zu bewegen.
Der Meinung bin ich inzwischen auch, es hapert nur noch bei der Umsetzung.
Ein Array mit den Feldern des Battlefields habe ich ja schon als Eigenschaft des Battlefields:
vector<vector<Tile> > tile;
Da können die Units sich dann anmelden wenn sie das Feld besetzen. Du kannst dann die einzelnen Felder fragen, ob auf ihnen eine Unit sitzt.
Das ist gut, dann spart man sich das Durchgehen des Unit-vectors.
Unit::calculate_route(int target_x, int target_y) { // hier route berechnen // dann für jedes tile auf dem Weg zum Ziel ausführen: if (tile[x,y].getBlocked) { // Alternativroute berechnen } }
Das ist soweit schon klar.
Aber nach Version 1 ist der Unit-vector ja eine Eigentschaft vom Battlefield und nach
Version 2 gibt es ein Battlefield und ein davon getrenntes Unit-vector.Auf jeden Fall muss der Unit aber das Battlefield auf dem sie sich bewegt ja irgendwie bekannt sein, sonst kann die Unit ja auch gar nicht sehen, ob zB das Feld vor ihr versperrt oder frei ist.
Das einzige was mir einfällt sind:
-ein globales Battlefield ()
-das Battlefield jedes Mal als Parameter mit übergeben, also:Unit::move_to(int target_x, int target_y, Battlefield battlefield)
Sprich, wie erlaube ich es
Battlefield.unit[i].move_to (int target_x, int target_y);
auf
Battlefield.tile[x][y]
zuzugreifen?
-
Tja, zu den Details kann ich Dir jetzt im Moment leider auch nicht weiterhelfen. Ich sitzte aber gerade bei der Planung für eine ganz ähnlich gelagerte Sache (rundenbasierte Weltraumstrategie).
Vielleicht kann ich in ein paar Tagen mal meine Lösung (bzw. die bei mir auftretenden Probleme posten). Kann sich allerdings noch etwas hinziehen.
In einer früheren Fassung des Programms, in der ich nur ein bißchen rumexperimentiert habe, habe ich es tatsächlich so gemacht, dass ich jedem Schiff bei der Erstellung einen Zeiger auf die Galaxis mitgegeben habe, so dass es bei Bewegungen die Methode
galaxy->ship_enters_sector(x,y,ship)
aufrufen konnte. Bzw. eigentlich war noch eine Klasse ShipManagement dazwischen, die die Verwaltung aller Schiffe übernommen hat.
So ganz ausgereift war das aber alles noch nicht.Gruß,
MTE.
-
Gibt es da wirklich keine andere Möglichkeit?
Jedenfalls schonmal vielen Dank für deine Antworten.
Es würde mich jetzt auch "einfach so" mal interessieren, ob das überhaupt möglich ist...
-
Hallo Münzbieger,
spontan würde ich für deine Battlefieldklasse eine Singletonklasse verwenden, vorrausgesetzt, deine Battlefieldinstanz existiert nur ein einziges mal.
Wenn du daraus eine Singletonklasse gemacht hast, musst du die Headerdatei der "Battlefieldsingletonklasse" in die unit.h (wenn die Datei bei dir so heißt) einbinden und kannst sie in der Unit.cpp / Unit.h verwenden.
Ich weiß jetzt nicht, wie du dein Code in Dateien aufgeteilt hast, deswegen ist dieser Tipp mit Vorsicht zu genießen.
Ich hoffe, ich konnte (ein bißchen) helfen.