Subversion Repositories spacemission

Rev

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

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