Subversion Repositories spacemission

Rev

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