Subversion Repositories spacemission

Rev

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

  1. unit LevMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, MMSystem,
  7.   Dialogs, StdCtrls, ExtCtrls, Menus, DIB, DXClass, DXSprite, DXDraws,
  8.   DXSounds, Spin, ComCtrls{$IF CompilerVersion >= 23.0}, System.UITypes,
  9.   WinAPI.DirectDraw{$ENDIF}, DirectX, ComLevelReader, Global, IOUtils;
  10.  
  11. type
  12.   TMainForm = class(TDXForm)
  13.     MainMenu: TMainMenu;
  14.     Spiel: TMenuItem;
  15.     Beenden: TMenuItem;
  16.     Hilfe: TMenuItem;
  17.     Leer1: TMenuItem;
  18.     Level: TMenuItem;
  19.     Informationen: TMenuItem;
  20.     Enemy1: TRadioButton;
  21.     Enemy2: TRadioButton;
  22.     Enemy3: TRadioButton;
  23.     Enemy4: TRadioButton;
  24.     Enemy5: TRadioButton;
  25.     Enemy6: TRadioButton;
  26.     Enemy7: TRadioButton;
  27.     ScrollBar: TScrollBar;
  28.     Bevel1: TBevel;
  29.     Bevel2: TBevel;
  30.     SelLabel: TLabel;
  31.     SelPanel: TPanel;
  32.     Bevel3: TBevel;
  33.     SLabel1a: TLabel;
  34.     SLabel2a: TLabel;
  35.     SLabel1b: TLabel;
  36.     SLabel2b: TLabel;
  37.     SLabel0: TLabel;
  38.     Neu: TMenuItem;
  39.     Image1: TImage;
  40.     SLabel3a: TLabel;
  41.     SLabel3b: TLabel;
  42.     SLabel4a: TLabel;
  43.     SLabel4b: TLabel;
  44.     LivesLabel: TLabel;
  45.     StatusBar: TStatusBar;
  46.     N1: TMenuItem;
  47.     Spielfelderweitern1: TMenuItem;
  48.     SidePanel: TPanel;
  49.     LivesEdit: TSpinEdit;
  50.     AlleLeveldateienaktualisieren1: TMenuItem;
  51.     N2: TMenuItem;
  52.     Leveltesten1: TMenuItem;
  53.     Hilfe1: TMenuItem;
  54.     N3: TMenuItem;
  55.     AufUpdatesprfen1: TMenuItem;
  56.     N4: TMenuItem;
  57.     WasgibtesNeues1: TMenuItem;
  58.     procedure DXDrawFinalize(Sender: TObject);
  59.     procedure DXDrawInitialize(Sender: TObject);
  60.     procedure FormCreate(Sender: TObject);
  61.     procedure DXTimerTimer(Sender: TObject; LagCount: Integer);
  62.     procedure BeendenClick(Sender: TObject);
  63.     procedure FormDestroy(Sender: TObject);
  64.     procedure LevelClick(Sender: TObject);
  65.     procedure FormShow(Sender: TObject);
  66.     procedure InformationenClick(Sender: TObject);
  67.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  68.     procedure DXDrawMouseDown(Sender: TObject; Button: TMouseButton;
  69.       Shift: TShiftState; X, Y: Integer);
  70.     procedure EnemyClick(Sender: TObject);
  71.     procedure NeuClick(Sender: TObject);
  72.     procedure DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X,
  73.       Y: Integer);
  74.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  75.     procedure Spielfelderweitern1Click(Sender: TObject);
  76.     procedure ScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode;
  77.       var ScrollPos: Integer);
  78.     procedure AlleLeveldateienaktualisieren1Click(Sender: TObject);
  79.     procedure Leveltesten1Click(Sender: TObject);
  80.     procedure HilfeTopicClick(Sender: TObject);
  81.     procedure AufUpdatesprfen1Click(Sender: TObject);
  82.   private
  83.     function GetTestlevelFilename: string;
  84.   public
  85.     { VCL-Ersatz }
  86.     spriteengine: tdxspriteengine;
  87.     dxtimer: tdxtimer;
  88.     imagelist: tdximagelist;
  89.     dxdraw: tdxdraw;
  90.     { Variablen }
  91.     FMenuItem: integer;
  92.     LevData: TLevelData;
  93.     ScrollP: integer;
  94.     AltScrollPos: integer;
  95.     Boss: boolean;
  96.     LevChanged: boolean;
  97.     NumEnemys: integer;
  98.     function SelectedEnemyType: TEnemyType;
  99.     { Grafik-Routinen }
  100.     function GetSpriteGraphic(Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
  101.     { Level-Routinen }
  102.     procedure EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer);
  103.     procedure DestroyLevel;
  104.     procedure RefreshFromLevData;
  105.     procedure AnzeigeAct;
  106.     { Initialisiations-Routinen }
  107.     procedure DXInit;
  108.     procedure ProgramInit;
  109.     { Farb-Routinen }
  110.     function ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
  111.     procedure PalleteAnim(Col: TRGBQuad; Time: Integer);
  112.   end;
  113.  
  114. var
  115.   MainForm: TMainForm;
  116.  
  117. implementation
  118.  
  119. uses
  120.   LevSplash, LevSpeicherung, ComInfo, LevOptions, ShellAPI, ComHilfe;
  121.  
  122. {$R *.DFM}
  123.  
  124. type
  125.   TBackground = class(TBackgroundSprite)
  126.   strict protected
  127.     procedure DoMove(MoveCount: Integer); override;
  128.   end;
  129.  
  130.   TEnemy = class(TImageSprite)
  131.   strict private
  132.     FLives: integer;
  133.     FEnemyType: TEnemyType;
  134.     FXCor: integer;
  135.     FCorInit: boolean;
  136.   strict protected
  137.     procedure DoMove(MoveCount: Integer); override;
  138.   public
  139.     constructor Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer); reintroduce;
  140.   end;
  141.  
  142. { TBackground }
  143.  
  144. procedure TBackground.DoMove(MoveCount: Integer);
  145. begin
  146.   X := -(MainForm.ScrollP * RasterW);
  147. end;
  148.  
  149. { TEnemy }
  150.  
  151. procedure TEnemy.DoMove(MoveCount: Integer);
  152. begin
  153.   if not FCorInit then
  154.   begin
  155.     FXCor := trunc(x) + (MainForm.ScrollP * RasterW);
  156.     FCorInit := true;
  157.   end;
  158.   if MainForm.LevData.IndexOfEnemy(FXCor, integer(round(Y)), FEnemyType, FLives) = -1 then dead;
  159.   X := FXCor - (MainForm.ScrollP * RasterW);
  160. end;
  161.  
  162. constructor TEnemy.Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer);
  163. begin
  164.   inherited Create(AParent);
  165.   if AEnemyType = etEnemyAttacker then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker);
  166.   if AEnemyType = etEnemyAttacker2 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker2);
  167.   if AEnemyType = etEnemyAttacker3 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker3);
  168.   if AEnemyType = etEnemyMeteor then Image := MainForm.GetSpriteGraphic(smgEnemyMeteor);
  169.   if AEnemyType = etEnemyUFO then Image := MainForm.GetSpriteGraphic(smgEnemyDisk);
  170.   if AEnemyType = etEnemyUFO2 then Image := MainForm.GetSpriteGraphic(smgEnemyDisk2);
  171.   if AEnemyType = etEnemyBoss then Image := MainForm.GetSpriteGraphic(smgEnemyBoss);
  172.  
  173.   if AEnemyType = etEnemyMeteor then FLives := 0 else FLives := ALives;
  174.   FEnemyType := AEnemyType;
  175.   Width := Image.Width;
  176.   Height := Image.Height;
  177.   PixelCheck := True;
  178. end;
  179.  
  180. { TMainForm }
  181.  
  182. procedure TMainForm.DXInit;
  183. begin
  184.   Imagelist.Items.LoadFromFile(OwnDirectory+'DirectX\Graphics.dxg');
  185.   ImageList.Items.MakeColorTable;
  186.   DXDraw.ColorTable := ImageList.Items.ColorTable;
  187.   DXDraw.DefColorTable := ImageList.Items.ColorTable;
  188.   DXDraw.UpdatePalette;
  189.   DXDraw.Initialize;
  190. end;
  191.  
  192. procedure TMainForm.FormCreate(Sender: TObject);
  193. resourcestring
  194.   SFileError = 'Die Datei kann von SpaceMission nicht geöffnet werden!';
  195. begin
  196.   { VCL-Ersatz start }
  197.   dxtimer := tdxtimer.create(self);
  198.   dxtimer.Interval := 100;
  199.   dxtimer.ActiveOnly := false;
  200.   dxtimer.Enabled := false;
  201.   dxtimer.OnTimer := DxTimerTimer;
  202.  
  203.   dxdraw := tdxdraw.Create(self);
  204.   dxdraw.Parent := self;
  205.   dxdraw.Left := 0;
  206.   dxdraw.Top := 0;
  207.   dxdraw.Width := SidePanel.Left;
  208.   dxdraw.Height := ScrollBar.Top;
  209.   dxdraw.AutoInitialize := False;
  210.   dxdraw.AutoSize := False;
  211.   dxdraw.Color := clBlack;
  212.   (*
  213.   dxdraw.Display.BitCount := 24;
  214.   dxdraw.Display.FixedBitCount := False;
  215.   dxdraw.Display.FixedRatio := False;
  216.   dxdraw.Display.FixedSize := False;
  217.   dxdraw.Display.Height := 600;
  218.   dxdraw.Display.Width := 800;
  219.   *)
  220.   dxdraw.Options := [doAllowReboot, doWaitVBlank, doAllowPalette256, doCenter, {doRetainedMode,} doHardware, doSelectDriver];
  221.   dxdraw.OnFinalize := DXDrawFinalize;
  222.   dxdraw.OnInitialize := DXDrawInitialize;
  223.   dxdraw.ParentShowHint := False;
  224.   dxdraw.ShowHint := False;
  225.   dxdraw.TabOrder := 0;
  226.   dxdraw.OnMouseDown := DXDrawMouseDown;
  227.   dxdraw.OnMouseMove := DXDrawMouseMove;
  228.  
  229.   spriteengine := tdxspriteengine.create(self);
  230.   spriteengine.DXDraw := dxdraw;
  231.  
  232.   imagelist := tdximagelist.create(self);
  233.   imagelist.DXDraw := dxdraw;
  234.  
  235.   { VCL-Ersatz ende }
  236.  
  237.   LivesEdit.MinValue := 1;
  238.   LivesEdit.MaxValue := MaxPossibleEnemyLives;
  239.   LivesEdit.Value := 1;
  240.  
  241.   Enemy1.Checked := true;
  242.   EnemyClick(Enemy1);
  243.   // Leeres Level am Anfang braucht keine Beenden-Bestätigung.
  244.   // LevChanged := true;
  245.  
  246.   //Application.Title := 'SpaceMission '+ProgramVersion+' - Leveleditor';
  247.   Caption := 'SpaceMission '+ProgramVersion+' - Leveleditor';
  248.   DXInit;
  249.   LevData := TLevelData.create;
  250.   ProgramInit;
  251.   DestroyLevel;
  252.   if (paramcount > 0) and (fileexists(paramstr(1))) and (ExtractFileExt(paramstr(1)).ToLower = '.lev') then
  253.   begin
  254.     try
  255.       LevData.RasterErzwingen := true;
  256.       LevData.LoadFromFile(paramstr(1));
  257.     except
  258.       on E: Exception do
  259.       begin
  260.         showmessage(SFileError + ' ' +E.Message);
  261.         DestroyLevel;
  262.       end;
  263.     end;
  264.     RefreshFromLevData;
  265.     LevChanged := false;
  266.     AnzeigeAct;
  267.   end;
  268. end;
  269.  
  270. procedure TMainForm.FormDestroy(Sender: TObject);
  271. var
  272.   tmp: string;
  273. begin
  274.   FreeAndNil(dxdraw);
  275.   FreeAndNil(LevData);
  276.   //FreeAndNil(spriteengine);
  277.   FreeAndNil(dxtimer);
  278.   FreeAndNil(imagelist);
  279.   tmp := GetTestlevelFilename;
  280.  
  281.   // SpaceMission.exe only loads a file once, so we can delete any test level
  282.   if FileExists(tmp) then DeleteFile(GetTestlevelFilename);
  283. end;
  284.  
  285. procedure TMainForm.BeendenClick(Sender: TObject);
  286. begin
  287.   close;
  288. end;
  289.  
  290. procedure TMainForm.DXDrawInitialize(Sender: TObject);
  291. begin
  292.   if Assigned(DXTimer) then DXTimer.Enabled := True;
  293. end;
  294.  
  295. procedure TMainForm.DXDrawFinalize(Sender: TObject);
  296. begin
  297.   if Assigned(DXTimer) then DXTimer.Enabled := False;
  298. end;
  299.  
  300. procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
  301. begin
  302.   if not DXDraw.CanDraw then exit;
  303.   LagCount := 1000 div 60;
  304.   SpriteEngine.Move(LagCount);
  305.   SpriteEngine.Dead;
  306.   DxDraw.Surface.Fill(0);
  307.   SpriteEngine.Draw;
  308.   DXDraw.Flip;
  309. end;
  310.  
  311. function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
  312. begin
  313.   with Result do
  314.   begin
  315.     rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256);
  316.     rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256);
  317.     rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256);
  318.     rgbReserved := 0;
  319.   end;
  320. end;
  321.  
  322. procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer);
  323. var
  324.   i: Integer;
  325.   t, t2: DWORD;
  326.   ChangePalette: Boolean;
  327.   c: Integer;
  328. begin
  329.   if DXDraw.Initialized then
  330.   begin
  331.     c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue));
  332.     ChangePalette := False;
  333.     if DXDraw.CanPaletteAnimation then
  334.     begin
  335.       t := GetTickCount;
  336.       while Abs(GetTickCount-t)<Time do
  337.       begin
  338.         t2 := Trunc(Abs(GetTickCount-t)/Time*255);
  339.         for i := 0 to 255 do
  340.           DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2);
  341.         DXDraw.UpdatePalette;
  342.         ChangePalette := True;
  343.       end;
  344.     end else
  345.       Sleep(Time);
  346.     for i := 0 to 4 do
  347.     begin
  348.       DXDraw.Surface.Fill(c);
  349.       DXDraw.Flip;
  350.     end;
  351.     if ChangePalette then
  352.     begin
  353.       DXDraw.ColorTable := DXDraw.DefColorTable;
  354.       DXDraw.UpdatePalette;
  355.     end;
  356.     DXDraw.Surface.Fill(c);
  357.     DXDraw.Flip;
  358.   end;
  359. end;
  360.  
  361. procedure TMainForm.ProgramInit;
  362. {var
  363.   i, j: Integer;}
  364. begin
  365.   sleep(500);
  366.   //PlayerSprite
  367.   with TBackground.Create(SpriteEngine.Engine) do
  368.   begin
  369.     SetMapSize(1, 1);
  370.     Image := MainForm.GetSpriteGraphic(smgStar3);
  371.     Z := -13;
  372.     Y := 40;
  373.     Tile := True;
  374.   end;
  375.   with TBackground.Create(SpriteEngine.Engine) do
  376.   begin
  377.     SetMapSize(1, 1);
  378.     Image := MainForm.GetSpriteGraphic(smgStar2);
  379.     Z := -12;
  380.     Y := 30;
  381.     Tile := True;
  382.   end;
  383.   with TBackground.Create(SpriteEngine.Engine) do
  384.   begin
  385.     SetMapSize(1, 1);
  386.     Image := MainForm.GetSpriteGraphic(smgStar1);
  387.     Z := -11;
  388.     Y := 10;
  389.     Tile := True;
  390.   end;
  391.   with TBackground.Create(SpriteEngine.Engine) do
  392.   begin
  393.     SetMapSize(1, 1);
  394.     Image := MainForm.GetSpriteGraphic(smgMatrix);
  395.     Z := -10;
  396.     Tile := True;
  397.   end;
  398.   {with TBackground.Create(SpriteEngine.Engine) do
  399.   begin
  400.     SetMapSize(200, 10);
  401.     Y := 10;
  402.     Z := -13;
  403.     FSpeed := 1 / 2;
  404.     Tile := True;
  405.     for i := 0 to MapHeight-1 do
  406.     begin
  407.       for j := 0 to MapWidth-1 do
  408.       begin
  409.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8);
  410.         if Random(100)<95 then Chips[j, i] := -1;
  411.       end;
  412.     end;
  413.   end;
  414.   with TBackground.Create(SpriteEngine.Engine) do
  415.   begin
  416.     SetMapSize(200, 10);
  417.     Y := 30;
  418.     Z := -12;
  419.     FSpeed := 1;
  420.     Tile := True;
  421.     for i := 0 to MapHeight-1 do
  422.     begin
  423.       for j := 0 to MapWidth-1 do
  424.       begin
  425.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4);
  426.         if Random(100)<95 then Chips[j, i] := -1;
  427.       end;
  428.     end;
  429.   end;
  430.   with TBackground.Create(SpriteEngine.Engine) do
  431.   begin
  432.     SetMapSize(200, 10);
  433.     Y := 40;
  434.     Z := -11;
  435.     FSpeed := 2;
  436.     Tile := True;
  437.     for i := 0 to MapHeight-1 do
  438.     begin
  439.       for j := 0 to MapWidth-1 do
  440.       begin
  441.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2);
  442.         if Random(100)<95 then Chips[j, i] := -1;
  443.       end;
  444.     end;
  445.   end;}
  446.   PalleteAnim(RGBQuad(0, 0, 0), 300);
  447.   mainform.Visible := true;
  448. end;
  449.  
  450. procedure TMainForm.RefreshFromLevData;
  451. var
  452.   i: integer;
  453. begin
  454.   MainForm.ScrollBar.Max := MainForm.LevData.LevelEditorLength;
  455.   for i := 0 to MainForm.LevData.CountEnemies - 1 do
  456.   begin
  457.     MainForm.EnemyCreateSprite(
  458.       MainForm.LevData.EnemyAdventTable[i].x,
  459.       MainForm.LevData.EnemyAdventTable[i].y,
  460.       MainForm.LevData.EnemyAdventTable[i].enemyType,
  461.       MainForm.LevData.EnemyAdventTable[i].lifes
  462.     );
  463.   end;
  464.   MainForm.NumEnemys := MainForm.LevData.CountEnemies;
  465.   MainForm.Boss := MainForm.LevData.HasBoss;
  466.   AnzeigeAct;
  467. end;
  468.  
  469. procedure TMainForm.LevelClick(Sender: TObject);
  470. begin
  471.   speicherungform.showmodal;
  472. end;
  473.  
  474. procedure TMainForm.Leveltesten1Click(Sender: TObject);
  475. var
  476.   sav: TSaveData;
  477.   tmp: string;
  478. begin
  479.   KillTask('SpaceMission.exe');
  480.  
  481.   sav := TSaveData.Create;
  482.   try
  483.     sav.Score := 0;
  484.     sav.Life := 6;
  485.     if Assigned(SpeicherungForm) then
  486.       sav.Level := SpeicherungForm.LevelNumber.Value
  487.     else
  488.       sav.Level := 1;
  489.     sav.GameMode := gmLevels;
  490.     sav.LevelData := TlevelData.Create;
  491.     sav.LevelData.Assign(LevData);
  492.     tmp := GetTestlevelFilename;
  493.     sav.SaveToFile(tmp);
  494.     ShellExecute(Handle, 'open', PChar(OwnDirectory+'SpaceMission.exe'), PChar('"'+tmp+'"'), PChar(OwnDirectory), SW_NORMAL);
  495.   finally
  496.     FreeAndNil(sav);
  497.   end;
  498. end;
  499.  
  500. procedure TMainForm.FormShow(Sender: TObject);
  501. begin
  502.   if Assigned(SplashForm) then
  503.   begin
  504.     SplashForm.Hide;
  505.     FreeAndNil(SplashForm);
  506.   end;
  507.  
  508.   dxtimer.Enabled := true;
  509.   dxtimer.ActiveOnly := true;
  510. end;
  511.  
  512. function TMainForm.GetSpriteGraphic(
  513.   Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
  514. begin
  515.   if (Sprite<>smgNone) and (imagelist.Items.Count >= Ord(Sprite)) then
  516.     result := imagelist.Items.Items[Ord(Sprite)-1]
  517.   else
  518.     result := nil;
  519. end;
  520.  
  521. function TMainForm.GetTestlevelFilename: string;
  522. begin
  523.   result := IncludeTrailingPathDelimiter(TPath.GetTempPath) + 'SpaceMissionTest.sav';
  524. end;
  525.  
  526. procedure TMainForm.HilfeTopicClick(Sender: TObject);
  527. // Please keep this code in-sync with GamMain.pas
  528. var
  529.   bakTimerEnabled: boolean;
  530. begin
  531.   bakTimerEnabled := dxtimer.Enabled;
  532.   try
  533.     dxtimer.Enabled := false;
  534.     HilfeForm.Caption := TMenuItem(Sender).Caption;
  535.     HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&&', #1, [rfReplaceAll]);
  536.     HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&', '', [rfReplaceAll]);
  537.     HilfeForm.Caption := StringReplace(HilfeForm.Caption, #1, '&', [rfReplaceAll]);
  538.     HilfeForm.ShowMarkDownHelp(OwnDirectory+TMenuItem(Sender).Hint);
  539.     HilfeForm.ShowModal;
  540.   finally
  541.     dxtimer.Enabled := bakTimerEnabled;
  542.   end;
  543. end;
  544.  
  545. procedure TMainForm.InformationenClick(Sender: TObject);
  546. begin
  547.   mainform.dxtimer.enabled := false;
  548.   InfoForm.showmodal;
  549.   mainform.dxtimer.enabled := true;
  550. end;
  551.  
  552. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
  553. begin
  554.   SpriteEngine.Engine.Clear;
  555.   DXTimer.Enabled := False;
  556. end;
  557.  
  558. procedure TMainForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton;
  559.   Shift: TShiftState; X, Y: Integer);
  560. var
  561.   i, j, k, l, ex, ey: integer;
  562.   ok, breaked: boolean;
  563. begin
  564.   ex := trunc(x/RasterW) * RasterW;
  565.   ey := trunc(y/RasterH) * RasterH;
  566.   EnemyCreateSprite(ex, ey, SelectedEnemyType, LivesEdit.Value);
  567.   breaked := false;
  568.   { Setzen }
  569.   if Button = mbLeft then
  570.   begin
  571.     ok := true;
  572.     if (SelectedEnemyType = etEnemyBoss) and boss then
  573.       ok := false // boss already exists
  574.     else
  575.     begin
  576.       for i := 1 to NumEnemyTypes do
  577.       begin
  578.         for j := 0 to MaxPossibleEnemyLives do
  579.         begin
  580.           if boss then
  581.           begin
  582.             for k := 0 to 3 do
  583.             begin
  584.               for l := 0 to 1 do
  585.               begin
  586.                 if LevData.IndexOfEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), etEnemyBoss, j) <> -1 then
  587.                 begin
  588.                   ok := false;
  589.                   break;
  590.                 end;
  591.               end;
  592.               if not ok then break;
  593.             end;
  594.             if not ok then break;
  595.           end;
  596.           if LevData.IndexOfEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j) <> -1 then
  597.           begin
  598.             ok := false;
  599.             break;
  600.           end;
  601.         end;
  602.         if not ok then break;
  603.       end;
  604.     end;
  605.     if ok then
  606.     begin
  607.       if SelectedEnemyType <> etEnemyMeteor then
  608.         LevData.AddEnemy(ex + (ScrollP * RasterW), ey, SelectedEnemyType, LivesEdit.Value)
  609.       else
  610.         LevData.AddEnemy(ex + (ScrollP * RasterW), ey, SelectedEnemyType, 0);
  611.       inc(NumEnemys);
  612.       if SelectedEnemyType = etEnemyBoss then boss := true;
  613.     end
  614.     else beep;
  615.   end
  616.   { Löschen }
  617.   else if Button = mbRight then
  618.   begin
  619.     for i := 1 to NumEnemyTypes do
  620.     begin
  621.       for j := 0 to MaxPossibleEnemyLives do
  622.       begin
  623.         if boss and (TEnemyType(i) = etEnemyBoss) then
  624.         begin
  625.           for k := 0 to 3 do
  626.           begin
  627.             for l := 0 to 1 do
  628.             begin
  629.               if LevData.IndexOfEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), TEnemyType(i), j) <> -1 then
  630.               begin
  631.                 LevData.DeleteEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), TEnemyType(i), j);
  632.                 Boss := false;
  633.                 dec(NumEnemys);
  634.                 breaked := true;
  635.                 break;
  636.               end;
  637.             end;
  638.             if breaked then break;
  639.           end;
  640.         end;
  641.         if LevData.IndexOfEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j) <> -1 then
  642.         begin
  643.           LevData.DeleteEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j);
  644.           if TEnemyType(i) = etEnemyBoss then Boss := false;
  645.           dec(NumEnemys);
  646.           breaked := true;
  647.           break;
  648.         end;
  649.       end;
  650.       if breaked then break;
  651.     end;
  652.   end;
  653.   LevChanged := true;
  654.   AnzeigeAct;
  655. end;
  656.  
  657. procedure TMainForm.EnemyClick(Sender: TObject);
  658. var
  659.   et: TEnemyType;
  660. begin
  661.   et := SelectedEnemyType;
  662.   Image1.Left := -(87 * (Ord(et) - 1)) + 1;
  663.   LivesEdit.Enabled := et <> etEnemyMeteor;
  664.   LivesLabel.Enabled := et <> etEnemyMeteor;
  665. end;
  666.  
  667. procedure TMainForm.EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer);
  668. var
  669.   Enemy: TSprite;
  670. begin
  671.   Enemy := TEnemy.Create(SpriteEngine.Engine, AEnemyType, ALives);
  672.   Enemy.x := x;
  673.   Enemy.y := y;
  674. end;
  675.  
  676. procedure TMainForm.DestroyLevel;
  677. begin
  678.   ScrollBar.Position := 0; // this doesn't call ScrollBarScroll()
  679.   ScrollP := 0;
  680.   LevData.Clear;
  681.   ScrollBar.Max := LevData.LevelEditorLength;
  682.   NumEnemys := 0;
  683.   Boss := false;
  684.   LevChanged := true;
  685.   LivesEdit.Value := 1;
  686.   Enemy1.Checked := true;
  687.   EnemyClick(Enemy1);
  688.   AnzeigeAct;
  689. end;
  690.  
  691. procedure TMainForm.AlleLeveldateienaktualisieren1Click(Sender: TObject);
  692. var
  693.   i: integer;
  694. begin
  695.   // Just for internal/development purposes
  696.   for i := 1 to MaxPossibleLevels do
  697.   begin
  698.     if FileExists('Levels\Level '+IntToStr(i)+'.lev') then
  699.     begin
  700.       LevData.RasterErzwingen := true;
  701.       LevData.LoadFromFile('Levels\Level '+IntToStr(i)+'.lev');
  702.       LevData.SaveToFile('Levels\Level '+IntToStr(i)+'.lev');
  703.     end;
  704.   end;
  705. end;
  706.  
  707. procedure TMainForm.AnzeigeAct;
  708. begin
  709.   SLabel1b.Caption := inttostr(NumEnemys);
  710.   if Boss then SLabel2b.Caption := 'Ja' else SLabel2b.Caption := 'Nein';
  711.   SLabel3b.Caption := inttostr(ScrollBar.Max);
  712.   if LevChanged then
  713.   begin
  714.     SLabel4a.Font.Color := $00000096;
  715.     SLabel4b.Font.Color := $00000096;
  716.     SLabel4b.Caption := 'Nein';
  717.   end
  718.   else
  719.   begin
  720.     SLabel4a.Font.Color := $00009600;
  721.     SLabel4b.Font.Color := $00009600;
  722.     SLabel4b.Caption := 'Ja';
  723.   end;
  724. end;
  725.  
  726. procedure TMainForm.AufUpdatesprfen1Click(Sender: TObject);
  727. begin
  728.   CheckForUpdates('spacemission');
  729. end;
  730.  
  731. procedure TMainForm.NeuClick(Sender: TObject);
  732. begin
  733.   if MessageDlg('Level wirklich löschen?', mtConfirmation, mbYesNoCancel, 0) = mrYes then
  734.     DestroyLevel;
  735. end;
  736.  
  737. procedure TMainForm.DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X,
  738.   Y: Integer);
  739. resourcestring
  740.   status_info = 'Zeigen Sie mit dem Mauszeiger auf eine Einheit, um deren Eigenschaften anzuzeigen...';
  741.   status_lives = 'Leben: ';
  742.   status_nolives = 'Einheit hat keine Lebensangabe';
  743. var
  744.   ex, ey, i, j, k, l: integer;
  745.   lifes: integer;
  746.   enemyType: TEnemyType;
  747.   enemyName: string;
  748.   breaked: boolean;
  749. begin
  750.   if sender <> DxDraw then
  751.   begin
  752.     StatusBar.SimpleText := ' ' + status_info;
  753.     exit;
  754.   end;
  755.   ex := trunc(x/RasterW) * RasterW;
  756.   ey := trunc(y/RasterH) * RasterH;
  757.   lifes := -1;
  758.   enemyType := etUnknown;
  759.   breaked := false;
  760.   for i := 1 to NumEnemyTypes do
  761.   begin
  762.     for j := 0 to MaxPossibleEnemyLives do
  763.     begin
  764.       if boss and (TEnemyType(i) = etEnemyBoss) then
  765.       begin
  766.         for k := 0 to 3 do
  767.         begin
  768.           for l := 0 to 1 do
  769.           begin
  770.             if LevData.IndexOfEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), TEnemyType(i), j) <> -1 then
  771.             begin
  772.               lifes := j;
  773.               breaked := true;
  774.               break;
  775.             end;
  776.           end;
  777.           if breaked then break;
  778.         end;
  779.       end;
  780.       if (breaked = false) and (LevData.IndexOfEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j) <> -1) then
  781.       begin
  782.         lifes := j;
  783.         enemyType := TEnemyType(i);
  784.         breaked := true;
  785.         break;
  786.       end;
  787.     end;
  788.     if breaked then break;
  789.   end;
  790.   if lifes <> -1 then
  791.   begin
  792.     if Ord(enemyType) = 1 then enemyName := Enemy1.Caption
  793.     else if Ord(enemyType) = 2 then enemyName := Enemy2.Caption
  794.     else if Ord(enemyType) = 3 then enemyName := Enemy3.Caption
  795.     else if Ord(enemyType) = 4 then enemyName := Enemy4.Caption
  796.     else if Ord(enemyType) = 5 then enemyName := Enemy5.Caption
  797.     else if Ord(enemyType) = 6 then enemyName := Enemy6.Caption
  798.     else if Ord(enemyType) = 7 then enemyName := Enemy7.Caption
  799.     else enemyName := '???';
  800.     if lifes > 0 then
  801.       StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_lives + inttostr(lifes)
  802.     else
  803.       StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_nolives;
  804.   end
  805.   else
  806.     StatusBar.SimpleText := ' ' + status_info;
  807. end;
  808.  
  809. procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  810. begin
  811.   if Assigned(LevData) and LevChanged and (LevData.CountEnemies>0) then
  812.     CanClose := MessageDlg('Beenden ohne abspeichern?', mtConfirmation, mbYesNoCancel, 0) = mrYes;
  813. end;
  814.  
  815. procedure TMainForm.Spielfelderweitern1Click(Sender: TObject);
  816. begin
  817.   LevelForm.Aktualisieren;
  818.   LevelForm.showmodal;
  819. end;
  820.  
  821. procedure TMainForm.ScrollBarScroll(Sender: TObject;
  822.   ScrollCode: TScrollCode; var ScrollPos: Integer);
  823. begin
  824.   ScrollP := ScrollPos;
  825. end;
  826.  
  827. function TMainForm.SelectedEnemyType: TEnemyType;
  828. begin
  829.   if Enemy1.Checked then result := etEnemyAttacker
  830.   else if Enemy2.Checked then result := etEnemyAttacker2
  831.   else if Enemy3.Checked then result := etEnemyAttacker3
  832.   else if Enemy4.Checked then result := etEnemyMeteor
  833.   else if Enemy5.Checked then result := etEnemyUFO
  834.   else if Enemy6.Checked then result := etEnemyUFO2
  835.   else if Enemy7.Checked then result := etEnemyBoss
  836.   else result := etUnknown;
  837. end;
  838.  
  839. end.
  840.  
  841.