Subversion Repositories spacemission

Rev

Rev 48 | Rev 52 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit ComLevelReader;
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes;
  7.  
  8. const
  9.   NumEnemyTypes = 7;
  10.  
  11. type
  12.   TEnemyType = (
  13.     etUnknown,
  14.     etEnemyAttacker,
  15.     etEnemyAttacker2,
  16.     etEnemyAttacker3,
  17.     etEnemyMeteor,
  18.     etEnemyUFO,
  19.     etEnemyUFO2,
  20.     etEnemyBoss
  21.   );
  22.  
  23.   TEnemyAdvent = record
  24.     enemyType: TEnemyType;
  25.     x: integer;
  26.     y: integer;
  27.     lifes: integer;
  28.   end;
  29.  
  30.   TLevelData = class(TPersistent)
  31.   strict private
  32.     procedure SortEnemies;
  33.   strict protected
  34.     procedure AssignTo(Dest: TPersistent); override;
  35.   public
  36.     RasterErzwingen: boolean;
  37.     LevelEditorLength: integer;
  38.     LevelName: string;
  39.     LevelAuthor: string;
  40.     EnemyAdventTable: array of TEnemyAdvent;
  41.     function IndexOfEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer): integer;
  42.     procedure AddEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer);
  43.     procedure DeleteEnemy(i: integer); overload;
  44.     procedure DeleteEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer); overload;
  45.     function CountEnemies: integer;
  46.     function HasBoss: boolean;
  47.     procedure Clear;
  48.     procedure LoadFromStrings(sl: TStrings); // version 0.3 - version 1.2 files
  49.     procedure LoadFromFile(filename: string); // version 0.2 - version 1.2 files
  50.     procedure SaveToStrings(sl: TStrings);
  51.     procedure SaveToFile(filename: string);
  52.     destructor Destroy; override;
  53.   end;
  54.  
  55.   TGameMode = (gmUnknown, gmLevels, gmRandom);
  56.  
  57.   TSaveData = class(TPersistent)
  58.   strict protected
  59.     procedure AssignTo(Dest: TPersistent); override;
  60.   public
  61.     Score: integer;
  62.     Life: integer;
  63.     Level: integer;
  64.     GameMode: TGameMode;
  65.     LevelData: TLevelData;
  66.     procedure Clear;
  67.     procedure LoadFromStrings(sl: TStrings);
  68.     procedure LoadFromFile(filename: string);
  69.     procedure SaveToStrings(sl: TStrings);
  70.     procedure SaveToFile(filename: string);
  71.     destructor Destroy; override;
  72.   end;
  73.  
  74. function GetLevelFileName(lev: integer; forceuserdir: boolean): string;
  75.  
  76. implementation
  77.  
  78. uses
  79.   SysUtils, StrUtils, Global, Windows;
  80.  
  81. function GetLevelFileName(lev: integer; forceuserdir: boolean): string;
  82.  
  83.   function _GetLevelVerzeichnisSystem: string;
  84.   begin
  85.     // Für die Auslieferungs-Levels
  86.     result := OwnDirectory + 'Levels';
  87.   end;
  88.  
  89.   function _GetLevelVerzeichnisUser: string;
  90.   begin
  91.     try
  92.       result := GetKnownFolderPath(FOLDERID_SavedGames);
  93.     except
  94.       result := '';
  95.     end;
  96.     if result = '' then
  97.     begin
  98.       // Pre Vista
  99.       result := OwnDirectory + 'Levels';
  100.     end
  101.     else
  102.     begin
  103.       result := IncludeTrailingPathDelimiter(result);
  104.       result := result + 'SpaceMission';
  105.     end;
  106.     result := IncludeTrailingPathDelimiter(result);
  107.     ForceDirectories(result);
  108.   end;
  109.  
  110.   function _GetLevelFileNameUser(lev: integer): string;
  111.   var
  112.     old, new: string;
  113.   begin
  114.     new := IncludeTrailingPathDelimiter(_GetLevelVerzeichnisUser)+'Level '+inttostr(lev)+'.lev'; // Version 0.3+ Level Files
  115.     old := IncludeTrailingPathDelimiter(_GetLevelVerzeichnisUser)+'Lev'+inttostr(lev)+'A1.lev'; // Version 0.2 Level Files
  116.     if fileexists(new) then exit(new);
  117.     if fileexists(old) then exit(old);
  118.     exit(new);
  119.   end;
  120.  
  121.   function _GetLevelFileNameSystem(lev: integer): string;
  122.   var
  123.     old, new: string;
  124.   begin
  125.     new := IncludeTrailingPathDelimiter(_GetLevelVerzeichnisSystem)+'Level '+inttostr(lev)+'.lev'; // Version 0.3+ Level Files
  126.     old := IncludeTrailingPathDelimiter(_GetLevelVerzeichnisSystem)+'Lev'+inttostr(lev)+'A1.lev'; // Version 0.2 Level Files
  127.     if fileexists(new) then exit(new);
  128.     if fileexists(old) then exit(old);
  129.     exit(new);
  130.   end;
  131.  
  132. var
  133.   usr, sys: string;
  134. begin
  135.   usr := _GetLevelFileNameUser(lev);
  136.   sys := _GetLevelFileNameSystem(lev);
  137.   if fileexists(usr) or forceuserdir then exit(usr);
  138.   if fileexists(sys) then exit(sys);
  139.   exit(usr);
  140. end;
  141.  
  142. { TLevelData }
  143.  
  144. procedure TLevelData.AssignTo(Dest: TPersistent);
  145. var
  146.   DestLevelData: TLevelData;
  147.   i: integer;
  148. begin
  149.   DestLevelData := Dest as TLevelData;
  150.   if Assigned(DestLevelData) then
  151.   begin
  152.     DestLevelData.RasterErzwingen := Self.RasterErzwingen;
  153.     DestLevelData.LevelEditorLength := Self.LevelEditorLength;
  154.     DestLevelData.LevelName := Self.LevelName;
  155.     DestLevelData.LevelAuthor := Self.LevelAuthor;
  156.     SetLength(DestLevelData.EnemyAdventTable, Length(Self.EnemyAdventTable));
  157.     for i := 0 to Length(Self.EnemyAdventTable) do
  158.     begin
  159.       DestLevelData.EnemyAdventTable[i] := Self.EnemyAdventTable[i];
  160.     end;
  161.   end
  162.   else
  163.   begin
  164.     inherited;
  165.   end;
  166. end;
  167.  
  168. procedure TLevelData.Clear;
  169. begin
  170.   SetLength(EnemyAdventTable, 0);
  171.   LevelEditorLength := DefaultLevelLength;
  172.   LevelName := '';
  173.   LevelAuthor := '';
  174. end;
  175.  
  176. function TLevelData.CountEnemies: integer;
  177. begin
  178.   result := Length(EnemyAdventTable);
  179. end;
  180.  
  181. procedure TLevelData.DeleteEnemy(i: integer);
  182. var
  183.   j: integer;
  184. begin
  185.   for j := i+1 to CountEnemies-1 do
  186.   begin
  187.     EnemyAdventTable[j-1] := EnemyAdventTable[j];
  188.   end;
  189.   SetLength(EnemyAdventTable, Length(EnemyAdventTable)-1);
  190. end;
  191.  
  192. procedure TLevelData.DeleteEnemy(x, y: integer; enemyType: TEnemyType;
  193.   lifes: integer);
  194. begin
  195.   DeleteEnemy(IndexOfEnemy(x, y, enemyType, lifes));
  196. end;
  197.  
  198. destructor TLevelData.Destroy;
  199. begin
  200.   Clear;
  201.   inherited;
  202. end;
  203.  
  204. function TLevelData.HasBoss: boolean;
  205. var
  206.   i: integer;
  207. begin
  208.   for i := 0 to Length(EnemyAdventTable) - 1 do
  209.   begin
  210.     if EnemyAdventTable[i].enemyType = etEnemyBoss then
  211.     begin
  212.       result := true;
  213.       exit;
  214.     end;
  215.   end;
  216.   result := false;
  217. end;
  218.  
  219. procedure TLevelData.AddEnemy(x,y:integer;enemyType:TEnemyType;lifes:integer);
  220. begin
  221.   SetLength(EnemyAdventTable, Length(EnemyAdventTable)+1);
  222.  
  223.   if enemyType = etEnemyMeteor then lifes := 0;
  224.   if RasterErzwingen then
  225.   begin
  226.     if x mod RasterW <> 0 then raise Exception.CreateFmt('X-Koordinate muss ohne Rest durch %d teilbar sein', [RasterW]);
  227.     if y mod RasterH <> 0 then raise Exception.CreateFmt('Y-Koordinate muss ohne Rest durch %d teilbar sein', [RasterH]);
  228.   end;
  229.   if lifes > MaxPossibleEnemyLives then lifes := MaxPossibleEnemyLives;
  230.  
  231.   EnemyAdventTable[Length(EnemyAdventTable)-1].x         := x;
  232.   EnemyAdventTable[Length(EnemyAdventTable)-1].y         := y;
  233.   EnemyAdventTable[Length(EnemyAdventTable)-1].enemyType := enemyType;
  234.   EnemyAdventTable[Length(EnemyAdventTable)-1].lifes     := lifes;
  235. end;
  236.  
  237. function TLevelData.IndexOfEnemy(x, y: integer; enemyType: TEnemyType;
  238.   lifes: integer): integer;
  239. var
  240.   i: integer;
  241. begin
  242.   for i := 0 to Length(EnemyAdventTable) - 1 do
  243.   begin
  244.     if (EnemyAdventTable[i].x = x) and
  245.        (EnemyAdventTable[i].y = y) and
  246.        (EnemyAdventTable[i].enemyType = enemyType) and
  247.        (EnemyAdventTable[i].lifes = lifes) then
  248.     begin
  249.       result := i;
  250.       exit;
  251.     end;
  252.   end;
  253.   result := -1;
  254. end;
  255.  
  256. procedure TLevelData.LoadFromStrings(sl: TStrings);
  257. var
  258.   curline: integer;
  259.   z, act: integer;
  260.   sl2: TStringList;
  261.   tmpX, tmpY, tmpLifes: integer;
  262.   tmpEnemy: TEnemyType;
  263.   tmpRest: string;
  264.   ergebnis: string;
  265. begin
  266.   Clear;
  267.  
  268.   LevelEditorLength := DefaultLevelLength;
  269.   LevelName := '';
  270.   LevelAuthor := '';
  271.  
  272.   if sl.Strings[0] = '; SpaceMission 0.3' then
  273.   begin
  274.     {$REGION 'Backwards compatibility level format 0.3 (convert to 0.4)'}
  275.     sl.Strings[0] := '; SpaceMission 0.4';
  276.     sl.Insert(1, '; LEV-File');
  277.     {$ENDREGION}
  278.   end;
  279.  
  280.   if (sl.Strings[0] = '; SpaceMission 0.4') and
  281.      (sl.Strings[1] = '; LEV-File') then
  282.   begin
  283.     {$REGION 'Backwards compatibility level format 0.4 (convert to 1.0)'}
  284.     sl2 := TStringList.Create;
  285.     try
  286.       z := 0;
  287.       act := 0;
  288.       while z < sl.Count do
  289.       begin
  290.         inc(z);
  291.         if z > 2 then inc(act);
  292.         if act = 5 then act := 1;
  293.         ergebnis := sl.Strings[z-1];
  294.         if ergebnis = '; SpaceMission 0.4' then
  295.           sl2.Add('; SpaceMission 1.0')
  296.         else
  297.         begin
  298.           if (ergebnis = '30000') and (z = 3) then
  299.             sl2.Add(IntTostr(DefaultLevelLength))
  300.           else
  301.           begin
  302.             //if not (((ergebnis = '0') and (z = 4)) or ((ergebnis = '-624') and (z = 5)) or ((ergebnis = '222') and (z = 6)) or ((ergebnis = '3') and (z = 7))) then
  303.             if (z < 4) or (z > 7) then
  304.             begin
  305.               if act = 4 then
  306.                 sl2.Add(inttostr(strtoint(ergebnis) + 32 - (5 * (strtoint(ergebnis) div 37))))
  307.               else
  308.                 sl2.Add(Ergebnis);
  309.             end;
  310.           end;
  311.         end;
  312.       end;
  313.       sl.Text := sl2.Text;
  314.     finally
  315.       FreeAndNil(sl2);
  316.     end;
  317.     {$ENDREGION}
  318.   end;
  319.  
  320.   if (sl.Strings[0] = '; SpaceMission 1.0') and
  321.      (sl.Strings[1] = '; LEV-File') then
  322.   begin
  323.     {$REGION 'Level format 1.0'}
  324.     LevelEditorLength := StrToInt(sl.Strings[2]);
  325.     curline := 3;
  326.     while curline < sl.Count do
  327.     begin
  328.       tmpEnemy := TEnemyType(strtoint(sl.Strings[curline]));
  329.       Inc(curline);
  330.       tmpX := strtoint(sl.Strings[curline]);
  331.       Inc(curline);
  332.       tmpY := strtoint(sl.Strings[curline]);
  333.       Inc(curline);
  334.       tmpLifes := strtoint(sl.Strings[curline]);
  335.       Inc(curline);
  336.       AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
  337.     end;
  338.     {$ENDREGION}
  339.   end
  340.   else if (SameText(sl.Strings[0], '[SpaceMission Level, Format 1.2]')) or
  341.           (SameText(sl.Strings[0], '[SpaceMission Savegame, Format 1.2]')) then
  342.   begin
  343.     {$REGION 'Level format 1.2'}
  344.     for curline := 1 to sl.Count-1 do
  345.     begin
  346.       // 1234567890123456789012345678901234567890
  347.       // 123456 123456 123456 123456 123456 ; Kommentar
  348.       if (sl.Strings[curline].Trim = '') or
  349.          (Copy(sl.Strings[curline], 1, 1) = ';') then
  350.         // Do nothing
  351.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Width' then
  352.       begin
  353.         LevelEditorLength := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
  354.       end
  355.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Name' then
  356.       begin
  357.         LevelName := TrimRight(Copy(sl.Strings[curline], 8, Length(sl.Strings[curline])))
  358.       end
  359.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Author' then
  360.       begin
  361.         LevelAuthor := TrimRight(Copy(sl.Strings[curline], 8, Length(sl.Strings[curline])))
  362.       end
  363.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Enemy' then
  364.       begin
  365.         tmpEnemy := TEnemyType(strtoint(TrimRight(Copy(sl.Strings[curline], 8, 6))));
  366.         tmpX     := strtoint(TrimRight(Copy(sl.Strings[curline], 15, 6)));
  367.         tmpY     := strtoint(TrimRight(Copy(sl.Strings[curline], 22, 6)));
  368.         tmpLifes := strtoint(TrimRight(Copy(sl.Strings[curline], 29, 6)));
  369.         tmpRest  := Copy(sl.Strings[curline], 36, Length(sl.Strings[curline])-36+1);
  370.         if (Copy(tmpRest, 1, 1) <> ';') and (Trim(tmpRest) <> '') then
  371.           raise Exception.CreateFmt('Zeile %d ist ungültig (Zusatzinfo am Ende)', [curline+1]);
  372.         AddEnemy(tmpX, tmpY, tmpEnemy, tmpLifes);
  373.       end;
  374.     end;
  375.     {$ENDREGION}
  376.   end
  377.   else
  378.   begin
  379.     raise Exception.Create('Level-Format nicht unterstützt oder Datei ist beschädigt');
  380.   end;
  381.  
  382.   SortEnemies; // Sortierung nach X-Koordinate ist sehr wichtig für das Spiel!
  383. end;
  384.  
  385. procedure TLevelData.LoadFromFile(filename: string);
  386. var
  387.   sl: TStringList;
  388.   i, j: integer;
  389.   temp: string;
  390.   m: array[1..6] of tstrings;
  391. begin
  392.   sl := TStringList.Create;
  393.   try
  394.     if EndsText('A1.lev', filename) then
  395.     begin
  396.       {$REGION 'Backwards compatibility level format 0.2 (split into 5-6 files; convert to 0.3)'}
  397.       m[1] := TStringList.create;
  398.       m[2] := TStringList.create;
  399.       m[3] := TStringList.create;
  400.       m[4] := TStringList.create;
  401.       m[5] := TStringList.create;
  402.       m[6] := TStringList.create;
  403.       try
  404.         for i := 1 to 6 do
  405.         begin
  406.           filename[Length(filename)-4] := IntToStr(i)[1]; // ...A2.sav, ...A3.sav, etc.
  407.           if FileExists(filename) then
  408.             m[i].loadfromfile(filename);
  409.         end;
  410.         m[1].strings[0] := '-624';
  411.         if m[6].Text = '' then m[6].Text := '30000';
  412.  
  413.         sl.Add('; SpaceMission 0.3');
  414.         sl.Add(temp);
  415.         for j := 0 to m[1].count-2 do
  416.         begin
  417.           for i := 0 to m[1].count-2 do
  418.           begin
  419.             if strtoint(m[1].strings[i]) > strtoint(m[1].strings[i+1]) then
  420.             begin
  421.               m[1].exchange(i, i+1);
  422.               m[2].exchange(i, i+1);
  423.               m[3].exchange(i, i+1);
  424.               m[4].exchange(i, i+1);
  425.               m[5].exchange(i, i+1);
  426.             end;
  427.           end;
  428.         end;
  429.         for i := 0 to m[3].count-1 do
  430.         begin
  431.           for j := 1 to 4 do
  432.           begin
  433.             if j = 1 then sl.Add(m[3].strings[i]);
  434.             if j = 2 then sl.Add(m[1].strings[i]);
  435.             if j = 3 then sl.Add(m[2].strings[i]);
  436.             if j = 4 then sl.Add(m[4].strings[i]);
  437.           end;
  438.         end;
  439.       finally
  440.         FreeAndNil(m[1]);
  441.         FreeAndNil(m[2]);
  442.         FreeAndNil(m[3]);
  443.         FreeAndNil(m[4]);
  444.         FreeAndNil(m[5]);
  445.         FreeAndNil(m[6]);
  446.       end;
  447.       {$ENDREGION}
  448.     end
  449.     else
  450.     begin
  451.       sl.LoadFromFile(filename);
  452.     end;
  453.  
  454.     LoadFromStrings(sl);
  455.   finally
  456.     FreeAndNil(sl);
  457.   end;
  458. end;
  459.  
  460. procedure TLevelData.SaveToStrings(sl: TStrings);
  461. var
  462.   i: integer;
  463. begin
  464.   sl.Clear;
  465.   sl.Add('[SpaceMission Level, Format 1.2]');
  466.   if LevelName   <> '' then sl.Add('Name   ' + LevelName);
  467.   if LevelAuthor <> '' then sl.Add('Author ' + LevelAuthor);
  468.   sl.Add('Width  ' + IntToStr(LevelEditorLength));
  469.   SortEnemies;
  470.   sl.Add(';      Type   XCoord YCoord Lives');
  471.   for i := 0 to Length(EnemyAdventTable)-1 do
  472.   begin
  473.     sl.Add(
  474.       'Enemy'.PadRight(6, ' ')+
  475.       ' '+
  476.       IntToStr(Ord(EnemyAdventTable[i].enemyType)).PadRight(6, ' ')+
  477.       ' '+
  478.       IntToStr(EnemyAdventTable[i].x).PadRight(6, ' ')+
  479.       ' '+
  480.       IntToStr(EnemyAdventTable[i].y).PadRight(6, ' ')+
  481.       ' '+
  482.       IntToStr(EnemyAdventTable[i].lifes).PadRight(6, ' ')+
  483.       ' '
  484.     );
  485.   end;
  486. end;
  487.  
  488. procedure TLevelData.SaveToFile(filename: string);
  489. var
  490.   sl: TStringList;
  491. begin
  492.   sl := TStringList.Create;
  493.   try
  494.     SaveToStrings(sl);
  495.     sl.SaveToFile(filename);
  496.   finally
  497.     FreeAndNil(sl);
  498.   end;
  499. end;
  500.  
  501. procedure TLevelData.SortEnemies;
  502. var
  503.   i, n: integer;
  504.   e: TEnemyAdvent;
  505. begin
  506.   // Bubble Sort Algorithmus
  507.   for n := Length(EnemyAdventTable) downto 2 do
  508.   begin
  509.     for i := 0 to n - 2 do
  510.     begin
  511.       if
  512.         // Sort by X-coord (important for the game!)
  513.         (EnemyAdventTable[i].x > EnemyAdventTable[i+1].x)
  514.         or
  515.         // Sort by Y-coord (just cosmetics)
  516.         ((EnemyAdventTable[i].x = EnemyAdventTable[i+1].x) and (EnemyAdventTable[i].y > EnemyAdventTable[i+1].y))
  517.       then
  518.       begin
  519.         e := EnemyAdventTable[i];
  520.         EnemyAdventTable[i] := EnemyAdventTable[i + 1];
  521.         EnemyAdventTable[i + 1] := e;
  522.       end;
  523.     end;
  524.   end;
  525. end;
  526.  
  527. { TSaveData }
  528.  
  529. procedure TSaveData.AssignTo(Dest: TPersistent);
  530. var
  531.   DestSaveData: TSaveData;
  532. begin
  533.   DestSaveData := Dest as TSaveData;
  534.   if Assigned(DestSaveData) then
  535.   begin
  536.     DestSaveData.Score := Self.Score;
  537.     DestSaveData.Life := Self.Life;
  538.     DestSaveData.Level := Self.Level;
  539.     DestSaveData.GameMode := Self.GameMode;
  540.     if not Assigned(DestSaveData.LevelData) then DestSaveData.LevelData := TLevelData.Create;
  541.     DestSaveData.LevelData.Assign(Self.LevelData);
  542.   end
  543.   else
  544.   begin
  545.     inherited;
  546.   end;
  547. end;
  548.  
  549. procedure TSaveData.Clear;
  550. begin
  551.   Score := 0;
  552.   Life := 0;
  553.   Level := 0;
  554.   GameMode := gmUnknown;
  555.   FreeAndNil(LevelData);
  556. end;
  557.  
  558. destructor TSaveData.Destroy;
  559. begin
  560.   Clear;
  561.   inherited;
  562. end;
  563.  
  564. procedure TSaveData.SaveToStrings(sl: TStrings);
  565. var
  566.   sl2: TStringList;
  567. begin
  568.   sl2 := TStringList.Create;
  569.   try
  570.     sl.Add('[SpaceMission Savegame, Format 1.2]');
  571.     sl.Add('Score  ' + IntToStr(Score));
  572.     sl.Add('Lives  ' + IntToStr(Life));
  573.     sl.Add('Level  ' + IntToStr(Level));
  574.     sl.Add('Mode   ' + IntToStr(Ord(GameMode)));
  575.     LevelData.SaveToStrings(sl2);
  576.     sl2.Delete(0); // Signature
  577.     sl.AddStrings(sl2);
  578.   finally
  579.     FreeAndNil(sl2);
  580.   end;
  581. end;
  582.  
  583. procedure TSaveData.LoadFromStrings(sl: TStrings);
  584. var
  585.   curline: Integer;
  586. begin
  587.   if (sl.Strings[0] = '; SpaceMission 1.0') and
  588.      (sl.Strings[1] = '; SAV-File') then
  589.   begin
  590.     Score    := StrToInt(sl.Strings[2]);
  591.     Life     := StrToInt(sl.Strings[3]);
  592.     Level    := StrToInt(sl.Strings[4]);
  593.     GameMode := TGameMode(StrToInt(sl.Strings[5]));
  594.     if Assigned(LevelData) then FreeAndNil(LevelData);
  595.   end
  596.   else if SameText(sl.Strings[0], '[SpaceMission Savegame, Format 1.2]') then
  597.   begin
  598.     Score    := 0;
  599.     Life     := 0;
  600.     Level    := 0;
  601.     GameMode := gmUnknown;
  602.     for curline := 1 to sl.Count-1 do
  603.     begin
  604.       // 1234567890123456789012345678901234567890
  605.       // 123456 123456 123456 123456 123456 ; Kommentar
  606.       if (sl.Strings[curline].Trim = '') or
  607.          (Copy(sl.Strings[curline], 1, 1) = ';') then
  608.         // Do nothing
  609.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Score' then
  610.       begin
  611.         Score := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
  612.       end
  613.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Lives' then
  614.       begin
  615.         Life := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
  616.       end
  617.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Level' then
  618.       begin
  619.         Level := StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6)))
  620.       end
  621.       else if Copy(sl.Strings[curline], 1, 6).TrimRight = 'Mode' then
  622.       begin
  623.         GameMode := TGameMode(StrToInt(TrimRight(Copy(sl.Strings[curline], 8, 6))))
  624.       end;
  625.     end;
  626.     if Assigned(LevelData) then FreeAndNil(LevelData);
  627.     LevelData := TLevelData.Create;
  628.     LevelData.RasterErzwingen := false;
  629.     LevelData.LoadFromStrings(sl);
  630.   end
  631.   else
  632.   begin
  633.     raise Exception.Create('Spielstand-Format nicht unterstützt oder Datei beschädigt');
  634.   end;
  635. end;
  636.  
  637. procedure TSaveData.LoadFromFile(filename: string);
  638. var
  639.   sl: TStringList;
  640. begin
  641.   sl := TStringList.Create;
  642.   try
  643.     sl.LoadFromFile(filename);
  644.     LoadFromStrings(sl);
  645.   finally
  646.     FreeAndNil(sl);
  647.   end;
  648. end;
  649.  
  650. procedure TSaveData.SaveToFile(filename: string);
  651. var
  652.   sl: TStringList;
  653. begin
  654.   sl := TStringList.Create;
  655.   try
  656.     SaveToStrings(sl);
  657.     sl.SaveToFile(filename);
  658.   finally
  659.     FreeAndNil(sl);
  660.   end;
  661. end;
  662.  
  663. end.
  664.