Subversion Repositories spacemission

Rev

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

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