AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Objekte aus Textdatei erstellen

Ein Thema von Acuaplano · begonnen am 16. Jun 2013 · letzter Beitrag vom 22. Jun 2013
Antwort Antwort
Seite 1 von 2  1 2      
Acuaplano

Registriert seit: 8. Mai 2013
29 Beiträge
 
#1

Objekte aus Textdatei erstellen

  Alt 16. Jun 2013, 18:22
Delphi-Version: 5
Moin Moin,

Ich arbeite grad' an einem kleinen Spiel mit der Andorra 2D-Engine, wobei jedoch mein Problem eher Delphi bezogen ist. Das Problem liegt in der Mapgenerierung, die in Textdateien abgespeichert wird. Bis jetzt sah die Mapgenerierung so aus:
Es steht ein Raster, dass aus Zahlen besteht, in etwa so:
1;2,3;
5;2;7;
8;2;3;
Die Zahlen zeigen dabei die Bilder für den Maphintergrund an. Die einzelnen Bilder wurden zuvor in eine Liste mit den entsprechenden Nummern geladen. Anschließend werden beim Laden der Map für jede Zahl ein Objekt an der entsprechenden Stelle und passenden Bildchen erstellt. Funktionieren tut's wunderbar, nur reicht das noch nicht für eine richtige Map:
Wie stelle ich es an, dass Objekte von verschiedenen Klassen gebildet werden, abhängig von dem was in der Textdatei steht?
Beispiel (Mehrere Ebenen sind bereits möglich):
TBaum; 0; TBaum;
TBrett; 0; TNpc;
0; TBaum; THaus;

Dabei muss ne praktische Lösung her, da ja noch ne ganze Menge Objekte dazukommen könnten. Ich hatte mir schon gedacht, dass ich irgendwie alle Objekte in eine Liste reinpacke und dann bei der Generierung daraus gesucht wird... aber wie genau das gehen soll weiß ich auch nicht.

Geändert von Acuaplano (16. Jun 2013 um 18:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.347 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Objekte aus Textdatei erstellen

  Alt 16. Jun 2013, 18:49
Warum benutzt du denn Textdateien? Hat das einen Grund?

Denn viel simpler wäre es, wenn du deinen Klassen jeweils die Methoden LoadFromStream und SaveToStream spendieren würdest, die das ganze binär speichern und laden. Dazu dann noch in der äußersten Ebene LoadFromFile und SaveToFile, die einen TFileStream aufmachen und an deine Streammethoden weitergeben, schon bist du fertig.

Das ist sehr viel einfacher, nur die Dateien sind manuell schlecht lesbar. Aber wenn das nicht wichtig ist, würde ich das eher so machen.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Acuaplano

Registriert seit: 8. Mai 2013
29 Beiträge
 
#3

AW: Objekte aus Textdatei erstellen

  Alt 16. Jun 2013, 19:38
Lesbar muss es nicht sein, dafür mit nem selbst gemachten Editor erstellbar, aber das sollte ja da auch kein Problem sein.
Falls ich das jetzt richtig verstanden habe (TFileStream ist Oberklasse von allen Objekten?), wird das auch nicht funktionieren, da ich die Objekte von einer anderen Klasse der Sprite Engine ableiten muss. Ansonsten müsste ich vielleicht große Teile der Engine umschreiben... und das trau ich mir nicht zu

Und um ehrlich zu sein arbeite ich auch nicht alleine daran. Ein paar andere und ich wollten einfach mal ein Spiel selber machen und ein paar Erfahrungen sammeln. Daher die simplen Texdateien .
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.347 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Objekte aus Textdatei erstellen

  Alt 16. Jun 2013, 20:53
Hier mal ein Beispiel:
Delphi-Quellcode:
unit UnitXYZ;

interface

uses
  Classes, SysUtils;

type
  TStringReaderWriter = class helper for TStream
    function ReadString: string;
    procedure WriteString(const AValue: string);
  end;

  TMyGameObject = class
  private
    type
      TExample = class
      private
        var
          FExampleString: string;
          FExampleInteger: LongInt;
        procedure SetExampleInteger(const Value: LongInt);
        procedure SetExampleString(const Value: string);
      public
        procedure SaveToStream(const ATarget: TStream);
        procedure LoadFromStream(const ASource: TStream);
        property ExampleString: string read FExampleString write SetExampleString;
        property ExampleInteger: LongInt read FExampleInteger write SetExampleInteger;
      end;
    var
      FInterestingString: string;
      FExampleObject: TExample;
    procedure SetInterestingString(const Value: string);
  public
    constructor Create;
    destructor Destroy; override;
    procedure SaveToStream(const ATarget: TStream);
    procedure LoadFromStream(const ASource: TStream);
    procedure SaveToFile(const AFilename: String);
    procedure LoadFromFile(const AFilename: String);
    property InterestingString: string read FInterestingString write SetInterestingString;
    property ExampleObject: TExample read FExampleObject;
  end;

implementation

{ TMyGameObject.TExample }

procedure TMyGameObject.TExample.LoadFromStream(const ASource: TStream);
begin
  FExampleString := ASource.ReadString;
  ASource.ReadBuffer(FExampleInteger, SizeOf(FExampleInteger));
end;

procedure TMyGameObject.TExample.SaveToStream(const ATarget: TStream);
begin
  ATarget.WriteString(FExampleString);
  ATarget.WriteBuffer(FExampleInteger, SizeOf(FExampleInteger));
end;

procedure TMyGameObject.TExample.SetExampleInteger(const Value: LongInt);
begin
  FExampleInteger := Value;
end;

procedure TMyGameObject.TExample.SetExampleString(const Value: string);
begin
  FExampleString := Value;
end;

{ TStringReaderWriter }

function TStringReaderWriter.ReadString: string;
var
  ResultString: AnsiString;
  StringSize: Integer;
begin
  Result := '';
  ReadBuffer(StringSize, SizeOf(StringSize));
  SetLength(ResultString, StringSize);
  ReadBuffer(Pointer(ResultString)^, StringSize);
  {$ifdef UNICODE}
  Result := Utf8ToString(ResultString);
  {$else}
  Result := Utf8Decode(ResultString);
  {$endif}
end;

procedure TStringReaderWriter.WriteString(const AValue: string);
var
  StringSize: Integer;
  StringToSave: AnsiString;
begin
  StringToSave := Utf8Encode(AValue);
  StringSize := Length(StringToSave);
  WriteBuffer(StringSize, SizeOf(StringSize));
  WriteBuffer(Pointer(StringToSave)^, StringSize);
end;

{ TMyGameObject }

constructor TMyGameObject.Create;
begin
  FExampleObject := TExample.Create;
end;

destructor TMyGameObject.Destroy;
begin
  FExampleObject.Free;
  inherited;
end;

procedure TMyGameObject.LoadFromFile(const AFilename: String);
var
  FileContents: TFileStream;
begin
  FileContents := TFileStream.Create(AFilename, fmOpenRead);
  try
    LoadFromStream(FileContents);
  finally
    FileContents.Free;
  end;
end;

procedure TMyGameObject.LoadFromStream(const ASource: TStream);
begin
  FInterestingString := ASource.ReadString;
  FExampleObject.LoadFromStream(ASource);
end;

procedure TMyGameObject.SaveToFile(const AFilename: String);
var
  FileContents: TFileStream;
begin
  FileContents := TFileStream.Create(AFilename, fmCreate);
  try
    SaveToStream(FileContents);
  finally
    FileContents.Free;
  end;
end;

procedure TMyGameObject.SaveToStream(const ATarget: TStream);
begin
  ATarget.WriteString(FInterestingString);
  FExampleObject.SaveToStream(ATarget);
end;

procedure TMyGameObject.SetInterestingString(const Value: string);
begin
  FInterestingString := Value;
end;

end.
Und benutzen kannst du das dann so:
Delphi-Quellcode:
var
  MyGameData: TMyGameObject;
begin
  if dlgOpen.Execute then
  begin
    MyGameData := TMyGameObject.Create;
    try
      MyGameData.LoadFromFile(dlgOpen.Filename);
      ShowMessage(MyGameData.InterestingString);
    finally
      MyGameData.Free;
    end;
  end;
Auf diese Weise ist nach außen immer alles gekapselt und du kannst die Objekte nach außen immer einfach benutzen ohne dich um die Interna zu kümmern.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Acuaplano

Registriert seit: 8. Mai 2013
29 Beiträge
 
#5

AW: Objekte aus Textdatei erstellen

  Alt 16. Jun 2013, 21:16
Okay, danke für die ausführliche Antwort!
Wir werden es dann mal so versuchen, aber das Hauptproblem ist ja immer noch vorhanden:

Ich versuch's mal anhand des aktuellen Codes zu erklären:

Delphi-Quellcode:
//Map bauen
    for i := 1 to reader.GetRasterX do // 1 bis 32 (Breite des Rasters)
    begin
      for j := 1 to reader.GetRasterY do
      begin
        with TMapUB.Create(AdSpriteEngine) do
        begin
          //Map an Hand der Textdatei bauen
          Image := AdImageList1.Find(raster[j - 1, i - 1]); // *
          //Immer in 96 Abständen laden
          x := i * 96;
          y := j * 96;
        end;
      end;
    end;
Raster ist hierbei sozusagen die verarbeitete Textdatei als einfaches Array, wobei es dann als Beispiel '3' ausgeben würde und dann das entsprechende Bild ausgewählt werden würde.
Wir wollen ja aber nun, dass genau an dieser Stelle zwischen einzelnen Klassen statt einzelnen Bildern unterschieden wird.
  Mit Zitat antworten Zitat
Acuaplano

Registriert seit: 8. Mai 2013
29 Beiträge
 
#6

AW: Objekte aus Textdatei erstellen

  Alt 18. Jun 2013, 14:47
Ich würde es mir dann in etwa so etwa in der Art vorstellen:
raster[j - 1, i - 1].Create
Sodass das Programm eben das hier ausführen würde:
TBaum1.Create
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.347 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Objekte aus Textdatei erstellen

  Alt 18. Jun 2013, 15:41
Darauf passt das Factory-Pattern, d.h. eine Factory, bei der sich die Klassen z.B. selbst registrieren (z.B. in initialization der Units). Diese Factory kennt dann die Klassen und kann die auch erstellen, wenn du dort dann nach einer Klasse anfragst.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Acuaplano

Registriert seit: 8. Mai 2013
29 Beiträge
 
#8

AW: Objekte aus Textdatei erstellen

  Alt 18. Jun 2013, 17:39
Darauf passt das Factory-Pattern, d.h. eine Factory, bei der sich die Klassen z.B. selbst registrieren (z.B. in initialization der Units). Diese Factory kennt dann die Klassen und kann die auch erstellen, wenn du dort dann nach einer Klasse anfragst.
Ich hab mich jetzt etwas in das Thema eingelesen und werd's noch etwas tun, aber entweder hab ich noch nicht den richtigen Teil gefunden oder das verschiebt mein Problem nur...
Am Beispiel aus dem Internet:
Delphi-Quellcode:
if ASelector = 'Furniturethen
    Result := TFurniture.Create
  else if ASelector = 'Chairthen
    Result := TChair.Create
  else if ASelector = 'Cupboardthen
    Result := TCupboard.Create
  else if ASelector = 'Coffee Tablethen
    Result := TCoffeeTable.Create
  else if ASelector = 'Kitchen Tablethen
    Result := TKitchenTable.Create
  else if ASelector = 'Tablethen
    Result := TTable.Create
Dieser Teil wird ja bei der Factory sozusagen "ausgelagert", wobei jedoch die if-anweisungen bleiben. Problem beim Spiel wird's aber sein, dass ganz viele Objekte dazukommen werden und 100 if-Anweisungen unpraktisch wären. Mein Wunsch wär es ja jetzt das auf ein paar Zeilen zu reduzieren.
Wie gesagt, ich bin noch grad' am Lesen.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Objekte aus Textdatei erstellen

  Alt 18. Jun 2013, 17:46
Vielleicht mal etwas allgemeiner:

Man kann seine Klassen registrieren, damit Objekte dieser Klasse zur Laufzeit erzeugt werden können. Das ist aber etwas aufwendig.

Ungefähr läuft das dann so ab:
Delphi-Quellcode:
// nur smbolischer Code, die genauen Funktionen habe ich nicht im Kopf
VorbereitungFuerBaum;
VorbereitungFuerHaus;
RegisterClass(TBaum, THaus);
...
Baum := CreateObject(TBaum);
Haus := CreateObject(THaus);
(Such mal ggf. nach "Objekte nach Klassennamen erzeugen" o.ä.)


Einfacher kannst Du das natürlich auch selbst in die Hand nehmen:
Delphi-Quellcode:
function GetNewObject(aClassName: String): TObject;
begin
  if aClassName = 'TBaumthen
    Exit(TBaum.Create(Self));
  if aClassName = 'THausthen
    Exit(THaus.Create(Self));
  if aClassName = 'Irgendwasthen
    Exit(TXYZ.Create(Self));
  Result := nil;
end;
Wenn alle Objekte von einer bestimmten Basisklasse abgeleitet werden, dann kann man geschickter Weise diese Basisklasse als Rückgabetyp der Funktion wählen.

Vielleicht nützt das als praktischer Ansatz.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Acuaplano

Registriert seit: 8. Mai 2013
29 Beiträge
 
#10

AW: Objekte aus Textdatei erstellen

  Alt 18. Jun 2013, 19:54
Vielleicht mal etwas allgemeiner:

Man kann seine Klassen registrieren, damit Objekte dieser Klasse zur Laufzeit erzeugt werden können. Das ist aber etwas aufwendig.

Ungefähr läuft das dann so ab:
Delphi-Quellcode:
// nur smbolischer Code, die genauen Funktionen habe ich nicht im Kopf
VorbereitungFuerBaum;
VorbereitungFuerHaus;
RegisterClass(TBaum, THaus);
...
Baum := CreateObject(TBaum);
Haus := CreateObject(THaus);
(Such mal ggf. nach "Objekte nach Klassennamen erzeugen" o.ä.)
Meinst Du damit das Thema mit GetClass & Co?
Das scheint nämlich ein guter Ansatz zu sein . Jedenfalls hab ich mich eben auch noch daran versucht und nicht so ganz weit gekommen. Zunächst aber etwas zur "Basisklasse":
Die Hierarchie sieht im Moment so aus:

TImageSprite (vorgegeben durch Engine)
|
TObjekt
|
TUnbenutzbar
|
TBaum1 (hier würden dann auch die ganzen anderen Objekte stehen)

Ob das jetzt so sinnvoll ist weiß ich nicht, aber es beizubehalten wär schon ganz nett. Daher würde eine Basisklasse auch wegfallen. Man sollte aber wissen, dass alles ab TObjekt in einer anderen Unit ausgelagert ist.
Jetzt aber GetClass:
Was mache ich falsch? Wär das überhaupt so möglich?
CRef := GetClass('TBaum1'); Bei mir ist CRef immer leer (ohne direkte Registrierung der Klasse). Registrieren kann ich es nicht, weil er mir dann immer ne Fehlermeldung ausgibt, dass das keine "persistent class" ist. Aber laut dem Linkhier müsste es doch auch gehen, wenn die Klasse in der Unit deklariert wurde ("Form classes and component classes that are referenced in a form declaration (instance variables) are automatically registered when the form is loaded."), oder hab ich da was falsch verstanden?
Fragen über Fragen... Tut mir leid, wenn es jetzt ganz einfach ist, ich bin noch ziemlich unerfahren .
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz