Subversion Repositories spacemission

Rev

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

  1. unit GamMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, ExtCtrls, Menus, DIB, DXClass, DXSprite, DXDraws, DXInput, DXSounds,
  8.   ShellAPI, wininet, DirectX{$IF CompilerVersion >= 23.0},
  9.   System.UITypes{$IFEND}, ComLevelReader, ComSaveGameReader, DirectMusic, Global;
  10.  
  11. type
  12.   TGameScene = (
  13.     gsNone,
  14.     gsTitle,
  15.     gsMain,
  16.     gsGameOver,
  17.     gsNewLevel,
  18.     gsWin
  19.   );
  20.  
  21.   TGameInterval = (
  22.     giLeicht,
  23.     giMittel,
  24.     giSchwer,
  25.     giMaster
  26.   );
  27.  
  28.   TBackground = class(TBackgroundSprite)
  29.   strict private
  30.     FSpeed: Double;
  31.   strict protected
  32.     procedure DoMove(MoveCount: Integer); override;
  33.   public
  34.     property Speed: Double read FSpeed write FSpeed;
  35.   end;
  36.  
  37.   TBackgroundSpecial = class(TBackgroundSprite)
  38.   strict private
  39.     FSpeed: Double;
  40.   strict protected
  41.     procedure DoMove(MoveCount: Integer); override;
  42.   public
  43.     property Speed: Double read FSpeed write FSpeed;
  44.   end;
  45.  
  46.   TExplosion = class(TImageSprite)
  47.   strict private
  48.     FCounter: Integer;
  49.   strict protected
  50.     procedure DoMove(MoveCount: Integer); override;
  51.   public
  52.     constructor Create(AParent: TSprite); override;
  53.   end;
  54.  
  55.   TPlayerOrEnemyState = (
  56.     pesUnknown,
  57.     pesNormal,
  58.     pesExploding, // only boss, as preparation of pesDead
  59.     pesDead,
  60.     pesDeadVanished,
  61.     pesFlyaway, // only player at mission end
  62.     pesEntering,
  63.     pesHovering // only some kind of enemies
  64.   );
  65.  
  66.   TPlayerOrEnemy = class abstract (TImageSprite)
  67.   strict protected
  68.     State: TPlayerOrEnemyState;
  69.   end;
  70.  
  71.   TPlayerSprite = class(TPlayerOrEnemy)
  72.   private
  73.     FTamaCount: Integer; // accessed by TPlayerTamaSprite.Destroy
  74.   strict private
  75.     FCounter: Integer;
  76.     FOldTamaTime: Integer;
  77.   strict protected
  78.     procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
  79.     procedure DoMove(MoveCount: Integer); override;
  80.   public
  81.     constructor Create(AParent: TSprite); override;
  82.     procedure FlyAway;
  83.   end;
  84.  
  85.   TPlayerTamaSprite = class(TImageSprite)
  86.   strict private
  87.     FPlayerSprite: TPlayerSprite;
  88.   strict protected
  89.     property PlayerSprite: TPlayerSprite read FPlayerSprite write FPlayerSprite;
  90.     procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
  91.     procedure DoMove(MoveCount: Integer); override;
  92.   public
  93.     constructor Create(AParent: TSprite; APlayerSprite: TPlayerSprite); reintroduce;
  94.     destructor Destroy; override;
  95.   end;
  96.  
  97.   TEnemyClass = class of TEnemy;
  98.   TEnemy = class abstract (TPlayerOrEnemy)
  99.   strict protected
  100.     FCounter: Integer;
  101.     FLife: integer;
  102.     procedure HitEnemy(ADead: Boolean); virtual;
  103.   public
  104.     property Life: integer read FLife;
  105.     procedure Hit(AHitStrength: integer = 1);
  106.     constructor Create(AParent: TSprite; ALifes: integer); reintroduce; virtual;
  107.     destructor Destroy; override;
  108.   end;
  109.  
  110.   TEnemyTama = class(TImageSprite)
  111.   strict private
  112.     FEnemySprite: TSprite;
  113.   strict protected
  114.     property EnemySprite: TSprite read FEnemySprite write FEnemySprite;
  115.     procedure DoMove(MoveCount: Integer); override;
  116.   public
  117.     constructor Create(AParent: TSprite; AEnemySprite: TSprite); reintroduce;
  118.   end;
  119.  
  120.   TEnemyMeteor = class(TEnemy)
  121.   strict protected
  122.     procedure DoMove(MoveCount: Integer); override;
  123.     procedure HitEnemy(ADead: Boolean); override;
  124.   public
  125.     constructor Create(AParent: TSprite; ALifes: integer); override;
  126.   end;
  127.  
  128.   TEnemyUFO = class(TEnemy)
  129.   strict protected
  130.     procedure DoMove(MoveCount: Integer); override;
  131.     procedure HitEnemy(ADead: Boolean); override;
  132.   public
  133.     constructor Create(AParent: TSprite; ALifes: integer); override;
  134.   end;
  135.  
  136.   TEnemyUFO2 = class(TEnemy)
  137.   strict private
  138.     FCounter: Integer;
  139.     FTamaCount: Integer;
  140.     FOldTamaTime: Integer;
  141.   strict protected
  142.     procedure DoMove(MoveCount: Integer); override;
  143.     procedure HitEnemy(ADead: Boolean); override;
  144.   public
  145.     constructor Create(AParent: TSprite; ALifes: integer); override;
  146.   end;
  147.  
  148.   TEnemyAttacker = class(TEnemy)
  149.   strict protected
  150.     procedure DoMove(MoveCount: Integer); override;
  151.     procedure HitEnemy(ADead: Boolean); override;
  152.   public
  153.     constructor Create(AParent: TSprite; ALifes: integer); override;
  154.   end;
  155.  
  156.   TEnemyAttacker2 = class(TEnemy)
  157.   strict private
  158.     FCounter: Integer;
  159.     FTamaF: Integer;
  160.     FTamaT: Integer;
  161.     FPutTama: Boolean;
  162.   strict protected
  163.     procedure DoMove(MoveCount: Integer); override;
  164.     procedure HitEnemy(ADead: Boolean); override;
  165.   public
  166.     constructor Create(AParent: TSprite; ALifes: integer); override;
  167.   end;
  168.  
  169.   TEnemyAttacker3 = class(TEnemy)
  170.   strict private
  171.     FCounter: Integer;
  172.     FTamaCount: Integer;
  173.     FOldTamaTime: Integer;
  174.   strict protected
  175.     procedure DoMove(MoveCount: Integer); override;
  176.     procedure HitEnemy(ADead: Boolean); override;
  177.   public
  178.     constructor Create(AParent: TSprite; ALifes: integer); override;
  179.   end;
  180.  
  181.   TEnemyBoss = class(TEnemy)
  182.   strict private
  183.     FCounter: Integer;
  184.     FTamaF: Integer;
  185.     FTamaT: Integer;
  186.     FPutTama: Boolean;
  187.     waiter1, waiter2: integer;
  188.   strict protected
  189.     procedure DoMove(MoveCount: Integer); override;
  190.     procedure HitEnemy(ADead: Boolean); override;
  191.   public
  192.     constructor Create(AParent: TSprite; ALifes: integer); override;
  193.   end;
  194.  
  195.   TMainForm = class(TDXForm)
  196.     MainMenu: TMainMenu;
  197.     Spiel: TMenuItem;
  198.     GameStart: TMenuItem;
  199.     GamePause: TMenuItem;
  200.     Beenden: TMenuItem;
  201.     Einstellungen: TMenuItem;
  202.     OptionMusic: TMenuItem;
  203.     Leer2: TMenuItem;
  204.     Hilfe: TMenuItem;
  205.     OptionSound: TMenuItem;
  206.     Leer3: TMenuItem;
  207.     Spielstand: TMenuItem;
  208.     Leer5: TMenuItem;
  209.     Neustart: TMenuItem;
  210.     Spielgeschwindigkeit: TMenuItem;
  211.     Leicht: TMenuItem;
  212.     Mittel: TMenuItem;
  213.     Schwer: TMenuItem;
  214.     Informationen: TMenuItem;
  215.     Leer6: TMenuItem;
  216.     Leer1: TMenuItem;
  217.     Cheat: TMenuItem;
  218.     CheckUpdates: TMenuItem;
  219.     Master: TMenuItem;
  220.     procedure DXDrawFinalize(Sender: TObject);
  221.     procedure DXDrawInitialize(Sender: TObject);
  222.     procedure FormCreate(Sender: TObject);
  223.     procedure DXTimerTimer(Sender: TObject; LagCount: Integer);
  224.     procedure DXTimerActivate(Sender: TObject);
  225.     procedure DXTimerDeactivate(Sender: TObject);
  226.     procedure DXDrawInitializing(Sender: TObject);
  227.     procedure GameStartClick(Sender: TObject);
  228.     procedure GamePauseClick(Sender: TObject);
  229.     procedure BeendenClick(Sender: TObject);
  230.     procedure OptionSoundClick(Sender: TObject);
  231.     procedure OptionMusicClick(Sender: TObject);
  232.     procedure SpielstandClick(Sender: TObject);
  233.     procedure NeustartClick(Sender: TObject);
  234.     procedure LeichtClick(Sender: TObject);
  235.     procedure MittelClick(Sender: TObject);
  236.     procedure SchwerClick(Sender: TObject);
  237.     procedure FormShow(Sender: TObject);
  238.     procedure InformationenClick(Sender: TObject);
  239.     procedure CheatClick(Sender: TObject);
  240.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  241.     procedure FormDestroy(Sender: TObject);
  242.     procedure CheckUpdatesClick(Sender: TObject);
  243.     procedure MasterClick(Sender: TObject);
  244.   private
  245.     ProgrammGestartet: boolean;
  246.     FInterval: TGameInterval;
  247.     FScene: TGameScene;
  248.     FMusic: TSpaceMissionMusicTrack;
  249.     FBlink: DWORD;
  250.     FBlinkTime: DWORD;
  251.     FFrame, FAngle, FCounter, FEnemyAdventPos: Integer;
  252.     PlayerSprite: TPlayerSprite;
  253.     TimerCS: TRTLCriticalSection;
  254.     LevelData: TLevelData;
  255.     procedure StartScene(Scene: TGameScene);
  256.     procedure EndScene;
  257.     procedure BlinkStart;
  258.     procedure BlinkUpdate;
  259.     procedure StartSceneTitle;
  260.     procedure SceneTitle;
  261.     procedure EndSceneTitle;
  262.     procedure StartSceneMain;
  263.     procedure SceneMain;
  264.     procedure EndSceneMain;
  265.     procedure StartSceneGameOver;
  266.     procedure SceneGameOver;
  267.     procedure EndSceneGameOver;
  268.     procedure StartSceneWin;
  269.     procedure SceneWin;
  270.     procedure EndSceneWin;
  271.     procedure StartSceneNewLevel;
  272.     procedure SceneNewLevel;
  273.     procedure EndSceneNewLevel;
  274.   public
  275.     FNextScene: TGameScene;
  276.     FScore: Integer;
  277.     FNotSave: boolean;
  278.     FLife: integer;
  279.     FLevel: integer;
  280.     FGameMode: TGameMode;
  281.     FBossLife: integer;
  282.     FRestEnemies: integer;
  283.     FCheat: boolean;
  284.     { VCL-Ersatz }
  285.     dxdraw: TDxDraw;
  286.     imagelist: TDxImageList;
  287.     spriteengine: tdxspriteengine;
  288.     dxsound: tdxsound;
  289.     dxmusic: tdxmusic;
  290.     wavelist: tdxwavelist;
  291.     dxinput: tdxinput;
  292.     dxtimer: tdxtimer;
  293.     { Level-Routinen }
  294.     procedure NewLevel(lev: integer);
  295.     procedure ResetLevelData;
  296.     { Musik-Routinen }
  297.     procedure MusicSwitchTrack(Name: TSpaceMissionMusicTrack);
  298.     procedure PlayMusic(Name: TSpaceMissionMusicTrack);
  299.     procedure StopMusic(Name: TSpaceMissionMusicTrack);
  300.     procedure ResumeMusic(Name: TSpaceMissionMusicTrack);
  301.     procedure PauseMusic(Name: TSpaceMissionMusicTrack);
  302.     { Sound-Routinen }
  303.     procedure PlaySound(Sound: TSpaceMissionSound; Wait: Boolean);
  304.     { Grafik-Routinen }
  305.     function GetSpriteGraphic(Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
  306.     { Initialisiations-Routinen }
  307.     procedure DXInit;
  308.     procedure SoundInit;
  309.     procedure MusicInit;
  310.     { Einstellungs-Routinen }
  311.     procedure LoadOptions;
  312.     procedure WriteOptions;
  313.     { Farb-Routinen }
  314.     function ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
  315.     procedure PalleteAnim(Col: TRGBQuad; Time: Integer);
  316.   end;
  317.  
  318. var
  319.   MainForm: TMainForm;
  320.  
  321. implementation
  322.  
  323. uses
  324.   GamSplash, GamSpeicherung, ComInfo, GamCheat, MMSystem, Registry;
  325.  
  326. const
  327.   conleicht =  650 div 60; // 10
  328.   conmittel = 1000 div 60; // 16
  329.   conschwer = 1350 div 60; // 22
  330.   conmaster = 2000 div 60; // 33
  331.   lives = 6;
  332.   DEFAULT_ANIMSPEED = 15/1000;
  333.   ADDITIONAL_ENEMIES_PER_LEVEL = 75;
  334.  
  335. {$R *.DFM}
  336.  
  337. var
  338.   Crash2, EnemyCounter: integer;
  339.   BossExists, Crash, crashsound: boolean;
  340.  
  341. const
  342.   DXInputButton = [isButton1, isButton2, isButton3,
  343.     isButton4, isButton5, isButton6, isButton7, isButton8, isButton9, isButton10, isButton11,
  344.     isButton12, isButton13, isButton14, isButton15, isButton16, isButton17, isButton18,
  345.     isButton19, isButton20, isButton21, isButton22, isButton23, isButton24, isButton25,
  346.     isButton26, isButton27, isButton28, isButton29, isButton30, isButton31, isButton32];
  347.  
  348. // https://www.delphipraxis.net/post43515.html
  349. function GetHTML(AUrl: string): string;
  350. var
  351.   databuffer : array[0..4095] of char;
  352.   ResStr : string;
  353.   hSession, hfile: hInternet;
  354.   dwindex,dwcodelen,dwread,dwNumber: cardinal;
  355.   dwcode : array[1..20] of char;
  356.   res    : pchar;
  357.   Str    : pchar;
  358. begin
  359.   ResStr:='';
  360.   if (system.pos('http://',lowercase(AUrl))=0) and
  361.      (system.pos('https://',lowercase(AUrl))=0) then
  362.      AUrl:='http://'+AUrl;
  363.  
  364.   // Hinzugefügt
  365.   application.ProcessMessages;
  366.  
  367.   hSession:=InternetOpen('InetURL:/1.0',
  368.                          INTERNET_OPEN_TYPE_PRECONFIG,
  369.                          nil,
  370.                          nil,
  371.                          0);
  372.   if assigned(hsession) then
  373.   begin
  374.     // Hinzugefügt
  375.     application.ProcessMessages;
  376.  
  377.     hfile:=InternetOpenUrl(
  378.            hsession,
  379.            pchar(AUrl),
  380.            nil,
  381.            0,
  382.            INTERNET_FLAG_RELOAD,
  383.            0);
  384.     dwIndex  := 0;
  385.     dwCodeLen := 10;
  386.  
  387.     // Hinzugefügt
  388.     application.ProcessMessages;
  389.  
  390.     HttpQueryInfo(hfile,
  391.                   HTTP_QUERY_STATUS_CODE,
  392.                   @dwcode,
  393.                   dwcodeLen,
  394.                   dwIndex);
  395.     res := pchar(@dwcode);
  396.     dwNumber := sizeof(databuffer)-1;
  397.     if (res ='200') or (res ='302') then
  398.     begin
  399.       while (InternetReadfile(hfile,
  400.                               @databuffer,
  401.                               dwNumber,
  402.                               DwRead)) do
  403.       begin
  404.  
  405.         // Hinzugefügt
  406.         application.ProcessMessages;
  407.  
  408.         if dwRead =0 then
  409.           break;
  410.         databuffer[dwread]:=#0;
  411.         Str := pchar(@databuffer);
  412.         resStr := resStr + Str;
  413.       end;
  414.     end
  415.     else
  416.       ResStr := 'Status:'+res;
  417.     if assigned(hfile) then
  418.       InternetCloseHandle(hfile);
  419.   end;
  420.  
  421.   // Hinzugefügt
  422.   application.ProcessMessages;
  423.  
  424.   InternetCloseHandle(hsession);
  425.   Result := resStr;
  426. end;
  427.  
  428.  
  429. { TBackground }
  430.  
  431. procedure TBackground.DoMove(MoveCount: Integer);
  432. var
  433.   ran: integer;
  434. begin
  435.   inherited DoMove(MoveCount);
  436.   X := X - MoveCount*(60/1000)*FSpeed;
  437.   randomize;
  438.   ran := Random(1500);
  439.   if ran = 150 then
  440.   begin
  441.     with TBackgroundSpecial.Create(mainform.SpriteEngine.Engine) do
  442.     begin
  443.       SetMapSize(1, 1);
  444.       Image := MainForm.GetSpriteGraphic(smgBackgroundPlanet1);
  445.       Width := Image.Width;
  446.       Height := Image.Height;
  447.  
  448.       Y := random(mainform.dxdraw.height);
  449.       X := mainform.dxdraw.width;
  450.  
  451.       ran := Random(2);
  452.       if ran = 0 then
  453.       begin
  454.         Z := -20;
  455.         FSpeed := 1.8;
  456.       end
  457.       else if ran = 1 then
  458.       begin
  459.         Z := -40;
  460.         FSpeed := 0.8;
  461.       end
  462.       else if ran = 2 then
  463.       begin
  464.         Z := -60;
  465.         FSpeed := 0.3;
  466.       end;
  467.     end;
  468.   end
  469.   else if ran = 500 then
  470.   begin
  471.     with TBackgroundSpecial.Create(mainform.SpriteEngine.Engine) do
  472.     begin
  473.       SetMapSize(1, 1);
  474.       ran := Random(4);
  475.       if ran = 0 then
  476.         Image := MainForm.GetSpriteGraphic(smgBackgroundRed)
  477.       else if ran = 1 then
  478.         Image := MainForm.GetSpriteGraphic(smgBackgroundBlue)
  479.       else if ran = 2 then
  480.         Image := MainForm.GetSpriteGraphic(smgBackgroundYellow)
  481.       else if ran = 3 then
  482.         Image := MainForm.GetSpriteGraphic(smgHintergrundRot);
  483.       Width := Image.Width;
  484.       Height := Image.Height;
  485.  
  486.       Y := random(mainform.dxdraw.height);
  487.       X := mainform.dxdraw.width;
  488.  
  489.       { ran := Random(2);
  490.       if ran = 0 then
  491.       begin
  492.         Z := -20;
  493.         FSpeed := 1.8;
  494.       end
  495.       else if ran = 1 then
  496.       begin
  497.         Z := -40;
  498.         FSpeed := 0.8;
  499.       end
  500.       else if ran = 2 then
  501.       begin }
  502.         Z := -60;
  503.         FSpeed := 0.3;
  504.       { end; }
  505.     end;
  506.   end;
  507. end;
  508.  
  509. { TBackgroundSpecial }
  510.  
  511. procedure TBackgroundSpecial.DoMove(MoveCount: Integer);
  512. begin
  513.   inherited DoMove(MoveCount);
  514.   X := X - MoveCount*(60/1000)*FSpeed;
  515.   if X < -Width then Dead;
  516. end;
  517.  
  518. { TExplosion }
  519.  
  520. constructor TExplosion.Create(AParent: TSprite);
  521. begin
  522.   inherited Create(AParent);
  523.   mainform.PlaySound(smsExplosion, false);
  524.   Image := MainForm.GetSpriteGraphic(smgExplosion);
  525.   Width := Image.Width;
  526.   Height := Image.Height;
  527.   AnimCount := Image.PatternCount;
  528.   AnimLooped := True;
  529.   AnimSpeed := DEFAULT_ANIMSPEED;
  530.   AnimPos := Random(AnimCount);
  531. end;
  532.  
  533. procedure TExplosion.DoMove(MoveCount: Integer);
  534. begin
  535.   inherited DoMove(MoveCount);
  536.   inc(FCounter, MoveCount);
  537.   if FCounter > 2999 then dead;
  538. end;
  539.  
  540. { TPlayerSprite }
  541.  
  542. constructor TPlayerSprite.Create(AParent: TSprite);
  543. begin
  544.   inherited Create(AParent);
  545.   State := pesEntering;
  546.   Image := MainForm.GetSpriteGraphic(smgMachine);
  547.   Width := Image.Width;
  548.   Height := Image.Height;
  549.   X := -70{20};
  550.   Y := mainform.dxdraw.surfaceHeight / 2 - (height / 2);
  551.   Z := 2;
  552.   AnimCount := Image.PatternCount;
  553.   AnimLooped := True;
  554.   AnimSpeed := DEFAULT_ANIMSPEED;
  555. end;
  556.  
  557. procedure TPlayerSprite.DoCollision(Sprite: TSprite; var Done: Boolean);
  558. begin
  559.   if mainform.FCheat then exit;
  560.   if (Sprite is TEnemy) or (Sprite is TEnemyTama) then
  561.   begin
  562.     if not crash then
  563.     begin
  564.       dec(MainForm.FLife);
  565.       Crash := true;
  566.       if MainForm.Flife=0 then
  567.       begin
  568.         MainForm.PlaySound(smsExplosion, false);
  569.         Collisioned := false;
  570.         FCounter := 0;
  571.         State := pesDead;
  572.         Done := false;
  573.         Image := MainForm.GetSpriteGraphic(smgExplosion);
  574.         Width := Image.Width;
  575.         Height := Image.Height;
  576.         AnimCount := Image.PatternCount;
  577.         AnimLooped := False;
  578.         AnimSpeed := DEFAULT_ANIMSPEED;
  579.         AnimPos := 0;
  580.       end;
  581.     end
  582.     else
  583.     begin
  584.       if not crashsound then
  585.       begin
  586.         MainForm.PlaySound(smsHit, False);
  587.         crashsound := true;
  588.       end;
  589.     end;
  590.   end;
  591. end;
  592.  
  593. procedure TPlayerSprite.DoMove(MoveCount: Integer);
  594. const
  595.   WegduesKonstante = 1.75;
  596. begin
  597.   inherited DoMove(MoveCount);
  598.   if State = pesNormal then
  599.   begin
  600.     if isUp in MainForm.DXInput.States then Y := Y - (250/1000)*MoveCount;
  601.     if isDown in MainForm.DXInput.States then Y := Y + (250/1000)*MoveCount;
  602.     if isLeft in MainForm.DXInput.States then X := X - (250/1000)*MoveCount;
  603.     if isRight in MainForm.DXInput.States then X := X + (250/1000)*MoveCount;
  604.     if X<0 then X := 0;
  605.     if X>mainform.dxdraw.surfacewidth-Width then X := mainform.dxdraw.surfacewidth-Width;
  606.     if Y<0 then Y := 0;
  607.     if Y>mainform.dxdraw.surfaceheight-Height then Y := mainform.dxdraw.surfaceheight-Height;
  608.     if isButton1 in MainForm.DXInput.States then
  609.     begin
  610.       if (FTamaCount<8) and (FCounter-FOldTamaTime>=100) then
  611.       begin
  612.         Inc(FTamaCount);
  613.         with TPlayerTamaSprite.Create(Engine, Self) do
  614.         begin
  615.           X := Self.X+Self.Width;
  616.           Y := Self.Y+Self.Height div 2-Height div 2;
  617.           Z := 10;
  618.         end;
  619.         FOldTamaTime := FCounter;
  620.       end;
  621.     end;
  622.     Collision;
  623.   end
  624.   else if State = pesDead then
  625.   begin
  626.     if FCounter>200 then
  627.     begin
  628.       FCounter := 0;
  629.       State := pesDeadVanished;
  630.       Visible := false;
  631.     end;
  632.   end
  633.   else if State = pesDeadVanished then
  634.   begin
  635.     if FCounter>1500 then
  636.     begin
  637.       MainForm.FNextScene := gsGameOver;
  638.       MainForm.PlaySound(smsSceneMov, false);
  639.       MainForm.PalleteAnim(RGBQuad(0, 0, 0), 300);
  640.       Sleep(200);
  641.     end;
  642.   end
  643.   else if State = pesFlyaway then
  644.   begin
  645.     X := X + MoveCount*(300/1000) * (X/MainForm.DXDraw.Width + WegduesKonstante);
  646.     if X > MainForm.DXDraw.Width+Width then
  647.     begin
  648.       Dead;
  649.       inc(mainform.FLevel);
  650.       MainForm.FNextScene := gsNewLevel;
  651.       MainForm.PlaySound(smsSceneMov, false);
  652.       MainForm.PalleteAnim(RGBQuad(0, 0, 0), 300);
  653.     end;
  654.   end
  655.   else if State = pesEntering then
  656.   begin
  657.     X := X + MoveCount*(300/1000);
  658.     if X > 19 then State := pesNormal;
  659.   end;
  660.   inc(FCounter, MoveCount);
  661. end;
  662.  
  663. procedure TPlayerSprite.FlyAway;
  664. begin
  665.   State := pesFlyaway;
  666. end;
  667.  
  668. { TPlayerTamaSprite }
  669.  
  670. constructor TPlayerTamaSprite.Create(AParent: TSprite; APlayerSprite: TPlayerSprite);
  671. begin
  672.   inherited Create(AParent);
  673.   FPlayerSprite := APlayerSprite;
  674.   Image := MainForm.GetSpriteGraphic(smgBounce);
  675.   Z := 2;
  676.   Width := Image.Width;
  677.   Height := Image.Height;
  678.   AnimCount := Image.PatternCount;
  679.   AnimLooped := True;
  680.   AnimSpeed := DEFAULT_ANIMSPEED;
  681.   MainForm.PlaySound(smsShoot, False);
  682. end;
  683.  
  684. destructor TPlayerTamaSprite.Destroy;
  685. begin
  686.   inherited Destroy;
  687.   Dec(FPlayerSprite.FTamaCount);
  688. end;
  689.  
  690. procedure TPlayerTamaSprite.DoCollision(Sprite: TSprite; var Done: Boolean);
  691. begin
  692.   if (Sprite is TEnemy) and not (Sprite is TEnemyTama) then
  693.   begin
  694.     TEnemy(Sprite).Hit;
  695.     Dead;
  696.   end;
  697.   Done := False;
  698. end;
  699.  
  700. procedure TPlayerTamaSprite.DoMove(MoveCount: Integer);
  701. begin
  702.   inherited DoMove(MoveCount);
  703.   X := X+(800/1000)*MoveCount;
  704.   if X>=mainform.dxdraw.surfacewidth then Dead;
  705.   Collision;
  706. end;
  707.  
  708. { TEnemy }
  709.  
  710. constructor TEnemy.Create(AParent: TSprite; ALifes: integer);
  711. begin
  712.   inherited Create(AParent);
  713.   FLife := ALifes;
  714.   inc(EnemyCounter);
  715. end;
  716.  
  717. destructor TEnemy.Destroy;
  718. begin
  719.   inherited Destroy;
  720.   dec(EnemyCounter);
  721. end;
  722.  
  723. procedure TEnemy.Hit(AHitStrength: integer = 1);
  724. begin
  725.   Dec(FLife, AHitStrength);
  726.   if FLife<=0 then
  727.   begin
  728.     Collisioned := False;
  729.     HitEnemy(True);
  730.   end
  731.   else
  732.     HitEnemy(False);
  733. end;
  734.  
  735. procedure TEnemy.HitEnemy(ADead: Boolean);
  736. begin
  737.   if ADead then
  738.     MainForm.PlaySound(smsExplosion, False)
  739.   else
  740.     MainForm.PlaySound(smsHit, False);
  741. end;
  742.  
  743. { TEnemyTama }
  744.  
  745. constructor TEnemyTama.Create(AParent: TSprite; AEnemySprite: TSprite);
  746. begin
  747.   inherited Create(AParent);
  748.   FEnemySprite := AEnemySprite;
  749.   Image := MainForm.GetSpriteGraphic(smgBounce2);
  750.   Width := Image.Width;
  751.   Height := Image.Height;
  752.   AnimCount := Image.PatternCount;
  753.   AnimLooped := True;
  754.   AnimSpeed := DEFAULT_ANIMSPEED;
  755.   MainForm.PlaySound(smsShoot, False);
  756. end;
  757.  
  758. procedure TEnemyTama.DoMove(MoveCount: Integer);
  759. begin
  760.   inherited DoMove(MoveCount);
  761.   X := X - MoveCount*(600/1000);
  762.   if X < -Width then Dead;
  763. end;
  764.  
  765. { TEnemyMeteor }
  766.  
  767. constructor TEnemyMeteor.Create(AParent: TSprite; ALifes: integer);
  768. begin
  769.   inherited Create(AParent, ALifes);
  770.   State := pesNormal;
  771.   Image := MainForm.GetSpriteGraphic(smgEnemyMeteor);
  772.   Width := Image.Width;
  773.   Height := Image.Height;
  774.   AnimCount := Image.PatternCount;
  775.   AnimLooped := True;
  776.   AnimSpeed := DEFAULT_ANIMSPEED;
  777.   PixelCheck := True;
  778. end;
  779.  
  780. procedure TEnemyMeteor.HitEnemy(ADead: Boolean);
  781. begin
  782.   inherited HitEnemy(False);
  783.  
  784.   if ADead then Collisioned := True;
  785. end;
  786.  
  787. procedure TEnemyMeteor.DoMove(MoveCount: Integer);
  788. begin
  789.   X := X - MoveCount*(250/1000);
  790.   if X < -Width then Dead;
  791. end;
  792.  
  793. { TEnemyUFO }
  794.  
  795. constructor TEnemyUFO.Create(AParent: TSprite; ALifes: integer);
  796. begin
  797.   inherited Create(AParent, ALifes);
  798.   State := pesNormal;
  799.   Image := MainForm.GetSpriteGraphic(smgEnemyDisk);
  800.   Width := Image.Width;
  801.   Height := Image.Height;
  802.   AnimCount := Image.PatternCount;
  803.   AnimLooped := True;
  804.   AnimSpeed := DEFAULT_ANIMSPEED;
  805. end;
  806.  
  807. procedure TEnemyUFO.HitEnemy(ADead: Boolean);
  808. begin
  809.   inherited HitEnemy(ADead);
  810.  
  811.   if ADead then
  812.   begin
  813.     State := pesDead;
  814.     FCounter := 0;
  815.     Inc(MainForm.FScore, 1000);
  816.     Image := MainForm.GetSpriteGraphic(smgExplosion);
  817.     Width := Image.Width;
  818.     Height := Image.Height;
  819.     AnimCount := Image.PatternCount;
  820.     AnimLooped := False;
  821.     AnimSpeed := DEFAULT_ANIMSPEED;
  822.     AnimPos := 0;
  823.   end
  824.   else
  825.   begin
  826.     Inc(MainForm.FScore, 100);
  827.   end;
  828. end;
  829.  
  830. procedure TEnemyUFO.DoMove(MoveCount: Integer);
  831. begin
  832.   inherited DoMove(MoveCount);
  833.   if State = pesNormal then
  834.   begin
  835.     X := X - MoveCount*(300/1000);
  836.     Y := Y + Cos256(FCounter div 15)*2;
  837.     if X < -Width then Dead;
  838.   end
  839.   else if State = pesDead then
  840.   begin
  841.     X := X - MoveCount*(300/1000);
  842.     if FCounter>200 then
  843.     begin
  844.       State := pesDeadVanished;
  845.       Dead;
  846.     end;
  847.   end;
  848.   inc(FCounter, MoveCount);
  849. end;
  850.  
  851. { TEnemyUFO2 }
  852.  
  853. constructor TEnemyUFO2.Create(AParent: TSprite; ALifes: integer);
  854. begin
  855.   inherited Create(AParent, ALifes);
  856.   State := pesNormal;
  857.   Image := MainForm.GetSpriteGraphic(smgEnemyDisk2);
  858.   Width := Image.Width;
  859.   Height := Image.Height;
  860.   AnimCount := Image.PatternCount;
  861.   AnimLooped := True;
  862.   AnimSpeed := DEFAULT_ANIMSPEED;
  863. end;
  864.  
  865. procedure TEnemyUFO2.HitEnemy(ADead: Boolean);
  866. begin
  867.   inherited HitEnemy(ADead);
  868.  
  869.   if ADead then
  870.   begin
  871.     State := pesDead;
  872.     FCounter := 0;
  873.     Inc(MainForm.FScore, 1000);
  874.     Image := MainForm.GetSpriteGraphic(smgExplosion);
  875.     Width := Image.Width;
  876.     Height := Image.Height;
  877.     AnimCount := Image.PatternCount;
  878.     AnimLooped := False;
  879.     AnimSpeed := DEFAULT_ANIMSPEED;
  880.     AnimPos := 0;
  881.   end
  882.   else
  883.   begin
  884.     Inc(MainForm.FScore, 100);
  885.   end;
  886. end;
  887.  
  888. procedure TEnemyUFO2.DoMove(MoveCount: Integer);
  889. begin
  890.   inherited DoMove(MoveCount);
  891.   if State = pesNormal then
  892.   begin
  893.     X := X - MoveCount*(300/1000);
  894.     Y := Y + Cos256(FCounter div 15)*2;
  895.     if X < -Width then Dead;
  896.     if FCounter-FOldTamaTime>=100 then
  897.     begin
  898.       Inc(FTamaCount);
  899.       with TEnemyTama.Create(Engine, Self) do
  900.       begin
  901.         X := Self.X;
  902.         Y := Self.Y+Self.Height div 2-Height div 2;
  903.         Z := 10;
  904.       end;
  905.       FOldTamaTime := FCounter;
  906.     end;
  907.   end
  908.   else if State = pesDead then
  909.   begin
  910.     X := X - MoveCount*(300/1000);
  911.     if FCounter>200 then
  912.     begin
  913.       State := pesDeadVanished;
  914.       Dead;
  915.     end;
  916.   end;
  917.   inc(FCounter, MoveCount);
  918. end;
  919.  
  920. { TEnemyAttacker }
  921.  
  922. constructor TEnemyAttacker.Create(AParent: TSprite; ALifes: integer);
  923. begin
  924.   inherited Create(AParent, ALifes);
  925.   State := pesNormal;
  926.   Image := MainForm.GetSpriteGraphic(smgEnemyAttacker);
  927.   Width := Image.Width;
  928.   Height := Image.Height;
  929.   AnimCount := Image.PatternCount;
  930.   AnimLooped := True;
  931.   AnimSpeed := DEFAULT_ANIMSPEED;
  932.   PixelCheck := True;
  933. end;
  934.  
  935. procedure TEnemyAttacker.HitEnemy(ADead: Boolean);
  936. begin
  937.   inherited HitEnemy(ADead);
  938.  
  939.   if ADead then
  940.   begin
  941.     State := pesDead;
  942.     FCounter := 0;
  943.     Inc(MainForm.FScore, 1000);
  944.     Image := MainForm.GetSpriteGraphic(smgExplosion);
  945.     Width := Image.Width;
  946.     Height := Image.Height;
  947.     AnimCount := Image.PatternCount;
  948.     AnimLooped := False;
  949.     AnimSpeed := DEFAULT_ANIMSPEED;
  950.     AnimPos := 0;
  951.   end
  952.   else
  953.   begin
  954.     Inc(MainForm.FScore, 100);
  955.   end;
  956. end;
  957.  
  958. procedure TEnemyAttacker.DoMove(MoveCount: Integer);
  959. begin
  960.   inherited DoMove(MoveCount);
  961.   if State = pesNormal then
  962.   begin
  963.     X := X - MoveCount*(300/1000)-FCounter div 128;
  964.     if X < -Width then Dead;
  965.   end
  966.   else if State = pesDead then
  967.   begin
  968.     X := X - MoveCount*(300/1000);
  969.     if FCounter>200 then
  970.     begin
  971.       State := pesDeadVanished;
  972.       Dead;
  973.     end;
  974.   end;
  975.   inc(FCounter, MoveCount);
  976. end;
  977.  
  978. { TEnemyAttacker2 }
  979.  
  980. constructor TEnemyAttacker2.Create(AParent: TSprite; ALifes: integer);
  981. begin
  982.   inherited Create(AParent, ALifes);
  983.   State := pesEntering;
  984.   Image := MainForm.GetSpriteGraphic(smgEnemyAttacker2);
  985.   Width := Image.Width;
  986.   Height := Image.Height;
  987.   AnimCount := Image.PatternCount;
  988.   AnimLooped := True;
  989.   AnimSpeed := DEFAULT_ANIMSPEED;
  990.   PixelCheck := True;
  991. end;
  992.  
  993. procedure TEnemyAttacker2.HitEnemy(ADead: Boolean);
  994. begin
  995.   inherited HitEnemy(ADead);
  996.  
  997.   if ADead then
  998.   begin
  999.     State := pesDead;
  1000.     FCounter := 0;
  1001.     Inc(MainForm.FScore, 5000);
  1002.     Image := MainForm.GetSpriteGraphic(smgExplosion);
  1003.     Width := Image.Width;
  1004.     Height := Image.Height;
  1005.     AnimCount := Image.PatternCount;
  1006.     AnimLooped := False;
  1007.     AnimSpeed := DEFAULT_ANIMSPEED;
  1008.     AnimPos := 0;
  1009.   end
  1010.   else
  1011.   begin
  1012.     Inc(MainForm.FScore, 100);
  1013.   end;
  1014. end;
  1015.  
  1016. procedure TEnemyAttacker2.DoMove(MoveCount: Integer);
  1017. begin
  1018.   inherited DoMove(MoveCount);
  1019.   if State = pesEntering then
  1020.   begin
  1021.     if X>((mainform.dxdraw.width/4) + (mainform.dxdraw.width/2) - (width/2)){450} then
  1022.       X := X - MoveCount*(300/1000)
  1023.     else
  1024.     begin
  1025.       Collisioned := True;
  1026.       State := pesHovering;
  1027.       FPutTama := True;
  1028.     end;
  1029.     Y := Y + Cos256(FCounter div 15)*5;
  1030.   end
  1031.   else if State = pesHovering then
  1032.   begin
  1033.     Y := Y + Cos256(FCounter div 15)*5;
  1034.     if FPutTama then
  1035.     begin
  1036.       if FTamaT>100 then
  1037.       begin
  1038.         with TEnemyTama.Create(Engine, Self) do
  1039.         begin
  1040.           Z := 1;
  1041.           X := Self.X-Width;
  1042.           Y := Self.Y+Self.Height div 2-Height div 2;
  1043.         end;
  1044.         Inc(FTamaF);
  1045.         if FTamaF>Random(30) then FPutTama := False;
  1046.         FTamaT := 0;
  1047.       end;
  1048.       FTamaT := FTamaT + MoveCount;
  1049.     end
  1050.     else
  1051.     begin
  1052.       FTamaT := FTamaT + MoveCount;
  1053.       if FTamaT>2000+Random(500) then
  1054.       begin
  1055.         FPutTama := True;
  1056.         FTamaF := 0;
  1057.         FTamaT := 0;
  1058.       end;
  1059.     end;
  1060.   end
  1061.   else if State = pesDead then
  1062.   begin
  1063.     if FCounter>200 then
  1064.     begin
  1065.       State := pesDeadVanished;
  1066.       Dead;
  1067.     end;
  1068.   end;
  1069.   inc(FCounter, MoveCount);
  1070. end;
  1071.  
  1072. { TEnemyAttacker3 }
  1073.  
  1074. constructor TEnemyAttacker3.Create(AParent: TSprite; ALifes: integer);
  1075. begin
  1076.   inherited Create(AParent, ALifes);
  1077.   State := pesNormal;
  1078.   Image := MainForm.GetSpriteGraphic(smgEnemyAttacker3);
  1079.   Width := Image.Width;
  1080.   Height := Image.Height;
  1081.   AnimCount := Image.PatternCount;
  1082.   AnimLooped := True;
  1083.   AnimSpeed := DEFAULT_ANIMSPEED;
  1084.   PixelCheck := True;
  1085. end;
  1086.  
  1087. procedure TEnemyAttacker3.HitEnemy(ADead: Boolean);
  1088. begin
  1089.   inherited HitEnemy(ADead);
  1090.  
  1091.   if ADead then
  1092.   begin
  1093.     State := pesDead;
  1094.     FCounter := 0;
  1095.     Inc(MainForm.FScore, 5000);
  1096.     Image := MainForm.GetSpriteGraphic(smgExplosion);
  1097.     Width := Image.Width;
  1098.     Height := Image.Height;
  1099.     AnimCount := Image.PatternCount;
  1100.     AnimLooped := False;
  1101.     AnimSpeed := DEFAULT_ANIMSPEED;
  1102.     AnimPos := 0;
  1103.   end
  1104.   else
  1105.   begin
  1106.     Inc(MainForm.FScore, 100);
  1107.   end;
  1108. end;
  1109.  
  1110. procedure TEnemyAttacker3.DoMove(MoveCount: Integer);
  1111. begin
  1112.   inherited DoMove(MoveCount);
  1113.   if State = pesNormal then
  1114.   begin
  1115.     X := X - (250/1000)*MoveCount;
  1116.     if X < -Width then Dead;
  1117.     if FCounter-FOldTamaTime>=100 then
  1118.     begin
  1119.       Inc(FTamaCount);
  1120.       with TEnemyTama.Create(Engine, Self) do
  1121.       begin
  1122.         X := Self.X;
  1123.         Y := Self.Y+Self.Height div 2-Height div 2;
  1124.         Z := 10;
  1125.       end;
  1126.       FOldTamaTime := FCounter;
  1127.      end;
  1128.   end
  1129.   else if State = pesDead then
  1130.   begin
  1131.     if FCounter>200 then
  1132.     begin
  1133.       State := pesDeadVanished;
  1134.       Dead;
  1135.     end;
  1136.   end;
  1137.   inc(FCounter, MoveCount);
  1138. end;
  1139.  
  1140. { TEnemyBoss }
  1141.  
  1142. constructor TEnemyBoss.Create(AParent: TSprite; ALifes: integer);
  1143. begin
  1144.   inherited Create(AParent, ALifes);
  1145.   State := pesEntering;
  1146.   Image := MainForm.GetSpriteGraphic(smgEnemyBoss);
  1147.   Width := Image.Width;
  1148.   Height := Image.Height;
  1149.   BossExists := true;
  1150.   MainForm.MusicSwitchTrack(smmBoss);
  1151.   AnimCount := Image.PatternCount;
  1152.   AnimLooped := True;
  1153.   AnimSpeed := DEFAULT_ANIMSPEED;
  1154.   PixelCheck := True;
  1155.   Collisioned := False;
  1156.   MainForm.FBossLife := FLife;
  1157.   waiter1 := 0;
  1158.   waiter2 := 0;
  1159. end;
  1160.  
  1161. procedure TEnemyBoss.HitEnemy(ADead: Boolean);
  1162. begin
  1163.   inherited HitEnemy(ADead);
  1164.  
  1165.   if ADead then
  1166.   begin
  1167.     State := pesExploding; // not pesDead for the boss!
  1168.     FCounter := 0;
  1169.     Inc(MainForm.FScore, 100000);
  1170.     BossExists := false;
  1171.     dec(MainForm.FBossLife);
  1172.   end
  1173.   else
  1174.   begin
  1175.     Inc(MainForm.FScore, 100);
  1176.     dec(MainForm.FBossLife);
  1177.   end;
  1178. end;
  1179.  
  1180. procedure TEnemyBoss.DoMove(MoveCount: Integer);
  1181. begin
  1182.   inherited DoMove(MoveCount);
  1183.   if State = pesEntering then
  1184.   begin
  1185.     if X>((mainform.dxdraw.width/4) + (mainform.dxdraw.width/2) - (width/4)){450} then
  1186.       X := X - MoveCount*(300/1000)
  1187.     else
  1188.     begin
  1189.       Collisioned := True;
  1190.       State := pesHovering;
  1191.       FPutTama := True;
  1192.     end;
  1193.     Y := Y + Cos256(FCounter div 15)*5;
  1194.   end
  1195.   else if State = pesHovering then
  1196.   begin
  1197.     Y := Y + Cos256(FCounter div 15)*5;
  1198.     if FPutTama then
  1199.     begin
  1200.       if FTamaT>100 then
  1201.       begin
  1202.         with TEnemyTama.Create(Engine, Self) do
  1203.         begin
  1204.           Z := 1;
  1205.           X := Self.X-Width;
  1206.           Y := Self.Y+Self.Height div 2-Height div 2;
  1207.         end;
  1208.         Inc(FTamaF);
  1209.         if FTamaF>Random(30) then FPutTama := False;
  1210.         FTamaT := 0;
  1211.       end;
  1212.       FTamaT := FTamaT + MoveCount;
  1213.     end
  1214.     else
  1215.     begin
  1216.       FTamaT := FTamaT + MoveCount;
  1217.       if FTamaT>2000+Random(500) then
  1218.       begin
  1219.         FPutTama := True;
  1220.         FTamaF := 0;
  1221.         FTamaT := 0;
  1222.       end;
  1223.     end;
  1224.   end
  1225.   else if State = pesExploding then
  1226.   begin
  1227.     inc(waiter1);
  1228.     if waiter1 = 3 then
  1229.     begin
  1230.       waiter1 := 0;
  1231.       inc(waiter2);
  1232.       if waiter2 <= 20 then
  1233.       begin
  1234.         with TExplosion.Create(Engine) do
  1235.         begin
  1236.           Z := 10;
  1237.           X := Self.X+Random(Self.Width)-16;
  1238.           Y := Self.Y+Random(Self.Height)-16;
  1239.         end;
  1240.       end
  1241.       else
  1242.       begin
  1243.         Inc(MainForm.FScore, 10000);
  1244.         State := pesDead;
  1245.       end;
  1246.     end;
  1247.   end
  1248.   else if State = pesDead then
  1249.   begin
  1250.     if FCounter>4000 then
  1251.     begin
  1252.       State := pesDeadVanished;
  1253.       Dead;
  1254.     end;
  1255.   end;
  1256.   inc(FCounter, MoveCount);
  1257. end;
  1258.  
  1259. { TMainForm }
  1260.  
  1261. procedure TMainForm.FormCreate(Sender: TObject);
  1262. resourcestring
  1263.   SFileError = 'Die Datei kann von SpaceMission nicht geöffnet werden!';
  1264. var
  1265.   SavGame: TSaveData;
  1266. begin
  1267.   LevelData := TLevelData.Create;
  1268.  
  1269.   { Beginne VCL-Ersatz }
  1270.   dxtimer := tdxtimer.Create(self);
  1271.   dxtimer.Interval := 33;
  1272.   dxtimer.OnActivate := DXTimerActivate;
  1273.   dxtimer.OnDeactivate := DXTimerDeactivate;
  1274.   dxtimer.OnTimer := DXTimerTimer;
  1275.   dxtimer.ActiveOnly := false;
  1276.   dxtimer.Enabled := false;
  1277.  
  1278.   dxdraw := tdxdraw.Create(self);
  1279.   dxdraw.Parent := self;
  1280.   dxdraw.Align := alClient;
  1281.   dxdraw.Left := 0;
  1282.   dxdraw.Top := 0;
  1283.   dxdraw.Width := mainform.ClientWidth;
  1284.   dxdraw.Height := mainform.ClientHeight;
  1285.   dxdraw.AutoInitialize := False;
  1286.   dxdraw.AutoSize := False;
  1287.   dxdraw.Color := clBlack;
  1288.   (*
  1289.   dxdraw.Display.BitCount := 24;
  1290.   dxdraw.Display.FixedBitCount := False;
  1291.   dxdraw.Display.FixedRatio := False;
  1292.   dxdraw.Display.FixedSize := False;
  1293.   dxdraw.Display.Height := 600;
  1294.   dxdraw.Display.Width := 800;
  1295.   *)
  1296.   dxdraw.Options := [doAllowReboot, doWaitVBlank, doAllowPalette256, doCenter, {doRetainedMode,} doHardware, doSelectDriver];
  1297.   dxdraw.TabOrder := 0;
  1298.   dxdraw.Visible := true;
  1299.   dxdraw.OnFinalize := DXDrawFinalize;
  1300.   dxdraw.OnInitialize := DXDrawInitialize;
  1301.   dxdraw.OnInitializing := DXDrawInitializing;
  1302.  
  1303.   dxsound := tdxsound.Create(self);
  1304.   dxsound.AutoInitialize := false;
  1305.  
  1306.   dxmusic := TDXMusic.Create(self);
  1307.   dxmusic.DXSound := dxsound;
  1308.  
  1309.   dxinput := tdxinput.Create(self);
  1310.   dxinput.Joystick.ForceFeedback := true;
  1311.   dxinput.Keyboard.ForceFeedback := true;
  1312.  
  1313.   wavelist := tdxwavelist.Create(self);
  1314.   wavelist.DXSound := dxsound;
  1315.  
  1316.   imagelist := tdximagelist.create(self);
  1317.   imagelist.DXDraw := dxdraw;
  1318.  
  1319.   spriteengine := tdxspriteengine.create(self);
  1320.   spriteengine.DXDraw := dxdraw;
  1321.  
  1322.   InitializeCriticalSection(TimerCS);
  1323.  
  1324.   { Ende VCL-Ersatz }
  1325.  
  1326.   Application.Title := 'SpaceMission '+ProgramVersion;
  1327.   LoadOptions;
  1328.   DXInit;
  1329.   SoundInit;
  1330.   MusicInit;
  1331.   ResetLevelData;
  1332.   if (paramcount = 0) and (fileexists(paramstr(1))) then // (paramcount > 0)
  1333.   begin
  1334.     SavGame := TSaveData.Create;
  1335.     try
  1336.       try
  1337.         SavGame.Load(paramstr(1));
  1338.         mainform.FScore := SavGame.FScore;
  1339.         mainform.FLife := SavGame.FLife;
  1340.         mainform.FLevel := SavGame.FLevel;
  1341.         mainform.FGameMode := SavGame.FGameMode;
  1342.       except
  1343.         on E: Exception do
  1344.         begin
  1345.           showmessage(SFileError + ' ' +E.Message);
  1346.           GameStartClick(GameStart);
  1347.           exit;
  1348.         end;
  1349.       end;
  1350.     finally
  1351.       FreeAndNil(SavGame);
  1352.     end;
  1353.     mainform.FNextScene := gsNewLevel;
  1354.     exit;
  1355.   end;
  1356.   GameStartClick(GameStart);
  1357. end;
  1358.  
  1359. procedure TMainForm.GameStartClick(Sender: TObject);
  1360. begin
  1361.   StartScene(gsTitle);
  1362. end;
  1363.  
  1364. function TMainForm.GetSpriteGraphic(
  1365.   Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
  1366. begin
  1367.   if (Sprite<>smgNone) and (imagelist.Items.Count >= Ord(Sprite)) then
  1368.     result := imagelist.Items.Items[Ord(Sprite)-1]
  1369.   else
  1370.     result := nil;
  1371. end;
  1372.  
  1373. procedure TMainForm.GamePauseClick(Sender: TObject);
  1374. begin
  1375.   GamePause.Checked := not GamePause.Checked;
  1376.   DXTimer.Enabled := not GamePause.Checked;
  1377.   if GamePause.Checked then
  1378.   begin
  1379.     if Assigned(DXTimer.OnDeactivate) then
  1380.       DXTimer.OnDeactivate(DXTimer);
  1381.   end
  1382.   else
  1383.   begin
  1384.     if Assigned(DXTimer.OnActivate) then
  1385.       DXTimer.OnActivate(DXTimer);
  1386.   end;
  1387. end;
  1388.  
  1389. procedure TMainForm.DXInit;
  1390. begin
  1391.   try
  1392.     Imagelist.Items.LoadFromFile(OwnDirectory+'DirectX\Graphics.dxg');
  1393.     ImageList.Items.MakeColorTable;
  1394.     DXDraw.ColorTable := ImageList.Items.ColorTable;
  1395.     DXDraw.DefColorTable := ImageList.Items.ColorTable;
  1396.     DXDraw.UpdatePalette;
  1397.     DXDraw.Finalize;
  1398.     DXDraw.Options := DXDraw.Options - [doFullScreen];
  1399.     DXDraw.autosize := true;
  1400.     DXDraw.Initialize;
  1401.   except
  1402.     //Imagelist.Items.clear;
  1403.     //application.terminate;
  1404.   end;
  1405. end;
  1406.  
  1407. procedure TMainForm.CheckUpdatesClick(Sender: TObject);
  1408. var
  1409.   cont: string;
  1410. begin
  1411.   cont := GetHTML('https://www.viathinksoft.de/update/?id=spacemission');
  1412.   if copy(cont, 0, 7) = 'Status:' then
  1413.   begin
  1414.     Application.MessageBox('Ein Fehler ist aufgetreten. Wahrscheinlich ist keine Internetverbindung aufgebaut, oder der der ViaThinkSoft-Server vorübergehend offline.', 'Fehler', MB_OK + MB_ICONERROR)
  1415.   end
  1416.   else
  1417.   begin
  1418.     if cont <> ProgramVersion then
  1419.     begin
  1420.       if Application.MessageBox('Eine neue Programmversion ist vorhanden. Möchten Sie diese jetzt herunterladen?', 'Information', MB_YESNO + MB_ICONASTERISK) = ID_YES then
  1421.         shellexecute(application.handle, 'open', pchar('https://www.viathinksoft.de/update/?id=@spacemission'), '', '', sw_normal);
  1422.     end
  1423.     else
  1424.     begin
  1425.       Application.MessageBox('Es ist keine neue Programmversion vorhanden.', 'Information', MB_OK + MB_ICONASTERISK);
  1426.     end;
  1427.   end;
  1428. end;
  1429.  
  1430. procedure TMainForm.BeendenClick(Sender: TObject);
  1431. begin
  1432.   close;
  1433. end;
  1434.  
  1435. procedure TMainForm.OptionSoundClick(Sender: TObject);
  1436. begin
  1437.   OptionSound.Checked := not OptionSound.Checked;
  1438.   SoundInit;
  1439.   WriteOptions;
  1440. end;
  1441.  
  1442. procedure TMainForm.SoundInit;
  1443. begin
  1444.   if (WaveOutGetNumDevs < 1) or not FileExists(OwnDirectory+'DirectX\Sound.dxw') then
  1445.   begin
  1446.     OptionSound.Checked := false;
  1447.     OptionSound.Enabled := False;
  1448.     exit;
  1449.   end;
  1450.  
  1451.   if OptionSound.Checked then
  1452.   begin
  1453.     if not DXSound.Initialized then
  1454.     begin
  1455.       try
  1456.         DXSound.Initialize;
  1457.         WaveList.Items.LoadFromFile(OwnDirectory+'DirectX\Sound.dxw');
  1458.       except
  1459.         OptionSound.enabled := False;
  1460.         WaveList.items.clear;
  1461.       end;
  1462.     end;
  1463.   end
  1464.   else DXSound.Finalize;
  1465. end;
  1466.  
  1467. procedure TMainForm.MusicInit;
  1468. var
  1469.   i: integer;
  1470. begin
  1471.   if (WaveOutGetNumDevs < 1) or not FileExists(OwnDirectory+'DirectX\Music.dxm') then
  1472.   begin
  1473.     optionmusic.Checked := false;
  1474.     optionmusic.Enabled := False;
  1475.     exit;
  1476.   end;
  1477.  
  1478.   try
  1479.     dxmusic.Midis.LoadFromFile(OwnDirectory+'DirectX\Music.dxm');
  1480.     for i := 0 to dxmusic.Midis.Count-1 do
  1481.     begin
  1482.       if not dxmusic.Midis.Items[i].IsInitialized then
  1483.       begin
  1484.         dxmusic.Midis.Items[i].Init;
  1485.         dxmusic.Midis.Items[i].Load;
  1486.       end;
  1487.     end;
  1488.   except
  1489.     optionmusic.enabled := false;
  1490.   end;
  1491. end;
  1492.  
  1493. procedure TMainForm.DXDrawInitializing(Sender: TObject);
  1494. begin
  1495.   if doFullScreen in DXDraw.Options then
  1496.   begin
  1497.     BorderStyle := bsNone;
  1498.     DXDraw.Cursor := crNone;
  1499.   end
  1500.   else
  1501.   begin
  1502.     BorderStyle := bsSingle;
  1503.     DXDraw.Cursor := crDefault;
  1504.   end;
  1505. end;
  1506.  
  1507. procedure TMainForm.DXDrawInitialize(Sender: TObject);
  1508. begin
  1509.   DXTimer.Enabled := True;
  1510. end;
  1511.  
  1512. procedure TMainForm.DXDrawFinalize(Sender: TObject);
  1513. begin
  1514.   DXTimer.Enabled := False;
  1515. end;
  1516.  
  1517. procedure TMainForm.DXTimerActivate(Sender: TObject);
  1518. begin
  1519.   if TDxTimer(Sender).Tag > 0 then
  1520.     TDxTimer(Sender).Tag := TDxTimer(Sender).Tag - 1; // es können mehrere activate/deactivate vorkommen, wegen dem Pause-Button
  1521.   if TDxTimer(Sender).Tag > 0 then
  1522.     exit;
  1523.   Caption := Application.Title;
  1524.   if not ProgrammGestartet then
  1525.   begin
  1526.     Programmgestartet := true;
  1527.     exit;
  1528.   end;
  1529.   ResumeMusic(FMusic);
  1530. end;
  1531.  
  1532. procedure TMainForm.DXTimerDeactivate(Sender: TObject);
  1533. begin
  1534.   TDxTimer(Sender).Tag := TDxTimer(Sender).Tag + 1;
  1535.   Caption := Application.Title + ' [Pause]';
  1536.   PauseMusic(FMusic);
  1537. end;
  1538.  
  1539. procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
  1540. begin
  1541.   EnterCriticalSection(TimerCS);
  1542.   try
  1543.     if crash then
  1544.     begin
  1545.       inc(Crash2);
  1546.       if crash2 = 30 then
  1547.       begin
  1548.         Crash2 := 0;
  1549.         crash := false;
  1550.         crashsound := false;
  1551.       end;
  1552.     end;
  1553.     if not DXDraw.CanDraw then exit;
  1554.     DXInput.Update;
  1555.     case FScene of
  1556.       gsTitle   : SceneTitle;
  1557.       gsMain    : SceneMain;
  1558.       gsGameOver: SceneGameOver;
  1559.       gsWin     : SceneWin;
  1560.       gsNewLevel: SceneNewLevel;
  1561.     end;
  1562.     if FNextScene<>gsNone then
  1563.     begin
  1564.       StartScene(FNextScene);
  1565.       FNextScene := gsNone;
  1566.     end;
  1567.     DXDraw.Flip;
  1568.   finally
  1569.     LeaveCriticalSection(TimerCS);
  1570.   end;
  1571. end;
  1572.  
  1573. procedure TMainForm.BlinkStart;
  1574. begin
  1575.   FBlink := 0;
  1576.   FBlinkTime := GetTickCount;
  1577. end;
  1578.  
  1579. const
  1580.   RegistrySettingsKey = 'SOFTWARE\ViaThinkSoft\SpaceMission\Settings';
  1581.  
  1582. procedure TMainForm.WriteOptions;
  1583. var
  1584.   Reg: TRegistry;
  1585. begin
  1586.   Reg := TRegistry.Create;
  1587.   try
  1588.     Reg.RootKey := HKEY_CURRENT_USER;
  1589.     if Reg.OpenKey(RegistrySettingsKey, true) then
  1590.     begin
  1591.       Reg.WriteBool('Music', OptionMusic.checked);
  1592.       Reg.WriteBool('Sound', OptionSound.checked);
  1593.       Reg.WriteInteger('Speed', Ord(FInterval));
  1594.       Reg.CloseKey;
  1595.     end;
  1596.   finally
  1597.     FreeAndNil(Reg);
  1598.   end;
  1599. end;
  1600.  
  1601. procedure TMainForm.LoadOptions;
  1602. var
  1603.   Reg: TRegistry;
  1604. begin
  1605.   Reg := TRegistry.Create;
  1606.   try
  1607.     Reg.RootKey := HKEY_CURRENT_USER;
  1608.     if Reg.OpenKey(RegistrySettingsKey, true) then
  1609.     begin
  1610.       if Reg.ValueExists('Music') then
  1611.         optionmusic.checked := Reg.ReadBool('Music')
  1612.       else
  1613.         optionmusic.checked := true; // default
  1614.  
  1615.       if Reg.ValueExists('Sound') then
  1616.         optionsound.checked := Reg.ReadBool('Sound')
  1617.       else
  1618.         optionsound.checked := true; // default
  1619.  
  1620.       if Reg.ValueExists('Speed') then
  1621.         FInterval := TGameInterval(Reg.ReadInteger('Speed'))
  1622.       else
  1623.         FInterval := giMittel; // default
  1624.  
  1625.       Reg.CloseKey;
  1626.     end;
  1627.   finally
  1628.     FreeAndNil(Reg);
  1629.   end;
  1630.   WriteOptions;
  1631. end;
  1632.  
  1633. procedure TMainForm.BlinkUpdate;
  1634. begin
  1635.   if GetTickCount<>FBlinkTime then
  1636.   begin
  1637.     FBlink := FBlink + (GetTickCount-FBlinkTime);
  1638.     FBlinkTime := GetTickCount;
  1639.   end;
  1640. end;
  1641.  
  1642. procedure TMainForm.PlaySound(Sound: TSpaceMissionSound; Wait: Boolean);
  1643. begin
  1644.   if (Sound<>smsNone) and (OptionSound.Checked) and (OptionSound.Enabled) and (WaveList.Items.Count >= Ord(Sound)) then
  1645.     WaveList.Items.Items[Ord(Sound)-1].Play(Wait);
  1646. end;
  1647.  
  1648. procedure TMainForm.MusicSwitchTrack(Name: TSpaceMissionMusicTrack);
  1649. begin
  1650.   if (not mainform.active) and (mainform.visible) then //1st Programmstart
  1651.     exit;
  1652.   if (OptionMusic.checked) and (OptionMusic.enabled) then
  1653.   begin
  1654.     StopMusic(FMusic);
  1655.     PlayMusic(Name);
  1656.   end;
  1657.   FMusic := Name;
  1658. end;
  1659.  
  1660. function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
  1661. begin
  1662.   with Result do
  1663.   begin
  1664.     rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256);
  1665.     rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256);
  1666.     rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256);
  1667.     rgbReserved := 0;
  1668.   end;
  1669. end;
  1670.  
  1671. procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer);
  1672. var
  1673.   i: Integer;
  1674.   t, t2: DWORD;
  1675.   ChangePalette: Boolean;
  1676.   c: Integer;
  1677. begin
  1678.   if DXDraw.Initialized then
  1679.   begin
  1680.     c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue));
  1681.     ChangePalette := False;
  1682.     if DXDraw.CanPaletteAnimation then
  1683.     begin
  1684.       t := GetTickCount;
  1685.       while Abs(GetTickCount-t)<Time do
  1686.       begin
  1687.         t2 := Trunc(Abs(GetTickCount-t)/Time*255);
  1688.         for i := 0 to 255 do
  1689.           DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2);
  1690.         DXDraw.UpdatePalette;
  1691.         ChangePalette := True;
  1692.       end;
  1693.     end
  1694.     else
  1695.     begin
  1696.       Sleep(Time);
  1697.     end;
  1698.     for i := 0 to 4 do
  1699.     begin
  1700.       DXDraw.Surface.Fill(c);
  1701.       DXDraw.Flip;
  1702.     end;
  1703.     if ChangePalette then
  1704.     begin
  1705.       DXDraw.ColorTable := DXDraw.DefColorTable;
  1706.       DXDraw.UpdatePalette;
  1707.     end;
  1708.     DXDraw.Surface.Fill(c);
  1709.     DXDraw.Flip;
  1710.   end;
  1711. end;
  1712.  
  1713. procedure TMainForm.StartScene(Scene: TGameScene);
  1714. begin
  1715.   EndScene;
  1716.   DXInput.States := DXInput.States - DXInputButton;
  1717.   FScene := Scene;
  1718.   BlinkStart;
  1719.   case FScene of
  1720.     gsTitle   : StartSceneTitle;
  1721.     gsMain    : StartSceneMain;
  1722.     gsGameOver: StartSceneGameOver;
  1723.     gsWin     : StartSceneWin;
  1724.     gsNewLevel: StartSceneNewLevel;
  1725.   end;
  1726. end;
  1727.  
  1728. procedure TMainForm.StartSceneTitle;
  1729. begin
  1730.   sleep(500);
  1731.   FCheat := false;
  1732.   BossExists := false;
  1733.   FLife := Lives;
  1734.   FLevel := 0;
  1735.   FScore := 0;
  1736.   FNotSave := true;
  1737.   Cheat.enabled := false;
  1738.   Neustart.enabled := false;
  1739.   GamePause.enabled := false;
  1740.   GameStart.enabled := false;
  1741.   Spielgeschwindigkeit.enabled := false;
  1742.   mainform.Visible := true;
  1743.   MusicSwitchTrack(smmTitle);
  1744. end;
  1745.  
  1746. procedure TMainForm.StartSceneMain;
  1747. {var
  1748.   i, j: Integer;}
  1749. begin
  1750.   sleep(500);
  1751.   FCounter := 0;
  1752.   NewLevel(FLevel);
  1753.   BossExists := false;
  1754.   MusicSwitchTrack(smmGame);
  1755.   FEnemyAdventPos := 0;
  1756.   FFrame := -4;
  1757.   PlayerSprite := TPlayerSprite.Create(SpriteEngine.Engine);
  1758.   with TBackground.Create(SpriteEngine.Engine) do
  1759.   begin
  1760.     SetMapSize(1, 1);
  1761.     Image := MainForm.GetSpriteGraphic(smgStar3);
  1762.     Z := -13;
  1763.     Y := 40;
  1764.     Speed := 1 / 2;
  1765.     Tile := True;
  1766.   end;
  1767.   with TBackground.Create(SpriteEngine.Engine) do
  1768.   begin
  1769.     SetMapSize(1, 1);
  1770.     Image := MainForm.GetSpriteGraphic(smgStar2);
  1771.     Z := -12;
  1772.     Y := 30;
  1773.     Speed := 1;
  1774.     Tile := True;
  1775.   end;
  1776.   with TBackground.Create(SpriteEngine.Engine) do
  1777.   begin
  1778.     SetMapSize(1, 1);
  1779.     Image := MainForm.GetSpriteGraphic(smgStar1);
  1780.     Z := -11;
  1781.     Y := 10;
  1782.     Speed := 2;
  1783.     Tile := True;
  1784.   end;
  1785.   {with TBackground.Create(SpriteEngine.Engine) do
  1786.   begin
  1787.     SetMapSize(200, 10);
  1788.     Y := 10;
  1789.     Z := -13;
  1790.     Speed := 1 / 2;
  1791.     Tile := True;
  1792.     for i := 0 to MapHeight-1 do
  1793.     begin
  1794.       for j := 0 to MapWidth-1 do
  1795.       begin
  1796.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8);
  1797.         if Random(100)<95 then Chips[j, i] := -1;
  1798.       end;
  1799.     end;
  1800.   end;
  1801.   with TBackground.Create(SpriteEngine.Engine) do
  1802.   begin
  1803.     SetMapSize(200, 10);
  1804.     Y := 30;
  1805.     Z := -12;
  1806.     Speed := 1;
  1807.     Tile := True;
  1808.     for i := 0 to MapHeight-1 do
  1809.     begin
  1810.       for j := 0 to MapWidth-1 do
  1811.       begin
  1812.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4);
  1813.         if Random(100)<95 then Chips[j, i] := -1;
  1814.       end;
  1815.     end;
  1816.   end;
  1817.   with TBackground.Create(SpriteEngine.Engine) do
  1818.   begin
  1819.     SetMapSize(200, 10);
  1820.     Y := 40;
  1821.     Z := -11;
  1822.     Speed := 2;
  1823.     Tile := True;
  1824.     for i := 0 to MapHeight-1 do
  1825.     begin
  1826.       for j := 0 to MapWidth-1 do
  1827.       begin
  1828.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2);
  1829.         if Random(100)<95 then Chips[j, i] := -1;
  1830.       end;
  1831.     end;
  1832.   end;}
  1833.   FNotSave := false;
  1834.   Cheat.enabled := true;
  1835.   Neustart.enabled := true;
  1836.   GamePause.enabled := true;
  1837.   GameStart.enabled := true;
  1838.   Spielgeschwindigkeit.enabled := true;
  1839. end;
  1840.  
  1841. procedure TMainForm.StartSceneGameOver;
  1842. begin
  1843.   sleep(500);
  1844.   FNotSave := true;
  1845.   Cheat.enabled := false;
  1846.   Spielgeschwindigkeit.enabled := false;
  1847.   Neustart.enabled := false;
  1848.   GamePause.enabled := false;
  1849.   MusicSwitchTrack(smmScene);
  1850.   BossExists := false;
  1851. end;
  1852.  
  1853. procedure TMainForm.StartSceneWin;
  1854. begin
  1855.   sleep(500);
  1856.   FNotSave := true;
  1857.   Cheat.enabled := false;
  1858.   Spielgeschwindigkeit.enabled := false;
  1859.   Neustart.enabled := false;
  1860.   GamePause.enabled := false;
  1861.   MusicSwitchTrack(smmScene);
  1862.   BossExists := false;
  1863. end;
  1864.  
  1865. procedure TMainForm.EndScene;
  1866. begin
  1867.   case FScene of
  1868.     gsTitle   : EndSceneTitle;
  1869.     gsMain    : EndSceneMain;
  1870.     gsGameOver: EndSceneGameOver;
  1871.     gsWin     : EndSceneWin;
  1872.     gsNewLevel: EndSceneNewLevel;
  1873.   end;
  1874. end;
  1875.  
  1876. procedure TMainForm.EndSceneTitle;
  1877. begin
  1878.   {  Ende Title  }
  1879. end;
  1880.  
  1881. procedure TMainForm.EndSceneMain;
  1882. begin
  1883.   SpriteEngine.Engine.Clear;
  1884. end;
  1885.  
  1886. procedure TMainForm.EndSceneGameOver;
  1887. begin
  1888.   {  Ende GameOver  }
  1889. end;
  1890.  
  1891. procedure TMainForm.EndSceneWin;
  1892. begin
  1893.   {  Ende Win  }
  1894. end;
  1895.  
  1896. procedure TMainForm.ResetLevelData;
  1897. begin
  1898.   LevelData.Clear;
  1899.   FRestEnemies := 0;
  1900. end;
  1901.  
  1902. procedure TMainForm.NewLevel(lev: integer);
  1903. resourcestring
  1904.   LNG_LEVEL_INVALID = 'Das Level Nr. %d ist ungültig!'+#13#10+'Das Programm wird beendet.';
  1905. var
  1906.   act: integer;
  1907.   Enemies: array[1..27] of TEnemyType;
  1908.   e: TEnemyAdvent;
  1909. begin
  1910.   ResetLevelData;
  1911.   if FGameMode = gmRandom then
  1912.   begin
  1913.     {$REGION 'Random game'}
  1914.     Enemies[1] := etEnemyAttacker;
  1915.     Enemies[2] := etEnemyMeteor;
  1916.     Enemies[3] := etEnemyUFO;
  1917.     Enemies[4] := etEnemyAttacker;
  1918.     Enemies[5] := etEnemyMeteor;
  1919.     Enemies[6] := etEnemyUFO;
  1920.     Enemies[7] := etEnemyAttacker;
  1921.     Enemies[8] := etEnemyMeteor;
  1922.     Enemies[9] := etEnemyUFO;
  1923.     Enemies[10] := etEnemyAttacker;
  1924.     Enemies[11] := etEnemyMeteor;
  1925.     Enemies[12] := etEnemyUFO;
  1926.     Enemies[13] := etEnemyAttacker;
  1927.     Enemies[14] := etEnemyMeteor;
  1928.     Enemies[15] := etEnemyUFO;
  1929.     Enemies[16] := etEnemyAttacker3;
  1930.     Enemies[17] := etEnemyAttacker;
  1931.     Enemies[18] := etEnemyMeteor;
  1932.     Enemies[19] := etEnemyUFO;
  1933.     Enemies[20] := etEnemyUFO2;
  1934.     Enemies[21] := etEnemyAttacker;
  1935.     Enemies[22] := etEnemyMeteor;
  1936.     Enemies[23] := etEnemyUFO;
  1937.     Enemies[24] := etEnemyAttacker2;
  1938.     Enemies[25] := etEnemyMeteor;
  1939.     Enemies[26] := etEnemyUFO;
  1940.     Enemies[27] := etEnemyAttacker;
  1941.     randomize;
  1942.     FRestEnemies := lev*ADDITIONAL_ENEMIES_PER_LEVEL+1;
  1943.     SetLength(LevelData.EnemyAdventTable, FRestEnemies);
  1944.     for act := 0 to lev*ADDITIONAL_ENEMIES_PER_LEVEL-1 do
  1945.     begin
  1946.       e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))];
  1947.       if e.enemyType = etEnemyAttacker2 then
  1948.       begin
  1949.         e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))]; {O_o}
  1950.       end;
  1951.       e.x := act*30 + random(85-(lev+(random(lev))*2)){O_o};
  1952.       e.y := random(dxdraw.surfaceheight);
  1953.       if e.enemyType = etEnemyAttacker2 then
  1954.       begin
  1955.         e.lifes := random(6)+1{O_o};
  1956.       end
  1957.       else
  1958.       begin
  1959.         e.lifes := random(lev)+1;
  1960.       end;
  1961.  
  1962.       LevelData.EnemyAdventTable[act] := e;
  1963.     end;
  1964.     e.enemyType := etEnemyBoss;
  1965.     e.x := lev*75*30{O_o} div lev;
  1966.     e.y := (dxdraw.surfaceheight div 2) - (MainForm.GetSpriteGraphic(smgEnemyBoss).height div 2);
  1967.     e.lifes := lev*5;
  1968.     LevelData.EnemyAdventTable[lev*ADDITIONAL_ENEMIES_PER_LEVEL] := e;
  1969.     Assert(FRestEnemies = Length(LevelData.EnemyAdventTable));
  1970.     {$ENDREGION}
  1971.   end
  1972.   else
  1973.   begin
  1974.     {$REGION 'Normal game'}
  1975.     if fileexists(GetLevelFileName(lev)) then
  1976.     begin
  1977.       try
  1978.         LevelData.Load(GetLevelFileName(lev));
  1979.         FRestEnemies := Length(LevelData.EnemyAdventTable);
  1980.       except
  1981.         showmessage(Format(LNG_LEVEL_INVALID, [lev]));
  1982.         ResetLevelData;
  1983.       end;
  1984.     end;
  1985.     {$ENDREGION}
  1986.   end;
  1987. end;
  1988.  
  1989. procedure TMainForm.SceneTitle;
  1990. var
  1991.   Logo: TPictureCollectionItem;
  1992. begin
  1993.   DXDraw.Surface.Fill(0);
  1994.   Logo := GetSpriteGraphic(smgLogo);
  1995.   {Logo.DrawWaveX(DXDraw.Surface, (dxdraw.surfaceWidth div 2) - 181, 65, Logo.Width, Logo.Height, 0,
  1996.     Trunc(16 - Cos256(FBlink div 60) * 16), 32, -FBlink div 5);}
  1997.   Logo.DrawWaveX(DXDraw.Surface, trunc((dxdraw.surfaceWidth / 2) - (Logo.Width / 2)), 65, Logo.Width, Logo.Height, 0,
  1998.     2, 80, Fangle * 4);
  1999.   inc(Fangle);
  2000.  
  2001.   if (isDown in MainForm.DXInput.States) and (FGameMode=gmLevels) then FGameMode := gmRandom;
  2002.   if ((isUp in MainForm.DXInput.States) and (FGameMode=gmRandom)) or (FGameMode=gmUnknown) then FGameMode := gmLevels;
  2003.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2004.   DXDraw.Surface.Canvas.Font.Size := 30;
  2005.   if FGameMode = gmLevels then
  2006.   begin
  2007.     DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2008.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-52, 'Normales Spiel');
  2009.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, (dxdraw.surfaceheight div 2)-52, '>');
  2010.     DXDraw.Surface.Canvas.Font.Color := clRed;
  2011.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)-50, 'Normales Spiel');
  2012.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)-50, '>');
  2013.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2014.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-2, 'Zufallslevel');
  2015.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2016.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2), 'Zufallslevel');
  2017.   end
  2018.   else
  2019.   begin
  2020.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2021.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-52, 'Normales Spiel');
  2022.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2023.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)-50, 'Normales Spiel');
  2024.     DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2025.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-2, 'Zufallslevel');
  2026.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, (dxdraw.surfaceheight div 2)-2, '>');
  2027.     DXDraw.Surface.Canvas.Font.Color := clRed;
  2028.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2), 'Zufallslevel');
  2029.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2), '>');
  2030.   end;
  2031.   { if (FBlink div 300) mod 2=0 then
  2032.   begin
  2033.     DXDraw.Surface.Canvas.Font.Color := clGreen;
  2034.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2035.     DXDraw.Surface.Canvas.Font.Color := clLime;
  2036.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2037.   end; }
  2038.   BlinkUpdate;
  2039.   DXDraw.Surface.Canvas.Release;
  2040.  
  2041.   // Weiter mit Leertaste oder Enter
  2042.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2043.   begin
  2044.     FLevel := 1;
  2045.     if ((FGameMode=gmLevels) and not fileexists(GetLevelFileName(FLevel))) or ((FGameMode=gmRandom) and (FLevel > 20)) then
  2046.     begin
  2047.       //PlaySound('Frage', False);
  2048.       exit;
  2049.     end;
  2050.     NewLevel(FLevel);
  2051.     PlaySound(smsSceneMov, False);
  2052.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2053.     Sleep(200);
  2054.     StartScene(gsMain);
  2055.   end;
  2056. end;
  2057.  
  2058. procedure TMainForm.SceneMain;
  2059. var
  2060.   Enemy: TSprite;
  2061.   spriteClass: TEnemyClass;
  2062. begin
  2063.   case FInterval of
  2064.     giLeicht: SpriteEngine.Move(conleicht);
  2065.     giMittel: SpriteEngine.Move(conmittel);
  2066.     giSchwer: SpriteEngine.Move(conschwer);
  2067.     giMaster: SpriteEngine.Move(conmaster);
  2068.   end;
  2069.   SpriteEngine.Dead;
  2070.   while (FEnemyAdventPos >= Low(LevelData.EnemyAdventTable)) and
  2071.     (FEnemyAdventPos <= High(LevelData.EnemyAdventTable)) and
  2072.     ((LevelData.EnemyAdventTable[FEnemyAdventPos].x / 4) <= FFrame) and
  2073.     (FRestEnemies > 0) do
  2074.   begin
  2075.     Dec(FRestEnemies);
  2076.     with LevelData.EnemyAdventTable[FEnemyAdventPos] do
  2077.     begin
  2078.       spriteClass := nil;
  2079.       case enemyType of
  2080.         //etUnknown: ;
  2081.         etEnemyAttacker:  spriteClass := TEnemyAttacker;
  2082.         etEnemyAttacker2: spriteClass := TEnemyAttacker2;
  2083.         etEnemyAttacker3: spriteClass := TEnemyAttacker3;
  2084.         etEnemyMeteor:    spriteClass := TEnemyMeteor;
  2085.         etEnemyUFO:       spriteClass := TEnemyUFO;
  2086.         etEnemyUFO2:      spriteClass := TEnemyUFO2;
  2087.         etEnemyBoss:      spriteClass := TEnemyBoss;
  2088.       end;
  2089.       if spriteClass <> nil then
  2090.       begin
  2091.         Enemy := spriteClass.Create(SpriteEngine.Engine, lifes);
  2092.         Enemy.x := dxdraw.surfacewidth;
  2093.         //Enemy.y := y;
  2094.         if y <> 0 then
  2095.           Enemy.y := dxdraw.surfaceheight / (480{maximale Bandbreite im alten Format} / y)
  2096.         else
  2097.           Enemy.y := 0;
  2098.       end;
  2099.     end;
  2100.     Inc(FEnemyAdventPos);
  2101.   end;
  2102.   Inc(FFrame);
  2103.   DXDraw.Surface.Fill(0);
  2104.   if FNextScene=gsNone then
  2105.   begin
  2106.     SpriteEngine.Draw;
  2107.     if MainForm.flife > 0 then
  2108.     begin
  2109.       DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2110.       DXDraw.Surface.Canvas.Font.Size := 20;
  2111.       DXDraw.Surface.Canvas.Font.Color := clOlive;
  2112.       DXDraw.Surface.Canvas.Textout(9, 9, 'Punkte: ' + FloatToStrF(FScore,ffNumber,14,0));
  2113.       DXDraw.Surface.Canvas.Font.Color := clYellow;
  2114.       DXDraw.Surface.Canvas.Textout(10, 10, 'Punkte: ' + FloatToStrF(FScore,ffNumber,14,0));
  2115.       DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2116.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-141, 9, 'Level: ' + IntToStr(MainForm.flevel));
  2117.       DXDraw.Surface.Canvas.Font.Color := clRed;
  2118.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-140, 10, 'Level: ' + IntToStr(MainForm.flevel));
  2119.       if FLife<0 then mainform.FLife := 0;
  2120.       if FCheat then
  2121.       begin
  2122.         DXDraw.Surface.Canvas.Font.Color := clPurple;
  2123.         DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, 'Leben: ?');
  2124.         DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2125.         DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, 'Leben: ?');
  2126.       end
  2127.       else
  2128.       begin
  2129.         if ((Flife = 1) and ((FBlink div 300) mod 2=0)) or (Flife <> 1) then
  2130.         begin
  2131.           DXDraw.Surface.Canvas.Font.Color := clPurple;
  2132.           DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, 'Leben: ' + IntToStr(MainForm.flife));
  2133.           DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2134.           DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, 'Leben: ' + IntToStr(MainForm.flife));
  2135.         end;
  2136.         if Flife = 1 then BlinkUpdate;
  2137.       end;
  2138.       {if BossExists and (FBossLife>0) then
  2139.       begin
  2140.         DXDraw.Surface.Canvas.Font.Color := clPurple;
  2141.         DXDraw.Surface.Canvas.Textout(449, 439, 'Boss: ' + IntToStr(FBossLife));
  2142.         DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2143.         DXDraw.Surface.Canvas.Textout(450, 440, 'Boss: ' + IntToStr(FBossLife));
  2144.       end
  2145.       else
  2146.         if RestlicheEinheiten>0 then
  2147.         begin
  2148.           DXDraw.Surface.Canvas.Font.Color := clPurple;
  2149.           DXDraw.Surface.Canvas.Textout(449, 439, 'Einheiten: ' + IntToStr(RestlicheEinheiten));
  2150.           DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2151.           DXDraw.Surface.Canvas.Textout(450, 440, 'Einheiten: ' + IntToStr(RestlicheEinheiten));
  2152.         end;}
  2153.       if BossExists and (FBossLife>0) then
  2154.       begin
  2155.         if (FRestEnemies>0) then
  2156.         begin
  2157.           DXDraw.Surface.Canvas.Font.Color := clGreen;
  2158.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-81, 'Boss: ' + IntToStr(FBossLife));
  2159.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Einheiten: ' + IntToStr(FRestEnemies));
  2160.           DXDraw.Surface.Canvas.Font.Color := clLime;
  2161.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-80, 'Boss: ' + IntToStr(FBossLife));
  2162.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Einheiten: ' + IntToStr(FRestEnemies));
  2163.         end;
  2164.         if (FRestEnemies<1) then
  2165.         begin
  2166.           DXDraw.Surface.Canvas.Font.Color := clGreen;
  2167.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Boss: ' + IntToStr(FBossLife));
  2168.           DXDraw.Surface.Canvas.Font.Color := clLime;
  2169.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Boss: ' + IntToStr(FBossLife));
  2170.         end;
  2171.       end;
  2172.       if (FRestEnemies>0) and not Bossexists then
  2173.       begin
  2174.         DXDraw.Surface.Canvas.Font.Color := clGreen;
  2175.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Einheiten: ' + IntToStr(FRestEnemies));
  2176.         DXDraw.Surface.Canvas.Font.Color := clLime;
  2177.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Einheiten: ' + IntToStr(FRestEnemies));
  2178.       end;
  2179.       if (EnemyCounter=0) and (FRestEnemies=0) and ((BossExists and (FBossLife=0)) or not BossExists) then
  2180.       begin
  2181.         DXDraw.Surface.Canvas.Font.Color := clGreen;
  2182.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, 'Mission erfolgreich!');
  2183.         DXDraw.Surface.Canvas.Font.Color := clLime;
  2184.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, 'Mission erfolgreich!');
  2185.         DXDraw.Surface.Canvas.Release;
  2186.         Sleep(1); // TODO: man merkt hier einen lag!
  2187.         inc(FCounter);
  2188.         if FCounter>150{200} then PlayerSprite.FlyAway;
  2189.       end;
  2190.     end
  2191.     else
  2192.     begin
  2193.       DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2194.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, 'Mission gescheitert!');
  2195.       DXDraw.Surface.Canvas.Font.Color := clRed;
  2196.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, 'Mission gescheitert!');
  2197.     end;
  2198.     DXDraw.Surface.Canvas.Release;
  2199.   end;
  2200. end;
  2201.  
  2202. procedure TMainForm.SceneGameOver;
  2203. begin
  2204.   DXDraw.Surface.Fill(0);
  2205.  
  2206.   FNotSave := true;
  2207.   Cheat.enabled := false;
  2208.   GamePause.enabled := false;
  2209.   Neustart.enabled := false;
  2210.   Brush.Style := bsClear;
  2211.   DXDraw.Surface.Canvas.Font.Size := 35;
  2212.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2213.   DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-127, 98, 'Game over!');
  2214.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2215.   DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-125, 100, 'Game over!');
  2216.   if (FBlink div 300) mod 2=0 then
  2217.   begin
  2218.     DXDraw.Surface.Canvas.Font.Size := 30;
  2219.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2220.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2221.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2222.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2223.   end;
  2224.   BlinkUpdate;
  2225.   DXDraw.Surface.Canvas.Release;
  2226.  
  2227.   // Weiter mit Leertaste oder Enter
  2228.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2229.   begin
  2230.     PlaySound(smsSceneMov, False);
  2231.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2232.     Sleep(200);
  2233.     StartScene(gsTitle);
  2234.   end;
  2235. end;
  2236.  
  2237. procedure TMainForm.SceneWin;
  2238. begin
  2239.   DXDraw.Surface.Fill(0);
  2240.  
  2241.   FNotSave := true;
  2242.   Cheat.enabled := false;
  2243.   GamePause.enabled := false;
  2244.   Neustart.enabled := false;
  2245.  
  2246.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2247.   DXDraw.Surface.Canvas.Font.Size := 35;
  2248.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2249.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-127, 98, 'Gewonnen!');
  2250.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2251.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-125, 100, 'Gewonnen!');
  2252.   if (FBlink div 300) mod 2=0 then
  2253.   begin
  2254.     DXDraw.Surface.Canvas.Font.Size := 30;
  2255.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2256.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2257.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2258.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2259.   end;
  2260.   BlinkUpdate;
  2261.   DXDraw.Surface.Canvas.Release;
  2262.  
  2263.   // Weiter mit Leertaste oder Enter
  2264.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2265.   begin
  2266.     PlaySound(smsSceneMov, False);
  2267.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2268.     Sleep(200);
  2269.     StartScene(gsTitle);
  2270.   end;
  2271. end;
  2272.  
  2273. procedure TMainForm.StartSceneNewLevel;
  2274. begin
  2275.   sleep(500);
  2276.   FNotSave := false;
  2277.   Cheat.enabled := false;
  2278.   Neustart.enabled := false;
  2279.   GamePause.enabled := false;
  2280.   GameStart.enabled := true;
  2281.   Spielgeschwindigkeit.enabled := false;
  2282.   BossExists := false;
  2283.   Spielgeschwindigkeit.enabled := false;
  2284.   if ((FGameMode=gmLevels) and (not fileexists(GetLevelFileName(FLevel)))) or ((FGameMode=gmRandom) and (FLevel > 25)) then
  2285.   begin
  2286.     //PlaySound('SceneMov', False);
  2287.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2288.     Sleep(200);
  2289.     StartScene(gsWin);
  2290.     exit;
  2291.   end;
  2292.   MusicSwitchTrack(smmScene);
  2293. end;
  2294.  
  2295. procedure TMainForm.EndSceneNewLevel;
  2296. begin
  2297.   {  Ende NewLevel  }
  2298. end;
  2299.  
  2300. procedure TMainForm.SceneNewLevel;
  2301. begin
  2302.   DXDraw.Surface.Fill(0);
  2303.  
  2304.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2305.   DXDraw.Surface.Canvas.Font.Size := 40;
  2306.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2307.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(83+(length(inttostr(flevel))*22)), 98, 'Level '+inttostr(flevel));
  2308.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2309.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(81+(length(inttostr(flevel))*22)), 100, 'Level '+inttostr(flevel));
  2310.   if (FBlink div 300) mod 2=0 then
  2311.   begin
  2312.     DXDraw.Surface.Canvas.Font.Size := 30;
  2313.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2314.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2315.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2316.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2317.   end;
  2318.   BlinkUpdate;
  2319.   DXDraw.Surface.Canvas.Release;
  2320.  
  2321.   // Weiter mit Leertaste oder Enter
  2322.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2323.   begin
  2324.     PlaySound(smsSceneMov, False);
  2325.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2326.     Sleep(200);
  2327.     StartScene(gsMain);
  2328.   end;
  2329. end;
  2330.  
  2331. procedure TMainForm.OptionMusicClick(Sender: TObject);
  2332. begin
  2333.   OptionMusic.Checked := not OptionMusic.Checked;
  2334.   if OptionMusic.Checked then
  2335.   begin
  2336.     MusicSwitchTrack(FMusic)
  2337.   end
  2338.   else
  2339.   begin
  2340.     StopMusic(FMusic);
  2341.   end;
  2342.   WriteOptions;
  2343. end;
  2344.  
  2345. procedure TMainForm.MasterClick(Sender: TObject);
  2346. begin
  2347.   master.checked := true;
  2348.   FInterval := giMaster;
  2349.   writeoptions;
  2350. end;
  2351.  
  2352. procedure TMainForm.PlayMusic(Name: TSpaceMissionMusicTrack);
  2353. begin
  2354.   if not OptionMusic.checked then exit;
  2355.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2356.   dxmusic.Midis.Items[Ord(Name)-1].Play;
  2357. end;
  2358.  
  2359. procedure TMainForm.StopMusic(Name: TSpaceMissionMusicTrack);
  2360. begin
  2361.   if Name = smmNone then exit;
  2362.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2363.   dxmusic.Midis.Items[Ord(Name)-1].Stop;
  2364. end;
  2365.  
  2366. procedure TMainForm.ResumeMusic(Name: TSpaceMissionMusicTrack);
  2367. begin
  2368.   if not OptionMusic.checked then exit;
  2369.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2370.   dxmusic.Midis.Items[Ord(Name)-1].Play; // TODO: how to pause/resume instead play/stop
  2371. end;
  2372.  
  2373. procedure TMainForm.PauseMusic(Name: TSpaceMissionMusicTrack);
  2374. begin
  2375.   if Name = smmNone then exit;
  2376.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2377.   dxmusic.Midis.Items[Ord(Name)-1].Stop; // TODO: how to pause/resume instead play/stop
  2378. end;
  2379.  
  2380. procedure TMainForm.SpielstandClick(Sender: TObject);
  2381. begin
  2382.   speicherungform.showmodal;
  2383. end;
  2384.  
  2385. procedure TMainForm.NeustartClick(Sender: TObject);
  2386. begin
  2387.   FLife := Lives;
  2388.   FLevel := 1; // ???
  2389.   FScore := 0;
  2390.   EnemyCounter := 0;
  2391.   StartScene(gsMain);
  2392.   MusicSwitchTrack(smmGame);
  2393. end;
  2394.  
  2395. procedure TMainForm.LeichtClick(Sender: TObject);
  2396. begin
  2397.   leicht.checked := true;
  2398.   FInterval := giLeicht;
  2399.   writeoptions;
  2400. end;
  2401.  
  2402. procedure TMainForm.MittelClick(Sender: TObject);
  2403. begin
  2404.   mittel.checked := true;
  2405.   FInterval := giMittel;
  2406.   writeoptions;
  2407. end;
  2408.  
  2409. procedure TMainForm.SchwerClick(Sender: TObject);
  2410. begin
  2411.   schwer.checked := true;
  2412.   FInterval := giSchwer;
  2413.   writeoptions;
  2414. end;
  2415.  
  2416. procedure TMainForm.FormShow(Sender: TObject);
  2417. begin
  2418.   if Assigned(SplashForm) then
  2419.   begin
  2420.     SplashForm.Hide;
  2421.     FreeAndNil(SplashForm);
  2422.   end;
  2423.  
  2424.   dxtimer.Enabled := true;
  2425.   dxtimer.ActiveOnly := true;
  2426. end;
  2427.  
  2428. procedure TMainForm.InformationenClick(Sender: TObject);
  2429. begin
  2430.   dxtimer.enabled := false;
  2431.   InfoForm.showmodal;
  2432.   if not mainform.gamepause.checked then mainform.dxtimer.enabled := true;
  2433. end;
  2434.  
  2435. procedure TMainForm.CheatClick(Sender: TObject);
  2436. begin
  2437.   CheatForm.showmodal;
  2438. end;
  2439.  
  2440. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
  2441. begin
  2442.   if optionMusic.checked then StopMusic(FMusic);
  2443.   SpriteEngine.Engine.Clear;
  2444.   dxsound.Finalize;
  2445.   dxinput.Destroy;
  2446.   DXTimer.Enabled := False;
  2447. end;
  2448.  
  2449. procedure TMainForm.FormDestroy(Sender: TObject);
  2450. begin
  2451.   FreeAndNil(imagelist);
  2452.   FreeAndNil(spriteengine);
  2453.   FreeAndNil(dxdraw);
  2454.   FreeAndNil(wavelist);
  2455.   FreeAndNil(dxsound);
  2456.   //FreeAndNil(dxinput);
  2457.   FreeAndNil(dxtimer);
  2458.   FreeAndNil(dxmusic);
  2459.   DeleteCriticalSection(TimerCS);
  2460.   FreeAndNil(LevelData);
  2461. end;
  2462.  
  2463. end.
  2464.  
  2465.