| Autor |
Beitrag |
kai_lamers
      
Beiträge: 24
|
Verfasst: Mi 08.10.08 12:01
Hallo liebe Leute,
ich bin grad dabei für die Schule ein kleines Strategiespiel in 2d (Iso Darstellung) zu schreiben, Grafikmäßig ist alles soweit erstmal alles kein Problem und läuft, nun wollte ich jedoch, bevor ich anfange die Spiellogik zu implementieren einfach mal nachfragen, ob ihr Schwachpunkte in der Vorgehensweise findet oder wie ihr es machen würdet.
Es geht in diesem Thema erstmal nur um die Gebäude, später werde ich wohl sicherlich auch noch andere Fragen stellen
Also mein grundlegender Gedanke war:
Es gibt eine Klasse TBuilding, die folgende Eigenschaften besitzt:
X,Y : Positionierung auf der Weltkarte
getreide,stein,metall: Variablen für Baukosten
entwicklungsstufe:integer
Eine geerbte Klasse sähe dann etwa so aus
TMuehle = Class (TBuilding)
Es gibt folgende Prozeduren und Eigenschaften:
property ertraggetreide, etraggestein, ertragmetall: Werte, die in Abhängigkeit der Entwicklungsstufe angeben, welche Ressourcen die Mühle erzeugt
property produktionszeit: Anzahl der Zeiteinheiten, bis die Werte (ertraggetreide, ertraggestein,ertragmetall) dem Spielerkonto zugefügt werden.
Prozedur entwickeln: Setzt die Gebäudestufe eins nach oben
Die Klassen sind jetzt nur grob skizziert, genauere Ausarbeitung habe ich noch nicht durchgeführt
Dieser Ansatz wirkt auf mich aber bei näherer Betrachtung ziemlich unklug, da ich das Gefühl habe, dass ich später ziemlich eingeschränkt sein werde.
Wie geht man also in solche einem Fall klugerweise vor?
Danke schonmal,
Kai
Einloggen, um Attachments anzusehen!
Zuletzt bearbeitet von kai_lamers am Fr 10.10.08 22:14, insgesamt 2-mal bearbeitet
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 08.10.08 12:23
Grundsätzlich ist das schon eine mE nach gute Vorgehensweise, du müsstest halt schauen, dass du so viel wie möglich "standardisierst" und in die Oberklasse packst, ich habe dann auch teilweise, wenn es um eine Darstellung ging diese wiederum auch gekapselt, so dass die Grundmethoden davon auch in einer Oberklasse als Eigenschaft deiner Oberklasse stehen.
Also so in der Art: Delphi-Quelltext 1:
| Game.ObjectManager.Object[i].PropertyManager.ShowProperties; | ShowProperties wäre dann überschrieben durch den passenden PropertyManager und würde im Spiel eine entsprechende Anzeige aufbauen, deren benötigte Größe du wiederum standardisiert abfragen könntest, etc.
Die Frage ist immer, wo sich so etwas lohnt. Wenn du ohnehin auch von der Spiellogik her sehr viel mit den speziellen Gebäuden machst, dann lohnt sich das nicht so sehr, weil du ohnehin nach Typ unterscheiden musst. Wenn aber außer (z.B. regelmäßig angestoßenen) objektinternen Berechnungen der Typ in der Spiellogik keine große Rolle spielt, dann lohnt sich das, weil du dich um den Typ selbst bei der Darstellung und ggf. Einstellung von Parametern nicht um den Typ kümmern musst. Das Eintragen in ein Einstellungsinterface o.ä. könnte wie die Darstellung der Parameter der entsprechende typbezogene PropertyManager übernehmen.
Das würde dann so aussehen, dass du deinem Objektmanager sagst, welchen Typ er erzeugen soll, der tut das, dann wird z.B. eine Mühle erzeugt und diese erstellt sich den passenden PropertyManager dazu und packt den in die geerbte allgemeine Property. Mir hat es Spaß gemacht mit derartigen Konstrukten herumzuspielen und hatte dann performanten aber auch einfach zu ändernden Code. Den Überblick zu behalten ist aber nicht ganz einfach, deshalb musst du aufpassen, dass du deinen Quelltext gut kommentierst, vor allem im Hinblick darauf was wo erzeugt wird und was von anderer Stelle her vorausgesetzt wird. (Eben zum Beispiel, dass die spezielle Klasse sich auch einen eigenen PropertyManager erstellt, und das bei einem neuen Typ nicht vergessen wird.)
Ob das eine wirklich gute Vorgehensweise ist, kann ich nicht so gut beurteilen, da ich selbst eher durch Ausprobieren denn durch Lehrer gelernt habe. 
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Mi 08.10.08 14:52
Hi,
- Gibt es denn viele Gebäude, die mehrere Sachen erzeugen? Ich würde davon eine Klasse ableiten, die zwei Eigenschaft hat: Produkt, Menge. Davon überschreibst du dann die Methode zum Erzeugen von Rohstoffen so, dass du beim Ableiten nurnoch den Rohstoff und die Menge angeben musst.
Generell: Wenn du etwas häufige brauchen könntest, ruhig nochmal eine Zwischenstufe machen
- Eine weitere Klasse davon ableiten, die eine Ereignismethode OnProduction hat. Damit ließen sich dann auch Sachen wie eine Werft(da muss ja ein Schiff raus, dann. Also noch etwas passieren) oder im Extremfall ein Kanonenturm(Kugel Abfeuern, bräuchte allerdings eine schnelle "Produktionsfolge"
) realisieren.
Eigentlich bist du mit dem objektorientierten Ansatz schon ganz richtig(hättest du nciht gedacht, was?^^). Es lassen sich ja jederzeit besondere Ereingnisse einbauen. An welcher Stelle vermutest du denn, dass dich der Ansatz blockieren könnte?
mfG,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Mi 08.10.08 14:53
Hey,
danke schonmal - die Idee mit dem Objekt Manager ist sehr gut, sodass man von einer zentralisierten Klasse Zugriff auf alle Objekte hat - das werde ich auf jeden Fall implementieren!
Danke schonmal
"Viele Gebäude" ist natürlich relativ. Ich wollte die typischen Anlagen übernehmen: Wohnhaus, Mühle-->Feld, Werft, Kaserne, Waffenschmiede, Steinbruch, Metallabbaustätte, Kirche, Hafen, Markt,Wall,Kanonenturm,Tor... Ich denke grob waren das alle.
Aber grob muss es erstmal mit einem Gebäude logisch richtig funktionieren, weitere zu implementieren sollte kein Problem darstellen, wenn die Mutterklasse entsprechend ordentlich gestaltet ist.
An welcher Stelle genau dieser Ansatz für mich etwas zu "simpel" scheint, kann ich gar nicht sagen.
Es war eben der erste Ansatz und ich weiß erfahrungsgemäß von mir, dass mein erster Ansatz im Bereich der OOP IMMER grundsätzliche Fehler enthält, das ist quasi ein Naturgesetz *g*
EDIT:
Hier ist dann mal die erste Version meiner Klassen, ist nicht ganz so, wie oben beschrieben, aber auf mich macht das jetzt erstmal einen relativ guten Eindruck, getestet ist das ganze noch nicht. Habs grad eben erstmal runtergetippt.
Praktisch an dieser Vorgehensweise ist es, dass man absolut flexibel bleibt bezüglich der Gebäude bleibt, da alle Gebäude über eine externe (noch unverschlüsselte) Textdatei eingelesen werden
Neues Gebäude = Neue Zeile in Datei, schon ist das Gebäude verfügbar.
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: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195:
| unit Uobject;
interface
Uses SysUtils,Classes;
type TSTringdynarray = array of String;
type Tpropertylist=Record name:string; building_id:integer; tile_id:integer; need_oat:integer; need_stone:integer; need_metal:integer; produce_oat:integer; produce_stone:integer; produce_metal:integer; produce_oat_time:integer; produce_stone_time:integer; produce_metal_time:integer; end;
type TPropertymanager=Class(Tobject) private props:Tpropertylist;
public constructor create(building_file:string;building_typ:integer); property properties:Tpropertylist read props; end;
TBuilding=Class(Tobject) private prope_manager:Tpropertymanager; xcoord:integer; ycoord:integer; b_typ:integer; b_level:integer; b_status:integer; procedure setx(x:integer); procedure sety(y:integer); procedure settyp(typ:integer); procedure setlevel(level:integer); procedure setstatus(status:integer); public constructor create(building_typ:integer); property x:integer read xcoord write setx; property y:integer read ycoord write sety; property typ:integer read b_typ write settyp; property level:integer read b_level write setlevel; property status:integer read b_status write setstatus; property prop_manager:Tpropertymanager read prope_manager; procedure develop; end;
TObjectmanager=Class(TObject) private object_id:integer; object_array:array[0..2500] of Tbuilding; protected function getbuilding(Index: Integer): Tbuilding; public constructor create; function build(typ:integer;x,y:integer;stufe:integer):integer; property objects[Index: Integer]: Tbuilding read getbuilding ; default; end;
implementation
function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray; var SepLen: Integer; F, P: PChar; ALen, Index: Integer; begin SetLength(Result, 0); if (S = '') or (Limit < 0) then Exit; if Separator = '' then begin SetLength(Result, 1); Result[0] := S; Exit; end; SepLen := Length(Separator); ALen := Limit; SetLength(Result, ALen);
Index := 0; P := PChar(S); while P^ <> #0 do begin F := P; P := AnsiStrPos(P, PChar(Separator)); if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F); if Index >= ALen then begin Inc(ALen, 5); SetLength(Result, ALen); end; SetString(Result[Index], F, P - F); Inc(Index); if P^ <> #0 then Inc(P, SepLen); end; if Index < ALen then SetLength(Result, Index); end;
constructor Tpropertymanager.create(building_file:string;building_typ:integer); var b_file:textfile; var line:string; var res:TSTringdynarray; begin AssignFile(b_file,building_file); Reset(b_file); while not eof (b_file) do begin readln(b_file,line); res:=Explode(',',line,0); props.name:=res[0]; props.building_id:=strtoint(res[1]); props.tile_id:=strtoint(res[2]); props.need_oat:=strtoint(res[3]); props.need_stone:=strtoint(res[4]); props.need_metal:=strtoint(res[5]); props.produce_oat:=strtoint(res[6]); props.produce_stone:=strtoint(res[7]); props.produce_metal:=strtoint(res[8]); props.produce_oat_time:=strtoint(res[9]); props.produce_stone_time:=strtoint(res[10]); props.produce_metal_time:=strtoint(res[11]); if building_typ=props.building_id then break; end; end;
constructor Tbuilding.create(building_typ:integer); begin inherited create; prope_manager:=Tpropertymanager.create('building.txt',building_typ); end;
function Tobjectmanager.getbuilding(Index: Integer): Tbuilding; begin Result := object_array[Index]; end;
procedure Tbuilding.develop(); begin inc(b_level); end;
procedure Tbuilding.setx(x:integer); begin xcoord:=x; end;
procedure Tbuilding.sety(y:integer); begin ycoord:=y; end;
procedure Tbuilding.settyp(typ:integer); begin b_typ:=typ; end;
procedure Tbuilding.setlevel(level:integer); begin b_level:=level; end;
procedure Tbuilding.setstatus(status:integer); begin b_status:=status; end;
constructor Tobjectmanager.create(); begin object_id:=0; end;
function Tobjectmanager.build(typ:integer;x,y:integer;stufe:integer):integer; begin object_array[object_id]:=TBuilding.create(typ); object_array[object_id].typ:=typ; object_array[object_id].x:=x; object_array[object_id].y:=y; object_array[object_id].level:=stufe; result:=object_id; inc(object_id); end;
end. |
Building.txt:
Quelltext 1: 2:
| Muehle,1,16,10,10,10,5,0,0,20,0,0 Bauernhaus,2,17,20,15,10,0,0,0,0,0,0 |
EDIT 2:
Ich glaube es ja kaum, aber die oben abgebildeten Klassen tun tatsächlich alles so, wie ich es mir gewünscht habe und das ziemlich auf Anhieb
Wenn ihr mir jetzt noch sagt, dass ihr den obigen Ansatz auch noch als sinnvoll erachtet, dann bin ich froh und sehe mein Grundgerüst als geebnet an!
Ich bekam grad eine PN, ob ich zwischendurch mal einen Zwischenstand hochladen kann:
Tu ich gerne und mache ich auch. Es wird zwar kein Age of Empires, aber ein niedliches kleines Spielchen wirds schon werden, ist halt für die Schule
ANBEI DIE ERSTE VERSION ONLINE:
Bisher kann man nur Mühlen bauen, ich weiß noch nicht, wie ich das Gamehandling an sich gestalten werde, es ist aber ja auch erstmal nur eine Testversion. Sämtliche Klasse sind bereits implementiert und funktionieren, überzeugt euch selbst.
Die Building.txt muss im gleichen Ordner wie das Programm an sich sein.
Lg,
Kai
Einloggen, um Attachments anzusehen!
Zuletzt bearbeitet von kai_lamers am Do 09.10.08 13:20, insgesamt 2-mal bearbeitet
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Do 09.10.08 12:19
Hey,
heute geht es dann weiter. Nachdem ich die Gebäudelogik nun implementiert habe, bin ich grad noch recht unschlüssig, womit ich am besten weiter mache.
Wo würdet ihr weitergehend ansetzen?
Danke und lieben Gruß,
Kai
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Do 09.10.08 12:31
in der einheitenproduktion würd ich weitermachen, falls es sowas gibt. aber bis jetzt hast du nur geschrieben da es ein strategiespeil sein soll, nicht was für eins! ein friedliches a la Siedler oder ein kriegerisches a la Cossacks.
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Do 09.10.08 12:50
Stimmt, du hast Recht - das sollte ich auf jeden Fall noch ergänzen.
Erstmal soll es nur ein friedliches Strategiespiel werden, welches noch ohne Gegner und Kriege auskommt, einfach - weil ich mich vor der Entwicklung einer entsprechenden KI fürchte.
Allerdings möchte ich das ganze so offen halten, dass ich im Nachhinein immer noch Gegnerklassen ein bauen kann.
Ich habe mich gerade an die Entwicklung der Gamehandling Klasse gemacht, denn ohne die kann ich noch so viel programmieren, wenn ich es nicht anwählen kann, ist's doof.
Beispiel das Ressourcenfeld (grad noch in Entwicklung):
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:
| TRessourcewindow=Class(TObject) private b_posx:integer; b_posy:integer; b_width:integer; b_height:integer; b_visible:Boolean; protected procedure setvisible(vis:Boolean); public procedure draw(canvas:TDirectDrawSurfaceCanvas); constructor create(x,y,width,height:integer;visible:boolean); property visible:Boolean read b_visible write setvisible; procedure setpos(posx,posy:integer); end;
constructor TRessourcewindow.create(x:integer;y:integer;width:integer;height:integer;visible:boolean); begin b_posx:=x; b_posy:=y; b_width:=width; b_height:=height; b_visible:=visible; end;
procedure TRessourcewindow.setpos(posx:Integer;posy:integer); begin b_posx:=posx; b_posy:=posy; end;
procedure TRessourcewindow.draw(canvas:TDirectDrawSurfaceCanvas); begin if b_visible then begin canvas.Brush.Color:=clred; canvas.Rectangle(b_posx,b_posy,b_posx+b_width,b_posy+b_height); canvas.release; end; end;
procedure TRessourcewindow.setvisible(vis:Boolean); begin b_visible:=vis; end; |
Lg,
Kai
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 09.10.08 12:51
Du hast beim Zugriff auf die building.txt vergessen den Pfad hinzuzufügen (ExtractFilePath(ParamStr(0)) + 'building.txt'). Als ich zuerst aus dem Browser direkt gestartet habe (der Download ging ja in den selben Ordner) kam beim Klick die Meldung "Datei nicht gefunden". Deshalb musste ich es aus dem Windows Explorer starten, wo dann das Arbeitsverzeichnis zufälligerweise dem Anwendungsverzeichnis entspricht.
www.delphi-library.d...ewtopic.php?p=499701
Ja, du musst dir dann überlegen was im Spiel passieren soll, und dementsprechend weitermachen. Die bereits benannte Einheitenproduktion ist eine Möglichkeit, du kannst auch erstmal allgemein schauen wie denn eigentlich mit Produkten umgegangen wird. Irgendwie musst du ja in Zyklen die Produktion bei allen Gebäuden "abholen" und in deine Gesamtressourcen einbinden, etc.
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Do 09.10.08 13:03
Hi,
Das oben könntest du noch etwas kompakter machen, indem du Einen Unterrecord TRecources definierst, der oat, stone, metal: Integer enthält. Der andere Record vereinfacht sich dann zu Produce, Need, Time: TRecources.
Damit wird das ganze nicht nur schneller zu Tippen(du wirst diese Dreierrecourcen sicher noch etliche Male verwenden, also kannst du es auch gleich zusammenfassen). Der Hauptgrund ist, dass du und andere schneller durch den Quelltext finden, wenn er übersichtlicher und kürzer wird.
@Elundriel: Stimme ich zu. Als erstes mal die Hauptprocedure, in der das Spiel läuft(und sei es nun in einem Timer oder in eir Schleife). Damit auch wahrscheinlich eine Unterprocedure(schön viele davon, damit's übersichtlich wird  ) mit "for Buildings do Produce;" oder in der Art.
Wenn du die oberen Prozeduren in schön viele Unterprozeduren unterteilst, kommst du schonmal schneller voran: Du umschreibst den Programmablauf, ohne dich mit Details aufzuhalten. Außerdem ist alles für jemanden, der sich einliest, wie Pseudocode lesbar
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:
| procedure TGameForm.GameStepTimer(Sender: TObject); begin Game.Tick; end;
procedure TGame.Tick; begin CalcRecources; CalcDamage; InformPlayer; end;
procedure TGame.CalcRecources; var i: Integer; begin for i := 0 to Length(Buildings) - 1 do Building[i].CalcRecources(Player.Recources); end;
procedure TBuilding.CalcRecources(aPlayerRecources: TRecources); begin DecRec(self.ProduceTime, 1); if BiggerThan(aPlayerRecources, self.Need) then IncRec(aPlayerRecources, self.Produce, self.Need); end;
function BiggerThan(A, B: TRecources): Boolean; begin result := (A.Oat >= B.Oat) and (A.Stone >= B.Stone) and (A.Metal >= B.Metal); end; |
mfG,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Do 09.10.08 13:19
Hey,
danke die Sache mit dem Dateipfad ist korrigiert, die Idee zum neuen Record finde ich super, danke! Auch schon eingefügt und ich werde jetzt mal eine entsprechende Hauptroutine fertigen, das scheint mir auch sinnvoll.
Echt vielen Dank für Eure Anregungen, mit solchen Ideen von anderen macht es das ganze viel realisierbarer
Liebe Grüße,
Kai
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Do 09.10.08 19:00
Hey,
wow - ich freu mir hier grad ein Ast ab - weswegen: Meine Gebäude können nun endlich produzieren, es ist echt erstaunlich, wie man sich über so eine doofe Änderung von Zahlen freuen kann
Aber ich kann inzwischen auch jedem nur solch einen Objektorientieren Ansatz empfehlen. Es ist zwar eine Menge Mehrarbeit bis zum ersten sichtbaren Erfolg, doch wenn man dann einmal soweit ist, dass das Grundgerüst steht, dann funktioniert auch alles.
Anbei meine aktuelle Klassenunit:
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: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527:
| unit Uobject;
interface
Uses SysUtils,Classes,Graphics,DXDraws;
type TSTringdynarray = array of String;
type
Tressources=Class(TObject) private b_oat:integer; b_stone:integer; b_metal:integer; procedure setoat(o:integer); procedure setstone(s:integer); procedure setmetal(m:integer); public property oat:integer read b_oat write setoat; property stone:integer read b_stone write setstone; property metal:integer read b_metal write setmetal; end;
Tpropertylist=Class(TObject) private b_name:string; b_building_id:integer; b_tile_id:integer; b_need:Tressources; b_produce:Tressources; b_produce_time:TRessources; b_make_inhabitants:integer; b_max_level:integer; b_life_points:integer; b_time:Tressources; procedure setname(n:string); procedure setbuilding_id(b:integer); procedure settile_id(ti:integer); procedure setneed(ne:Tressources); procedure setproduce(pro:Tressources); procedure setproduce_time(prot:Tressources); procedure setmake_inhabitants(mi:integer); procedure setmax_level(ml:integer); procedure setlife_points(lp:integer); procedure settime(t:Tressources); public constructor create; property name:string read b_name write setname; property building_id:integer read b_building_id write setbuilding_id; property tile_id:integer read b_tile_id write settile_id; property need:Tressources read b_need write setneed; property produce:Tressources read b_produce write setproduce; property produce_time:TRessources read b_produce_time write setproduce_time; property make_inhabitants:integer read b_make_inhabitants write setmake_inhabitants; property max_level:integer read b_max_level write setmax_level; property life_points:integer read b_life_points write setlife_points; property time:Tressources read b_time write settime; end;
Tspieler=Class(TObject) private b_res:Tressources; b_inhabitants:integer; b_century:integer; procedure setressources(res:Tressources); procedure setinhabitants(inhab:integer); procedure setcentury(centu:integer); public constructor create(oat,stone,metal,inhabitants,century:integer); property ressources:Tressources read b_res write setressources; property inhabitants:integer read b_inhabitants write setinhabitants; property century:integer read b_century write setcentury; end;
TMessagewindow=Class(TObject) private b_posx:integer; b_posy:integer; b_width:integer; b_height:integer; b_visible:Boolean; b_text:string; protected procedure setvisible(vis:Boolean); procedure settext(tex:string); public procedure draw(canvas:TDirectDrawSurfaceCanvas); constructor create(x,y,width,height:integer;visible:boolean); property visible:Boolean read b_visible write setvisible; procedure setpos(posx,posy:integer); property text:string read b_text write settext; end;
TPropertymanager=Class(Tobject) private props:Tpropertylist; procedure setprops(prop:Tpropertylist); public constructor create(building_file:string;building_typ:integer); property properties:Tpropertylist read props write setprops; end;
TBuilding=Class(Tobject) private prope_manager:Tpropertymanager; xcoord:integer; ycoord:integer; b_typ:integer; b_level:integer; b_status:integer; procedure setx(x:integer); procedure sety(y:integer); procedure settyp(typ:integer); procedure setlevel(level:integer); procedure setstatus(status:integer); procedure setpropmanager(propmanager:Tpropertymanager); public constructor create(building_typ:integer); property x:integer read xcoord write setx; property y:integer read ycoord write sety; property typ:integer read b_typ write settyp; property level:integer read b_level write setlevel; property status:integer read b_status write setstatus; property prop_manager:Tpropertymanager read prope_manager write setpropmanager; procedure develop; end;
TObjectmanager=Class(TObject) private object_id:integer; object_array:array[0..2500] of Tbuilding; protected function getbuilding(Index: Integer): Tbuilding; procedure putbuilding(Index: Integer; build:Tbuilding); public constructor create; function build(typ:integer;x,y:integer;stufe:integer):integer; function search(x,y:integer):integer; property objects[Index: Integer]: Tbuilding read getbuilding write putbuilding; default; property max_id:integer read object_id; end;
TGame=Class(TObject) private b_objectmanager:Tobjectmanager; b_reswindow:TMessagewindow; b_eventwindow:TMessagewindow; b_spieler:Tspieler; procedure inctime(res:Tressources); procedure setobjectmanager(om:Tobjectmanager); public constructor create(); procedure calcressources; procedure tick; procedure informplayer; property Objectmanager : TObjectmanager read b_objectmanager write setobjectmanager; property reswindow : TMessagewindow read b_reswindow; property eventwindow : TMessageWindow read b_eventwindow; property spieler : TSpieler read b_spieler; end;
implementation
function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray; var SepLen: Integer; F, P: PChar; ALen, Index: Integer; begin SetLength(Result, 0); if (S = '') or (Limit < 0) then Exit; if Separator = '' then begin SetLength(Result, 1); Result[0] := S; Exit; end; SepLen := Length(Separator); ALen := Limit; SetLength(Result, ALen);
Index := 0; P := PChar(S); while P^ <> #0 do begin F := P; P := AnsiStrPos(P, PChar(Separator)); if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F); if Index >= ALen then begin Inc(ALen, 5); SetLength(Result, ALen); end; SetString(Result[Index], F, P - F); Inc(Index); if P^ <> #0 then Inc(P, SepLen); end; if Index < ALen then SetLength(Result, Index); end;
procedure Tressources.setoat(o:integer); begin b_oat:=o; end;
procedure Tressources.setstone(s:integer); begin b_stone:=s; end;
procedure Tressources.setmetal(m:integer); begin b_metal:=m; end;
constructor Tpropertylist.create(); begin b_need:=Tressources.create; b_produce:=Tressources.create; b_produce_time:=Tressources.create; b_time:=Tressources.create; end;
procedure Tpropertylist.setname(n:string); begin b_name:=n; end;
procedure Tpropertylist.setbuilding_id(b:integer); begin b_building_id:=b; end;
procedure Tpropertylist.settile_id(ti:integer); begin b_tile_id:=ti; end;
procedure Tpropertylist.setneed(ne:Tressources); begin b_need:=ne; end;
procedure Tpropertylist.setproduce(pro:Tressources); begin b_produce:=pro; end;
procedure Tpropertylist.setproduce_time(prot:Tressources); begin b_produce_time:=prot; end;
procedure Tpropertylist.setmake_inhabitants(mi:integer); begin b_make_inhabitants:=mi; end;
procedure Tpropertylist.setmax_level(ml:integer); begin b_max_level:=ml; end;
procedure Tpropertylist.setlife_points(lp:integer); begin b_life_points:=lp; end;
procedure Tpropertylist.settime(t:Tressources); begin b_time:=t; end;
constructor Tspieler.create(oat,stone,metal,inhabitants,century:integer); begin b_res:=Tressources.Create; b_res.oat:=oat; b_res.stone:=stone; b_res.metal:=metal; b_inhabitants:=inhabitants; b_century:=century; end;
procedure Tspieler.setressources(res:Tressources); begin b_res:=res; end;
procedure Tspieler.setinhabitants(inhab:integer); begin b_inhabitants:=inhab; end;
procedure Tspieler.setcentury(centu:integer); begin b_century:=centu; end;
constructor TMessagewindow.create(x:integer;y:integer;width:integer;height:integer;visible:boolean); begin b_posx:=x; b_posy:=y; b_width:=width; b_height:=height; b_visible:=visible; end;
procedure TMessagewindow.setpos(posx:Integer;posy:integer); begin b_posx:=posx; b_posy:=posy; end;
procedure TMessagewindow.draw(canvas:TDirectDrawSurfaceCanvas); begin if b_visible then begin canvas.Brush.Color:=clred; canvas.Font.Color:=clblack; canvas.Rectangle(b_posx,b_posy,b_posx+b_width,b_posy+b_height); canvas.TextOut(b_posx+1,b_posy+1,b_text); canvas.release; end; end;
procedure TMessagewindow.setvisible(vis:Boolean); begin b_visible:=vis; end;
procedure TMessagewindow.settext(tex:string); begin b_text:=tex; end;
constructor Tpropertymanager.create(building_file:string;building_typ:integer); var b_file:textfile; var line:string; var res:TSTringdynarray; begin props:=Tpropertylist.Create; AssignFile(b_file,ExtractFilePath(ParamStr(0)) + building_file); Reset(b_file); while not eof (b_file) do begin readln(b_file,line); res:=Explode(',',line,0); props.name:=res[0]; props.building_id:=strtoint(res[1]); props.tile_id:=strtoint(res[2]); props.need.oat:=strtoint(res[3]); props.need.stone:=strtoint(res[4]); props.need.metal:=strtoint(res[5]); props.produce.oat:=strtoint(res[6]); props.produce.stone:=strtoint(res[7]); props.produce.metal:=strtoint(res[8]); props.produce_time.oat:=strtoint(res[9]); props.produce_time.stone:=strtoint(res[10]); props.produce_time.metal:=strtoint(res[11]); props.make_inhabitants:=strtoint(res[12]); props.max_level:=strtoint(res[13]); props.life_points:=strtoint(res[14]); if building_typ=props.building_id then break; end; end;
procedure Tpropertymanager.setprops(prop:Tpropertylist); begin props:=prop; end;
constructor Tbuilding.create(building_typ:integer); begin inherited create; prope_manager:=Tpropertymanager.create('building.txt',building_typ); end;
procedure Tbuilding.setpropmanager(propmanager:Tpropertymanager); begin prope_manager:=propmanager; end;
procedure Tbuilding.develop(); begin inc(b_level); end;
procedure Tbuilding.setx(x:integer); begin xcoord:=x; end;
procedure Tbuilding.sety(y:integer); begin ycoord:=y; end;
procedure Tbuilding.settyp(typ:integer); begin b_typ:=typ; end;
procedure Tbuilding.setlevel(level:integer); begin b_level:=level; end;
procedure Tbuilding.setstatus(status:integer); begin b_status:=status; end;
constructor Tobjectmanager.create(); begin object_id:=0; end;
function Tobjectmanager.search(x:integer;y:integer):integer; var i:integer; begin if object_id>0 then begin for i:=0 to object_id-1 do begin if (object_array[i].x=x) and (object_array[i].y=y) then begin result:=i; break; end; result:=-1; end; end else result:=-1; end;
function Tobjectmanager.getbuilding(Index: Integer): Tbuilding; begin result:=nil; if object_id > 0 then Result := object_array[Index]; end;
procedure Tobjectmanager.putbuilding(Index: Integer; build:Tbuilding); begin if object_id > 0 then object_array[Index] := build; end;
function Tobjectmanager.build(typ:integer;x,y:integer;stufe:integer):integer; begin object_array[object_id]:=TBuilding.create(typ); object_array[object_id].typ:=typ; object_array[object_id].x:=x; object_array[object_id].y:=y; object_array[object_id].level:=stufe; result:=object_id; inc(object_id); end;
constructor Tgame.create; begin b_objectmanager:=Tobjectmanager.create; b_reswindow:=TMessagewindow.create(0,0,250,15,true); b_eventwindow:=TMessagewindow.create(0,500,768,150,true); b_spieler:=Tspieler.create(100,100,100,10,1); b_reswindow.text:=' Getreide: '+inttostr(b_spieler.ressources.oat)+' Stein: '+inttostr(b_spieler.ressources.stone)+' Metall: '+inttostr(b_spieler.ressources.metal);end;
procedure Tgame.setobjectmanager(om:Tobjectmanager); begin b_objectmanager:=om; end;
procedure Tgame.tick; begin calcressources; b_reswindow.text:=' Getreide: '+inttostr(b_spieler.ressources.oat)+' Stein: '+inttostr(b_spieler.ressources.stone)+' Metall: '+inttostr(b_spieler.ressources.metal); informplayer; end;
procedure Tgame.calcressources; var i,x:integer; begin for i:=0 to b_objectmanager.max_id-1 do begin inctime(b_objectmanager.objects[i].prop_manager.properties.time); if b_objectmanager.objects[i].prop_manager.properties.time.oat>=b_objectmanager.objects[i].prop_manager.properties.produce_time.oat then begin b_spieler.ressources.oat:=b_spieler.ressources.oat+b_objectmanager.objects[i].prop_manager.properties.produce.oat; b_objectmanager.objects[i].prop_manager.properties.time.oat:=0; end; if b_objectmanager.objects[i].prop_manager.properties.time.stone>=b_objectmanager.objects[i].prop_manager.properties.produce_time.stone then begin b_spieler.ressources.stone:=b_spieler.ressources.stone+b_objectmanager.objects[i].prop_manager.properties.produce.stone; b_objectmanager.objects[i].prop_manager.properties.time.stone:=0; end; if b_objectmanager.objects[i].prop_manager.properties.time.metal>=b_objectmanager.objects[i].prop_manager.properties.produce_time.metal then begin b_spieler.ressources.metal:=b_spieler.ressources.metal+b_objectmanager.objects[i].prop_manager.properties.produce.metal; b_objectmanager.objects[i].prop_manager.properties.time.metal:=0; end; end; end;
procedure Tgame.inctime(res:Tressources); begin res.oat:=res.oat+1; res.stone:=res.stone+1; res.metal:=res.metal+1; end;
procedure Tgame.informplayer; begin end;
end. |
Ich habe deinen Vorschlag, hidden, ziemlich genau so umgesetzt.
So, nun ist erstmal 'ne kleine Pause angesagt, heute kann ich mich nicht mehr konzentrieren.
Anbei wieder die aktuelle Engine.
DIE OBEN ZU DOWNLOADENDE BUILDING.TXT MUSS WIEDER DABEI SEIN!
Lg,
Kai
Einloggen, um Attachments anzusehen!
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Do 09.10.08 19:03
schaut schon mal nicht schlecht aus! jedoch sollte die steuerung dann irgendwann noch angepasst werden.
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Do 09.10.08 19:16
Der Steuerung wollte ich mich als nächstes widmen, denn die tollsten Features bringen nix, wenn man sie durch die bisher nicht ausreichende Steuerung hervorrufen kann.
Das kommt dann morgen - noch sind ja Ferien.
Lg,
Kai
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Do 09.10.08 19:49
Hi,
kai_lamers hat folgendes geschrieben : | | Ich habe deinen Vorschlag, hidden, ziemlich genau so umgesetzt. |
Freut mich, wenn ich helfen konnte
| Zitat: | | object_array:array[0..2500] of Tbuilding; |
Es gibt übrigens auch dynamisch Arrays. Das sind dann im Speicher zwar keine richtigen Arrays mehr, aber du kannst nach wie vor so mit ihnen arbeiten, als wären es welche: Delphi-Quelltext 1: 2: 3: 4:
| ObjectArray: Array of TBuilding; SetLength(ObjectArray, 5); Length(ObjectArray); |
Was mir noch auffällt: Du müsstest Objekte, die du selbst erzeugst auch wieder freigeben, sobald du sie nichtmehr brauchst. Das geschieht über den Aufruf von "Free;". Wenn bei der Freigabe eines Objektes noch mehr freigegeben werden soll(dein TPropertyList-Objekt besitzt ja seinerseits Objekte, die freigegeben werden müssen), musst du einen "destructor"(analog zum constructor) daklarieren, dieser heißt im Normalfall "Destroy".
Free; macht dabei nichts anderes als "if self <> nil then Destroy;". Sprich: Wenn das Objekt nicht mehr(noch nicht) existiert, bekommst du keine Zugriffsverletzung. 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:
| constructor TPropertylist.Create(); begin b_need := TRessources.create; b_produce := TRessources.create; b_produce_time := TRessources.create; b_time := TRessources.create; end;
destructor TPropertylist.Destroy(); begin b_need.Free; b_produce.Free; b_produce_time.Free; b_time.Free; end;
procedure TGameForm.OnFormDestroy(Sender: TObject); begin b_Game.Free; end;
procedure TObject.Free; begin if Assigned(self) then self.Destroy; end;
function Assigned(X: TObject): Boolean; begin result := X <> nil; end; |
mfG,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Do 09.10.08 20:32
Ja,
du hast natürlich Recht, habe ich gar nicht dran gedacht.
Schon geändert.
Kai
|
|
wurstuk
      
Beiträge: 77
Win XP, Ubuntu
Delphi 7 personal
|
Verfasst: Fr 10.10.08 14:41
Titel: <(^_^)>
Hi
ähm ich check i-wie nicht wie diss geht das mann das Spiel spielen kann^^
ich habe mir erst die textdatei und dann die .exe runtegeladen (beide auf desktop) und dann in einen ordner gemacht aber dann kommt immer eine fehler meldung:
"DDraw.dll is not loaded"
dann hab ich mir nochmal dieses pgame runtergeladen und es damit probiert, es kam aber
der selbe Fehler...
kann mir i-einer sagen warum die nicht geht?
vllt liegts an dem PC, is nehmlich der von meinem Vater und der hat windows NT....
lg
_________________ Wer Rechtschreibfehler findet darf sie behalten!
<(^_^)> <[$_$]>
|
|
wurstuk
      
Beiträge: 77
Win XP, Ubuntu
Delphi 7 personal
|
Verfasst: Fr 10.10.08 14:50
ahhh an meinem Pc gehts^^
hmmm bei mir ist es i-wie sehr dunkel kann aber auch an meinem Bildschirm liegen da is immer alles dunkel^^
wenn ich auf eine Mühle drücke zeigt er mir Name usw an aber kann mann jetzt schon i-was selber bauen oder kann mann das i-wann überhaupt?
und die Steuerung ist noch ein bisschen komisch^^
aber sonst eig. ganz coool^^
wie lange machst du schon Delphi?
_________________ Wer Rechtschreibfehler findet darf sie behalten!
<(^_^)> <[$_$]>
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 10.10.08 14:50
wurstuk hat folgendes geschrieben : | | "DDraw.dll is not loaded" |
Nun ja, hast du denn DirectX auf dem PC überhaupt installiert? Wenn es wirklich Windows NT (nicht 2000 oder XP) ist, dann vermute ich mal, dass das nicht der Fall ist. Mehr als DirectX 6 wird AFAIK auch gar nicht für Windows NT unterstützt.
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Fr 10.10.08 15:03
PS: Die neuste Version sollte immer im Erstpost liegen. Mach doch .exe und .txt in ein zip-Archiv, dann brauchst du nur einen Download
PPS: Ja, dunkel ist es sehr  Und sag mal was hast du mit dem Programm gemacht? Das Standard-Taskleisten-Menü scheint deaktiviert zu sein und das Programm zwingt mich, es im Fullscreen-Modus auszuführen(so etwas würde ich ja gerne auswählen) 
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
kai_lamers 
      
Beiträge: 24
|
Verfasst: Fr 10.10.08 15:15
Hey,
ich werde es gleich zu einem Zip zusammenfassen und oben hineinladen.
Hidden hat folgendes geschrieben : |
PPS: Ja, dunkel ist es sehr Und sag mal was hast du mit dem Programm gemacht? Das Standard-Taskleisten-Menü scheint deaktiviert zu sein und das Programm zwingt mich, es im Fullscreen-Modus auszuführen(so etwas würde ich ja gerne auswählen)  |
Die Grafiken sind grad eh noch Übergangsmaterial. Hm, also an der eigentlichen Programmausgabe (also auch Fullscreen Einstellungen etc. habe ich seit der ersten Version nichts verändert.
Aber auch das lässt sich noch ändern, nachher wenn ich meinen heutigen Teil anfange, ist eh erstmal die Steuerung dran.
Ich arbeite schon seit etwa 3 Jahren mit Delphi, allerdings diesmal erstmal im Bereich der Spieleprogrammierung.
Lg,
Kai
|
|
|