Subversion Repositories spacemission

Rev

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