Subversion Repositories spacemission

Rev

Rev 27 | Rev 30 | 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.         showmessage(SFileError);
  1380.         GameStartClick(GameStart);
  1381.         exit;
  1382.       end;
  1383.     finally
  1384.       FreeAndNil(SavGame);
  1385.     end;
  1386.     mainform.FNextScene := gsNewLevel;
  1387.     exit;
  1388.   end;
  1389.   GameStartClick(GameStart);
  1390. end;
  1391.  
  1392. procedure TMainForm.GameStartClick(Sender: TObject);
  1393. begin
  1394.   StartScene(gsTitle);
  1395. end;
  1396.  
  1397. procedure TMainForm.GamePauseClick(Sender: TObject);
  1398. begin
  1399.   GamePause.Checked := not GamePause.Checked;
  1400.   DXTimer.Enabled := not GamePause.Checked;
  1401.   if GamePause.Checked then
  1402.   begin
  1403.     if Assigned(DXTimer.OnDeactivate) then
  1404.       DXTimer.OnDeactivate(DXTimer);
  1405.   end
  1406.   else
  1407.   begin
  1408.     if Assigned(DXTimer.OnActivate) then
  1409.       DXTimer.OnActivate(DXTimer);
  1410.   end;
  1411. end;
  1412.  
  1413. procedure TMainForm.DXInit;
  1414. begin
  1415.   try
  1416.     Imagelist.Items.LoadFromFile(FDirectory+'DirectX\Graphic.dxg');
  1417.     ImageList.Items.MakeColorTable;
  1418.     DXDraw.ColorTable := ImageList.Items.ColorTable;
  1419.     DXDraw.DefColorTable := ImageList.Items.ColorTable;
  1420.     DXDraw.UpdatePalette;
  1421.     DXDraw.Finalize;
  1422.     DXDraw.Options := DXDraw.Options - [doFullScreen];
  1423.     DXDraw.autosize := true;
  1424.     DXDraw.Initialize;
  1425.   except
  1426.     //Imagelist.Items.clear;
  1427.     //application.terminate;
  1428.   end;
  1429. end;
  1430.  
  1431. procedure TMainForm.CheckUpdatesClick(Sender: TObject);
  1432. var
  1433.   cont: string;
  1434. begin
  1435.   cont := GetHTML('https://www.viathinksoft.de/update/?id=spacemission');
  1436.   if copy(cont, 0, 7) = 'Status:' then
  1437.   begin
  1438.     Application.MessageBox('Ein Fehler ist aufgetreten. Wahrscheinlich ist keine Internetverbindung aufgebaut, oder der der ViaThinkSoft-Server vorübergehend offline.', 'Fehler', MB_OK + MB_ICONERROR)
  1439.   end
  1440.   else
  1441.   begin
  1442.     if cont <> ProgramVersion then
  1443.     begin
  1444.       if Application.MessageBox('Eine neue Programmversion ist vorhanden. Möchten Sie diese jetzt herunterladen?', 'Information', MB_YESNO + MB_ICONASTERISK) = ID_YES then
  1445.         shellexecute(application.handle, 'open', pchar('https://www.viathinksoft.de/update/?id=@spacemission'), '', '', sw_normal);
  1446.     end
  1447.     else
  1448.     begin
  1449.       Application.MessageBox('Es ist keine neue Programmversion vorhanden.', 'Information', MB_OK + MB_ICONASTERISK);
  1450.     end;
  1451.   end;
  1452. end;
  1453.  
  1454. procedure TMainForm.BeendenClick(Sender: TObject);
  1455. begin
  1456.   close;
  1457. end;
  1458.  
  1459. procedure TMainForm.OptionSoundClick(Sender: TObject);
  1460. begin
  1461.   OptionSound.Checked := not OptionSound.Checked;
  1462.   SoundInit;
  1463.   WriteOptions;
  1464. end;
  1465.  
  1466. procedure TMainForm.SoundInit;
  1467. begin
  1468.   if (WaveOutGetNumDevs < 1) or not FileExists(FDirectory+'DirectX\Sound.dxw') then
  1469.   begin
  1470.     OptionSound.Checked := false;
  1471.     OptionSound.Enabled := False;
  1472.     exit;
  1473.   end;
  1474.  
  1475.   if OptionSound.Checked then
  1476.   begin
  1477.     if not DXSound.Initialized then
  1478.     begin
  1479.       try
  1480.         DXSound.Initialize;
  1481.         WaveList.Items.LoadFromFile(FDirectory+'DirectX\Sound.dxw');
  1482.       except
  1483.         OptionSound.enabled := False;
  1484.         WaveList.items.clear;
  1485.       end;
  1486.     end;
  1487.   end
  1488.   else DXSound.Finalize;
  1489. end;
  1490.  
  1491. procedure TMainForm.MusicInit;
  1492. var
  1493.   i: integer;
  1494. begin
  1495.   if (WaveOutGetNumDevs < 1) or not FileExists(FDirectory+'DirectX\Music.dxm') then
  1496.   begin
  1497.     optionmusic.Checked := false;
  1498.     optionmusic.Enabled := False;
  1499.     exit;
  1500.   end;
  1501.  
  1502.   try
  1503.     dxmusic.Midis.LoadFromFile(FDirectory+'DirectX\Music.dxm');
  1504.     for i := 0 to dxmusic.Midis.Count-1 do
  1505.     begin
  1506.       if not dxmusic.Midis.Items[i].IsInitialized then
  1507.       begin
  1508.         dxmusic.Midis.Items[i].Init;
  1509.         dxmusic.Midis.Items[i].Load;
  1510.       end;
  1511.     end;
  1512.   except
  1513.     optionmusic.enabled := false;
  1514.   end;
  1515. end;
  1516.  
  1517. procedure TMainForm.DXDrawInitializing(Sender: TObject);
  1518. begin
  1519.   if doFullScreen in DXDraw.Options then
  1520.   begin
  1521.     BorderStyle := bsNone;
  1522.     DXDraw.Cursor := crNone;
  1523.   end
  1524.   else
  1525.   begin
  1526.     BorderStyle := bsSingle;
  1527.     DXDraw.Cursor := crDefault;
  1528.   end;
  1529. end;
  1530.  
  1531. procedure TMainForm.DXDrawInitialize(Sender: TObject);
  1532. begin
  1533.   DXTimer.Enabled := True;
  1534. end;
  1535.  
  1536. procedure TMainForm.DXDrawFinalize(Sender: TObject);
  1537. begin
  1538.   DXTimer.Enabled := False;
  1539. end;
  1540.  
  1541. procedure TMainForm.DXTimerActivate(Sender: TObject);
  1542. begin
  1543.   if TDxTimer(Sender).Tag > 0 then
  1544.     TDxTimer(Sender).Tag := TDxTimer(Sender).Tag - 1; // es können mehrere activate/deactivate vorkommen, wegen dem Pause-Button
  1545.   if TDxTimer(Sender).Tag > 0 then
  1546.     exit;
  1547.   Caption := Application.Title;
  1548.   if not ProgrammGestartet then
  1549.   begin
  1550.     Programmgestartet := true;
  1551.     exit;
  1552.   end;
  1553.   ResumeMusic(FMusic);
  1554. end;
  1555.  
  1556. procedure TMainForm.DXTimerDeactivate(Sender: TObject);
  1557. begin
  1558.   TDxTimer(Sender).Tag := TDxTimer(Sender).Tag + 1;
  1559.   Caption := Application.Title + ' [Pause]';
  1560.   PauseMusic(FMusic);
  1561. end;
  1562.  
  1563. procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
  1564. begin
  1565.   EnterCriticalSection(TimerCS);
  1566.   try
  1567.     if crash then
  1568.     begin
  1569.       inc(Crash2);
  1570.       if crash2 = 30 then
  1571.       begin
  1572.         Crash2 := 0;
  1573.         crash := false;
  1574.         crashsound := false;
  1575.       end;
  1576.     end;
  1577.     if not DXDraw.CanDraw then exit;
  1578.     DXInput.Update;
  1579.     case FScene of
  1580.       gsTitle   : SceneTitle;
  1581.       gsMain    : SceneMain;
  1582.       gsGameOver: SceneGameOver;
  1583.       gsWin     : SceneWin;
  1584.       gsNewLevel: SceneNewLevel;
  1585.     end;
  1586.     if FNextScene<>gsNone then
  1587.     begin
  1588.       StartScene(FNextScene);
  1589.       FNextScene := gsNone;
  1590.     end;
  1591.     DXDraw.Flip;
  1592.   finally
  1593.     LeaveCriticalSection(TimerCS);
  1594.   end;
  1595. end;
  1596.  
  1597. procedure TMainForm.BlinkStart;
  1598. begin
  1599.   FBlink := 0;
  1600.   FBlinkTime := GetTickCount;
  1601. end;
  1602.  
  1603. const
  1604.   RegistrySettingsKey = 'SOFTWARE\ViaThinkSoft\SpaceMission\Settings';
  1605.  
  1606. procedure TMainForm.WriteOptions;
  1607. var
  1608.   Reg: TRegistry;
  1609. begin
  1610.   Reg := TRegistry.Create;
  1611.   try
  1612.     Reg.RootKey := HKEY_CURRENT_USER;
  1613.     if Reg.OpenKey(RegistrySettingsKey, true) then
  1614.     begin
  1615.       Reg.WriteBool('Music', OptionMusic.checked);
  1616.       Reg.WriteBool('Sound', OptionSound.checked);
  1617.       Reg.WriteInteger('Speed', Ord(FInterval));
  1618.       Reg.CloseKey;
  1619.     end;
  1620.   finally
  1621.     FreeAndNil(Reg);
  1622.   end;
  1623. end;
  1624.  
  1625. procedure TMainForm.LoadOptions;
  1626. var
  1627.   Reg: TRegistry;
  1628. begin
  1629.   Reg := TRegistry.Create;
  1630.   try
  1631.     Reg.RootKey := HKEY_CURRENT_USER;
  1632.     if Reg.OpenKey(RegistrySettingsKey, true) then
  1633.     begin
  1634.       if Reg.ValueExists('Music') then
  1635.         optionmusic.checked := Reg.ReadBool('Music')
  1636.       else
  1637.         optionmusic.checked := true; // default
  1638.  
  1639.       if Reg.ValueExists('Sound') then
  1640.         optionsound.checked := Reg.ReadBool('Sound')
  1641.       else
  1642.         optionsound.checked := true; // default
  1643.  
  1644.       if Reg.ValueExists('Speed') then
  1645.         FInterval := TGameInterval(Reg.ReadInteger('Speed'))
  1646.       else
  1647.         FInterval := giMittel; // default
  1648.  
  1649.       Reg.CloseKey;
  1650.     end;
  1651.   finally
  1652.     FreeAndNil(Reg);
  1653.   end;
  1654.   WriteOptions;
  1655. end;
  1656.  
  1657. procedure TMainForm.BlinkUpdate;
  1658. begin
  1659.   if GetTickCount<>FBlinkTime then
  1660.   begin
  1661.     FBlink := FBlink + (GetTickCount-FBlinkTime);
  1662.     FBlinkTime := GetTickCount;
  1663.   end;
  1664. end;
  1665.  
  1666. procedure TMainForm.PlaySound(Name: string; Wait: Boolean);
  1667. begin
  1668.   if (OptionSound.Checked) and (OptionSound.Enabled) then
  1669.     WaveList.Items.Find(Name).Play(Wait);
  1670. end;
  1671.  
  1672. procedure TMainForm.MusicSwitchTrack(Name: TMusicTrack);
  1673. begin
  1674.   if (not mainform.active) and (mainform.visible) then //1st Programmstart
  1675.     exit;
  1676.   if (OptionMusic.checked) and (OptionMusic.enabled) then
  1677.   begin
  1678.     StopMusic(FMusic);
  1679.     PlayMusic(Name);
  1680.   end;
  1681.   FMusic := Name;
  1682. end;
  1683.  
  1684. function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
  1685. begin
  1686.   with Result do
  1687.   begin
  1688.     rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256);
  1689.     rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256);
  1690.     rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256);
  1691.     rgbReserved := 0;
  1692.   end;
  1693. end;
  1694.  
  1695. procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer);
  1696. var
  1697.   i: Integer;
  1698.   t, t2: DWORD;
  1699.   ChangePalette: Boolean;
  1700.   c: Integer;
  1701. begin
  1702.   if DXDraw.Initialized then
  1703.   begin
  1704.     c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue));
  1705.     ChangePalette := False;
  1706.     if DXDraw.CanPaletteAnimation then
  1707.     begin
  1708.       t := GetTickCount;
  1709.       while Abs(GetTickCount-t)<Time do
  1710.       begin
  1711.         t2 := Trunc(Abs(GetTickCount-t)/Time*255);
  1712.         for i := 0 to 255 do
  1713.           DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2);
  1714.         DXDraw.UpdatePalette;
  1715.         ChangePalette := True;
  1716.       end;
  1717.     end
  1718.     else
  1719.     begin
  1720.       Sleep(Time);
  1721.     end;
  1722.     for i := 0 to 4 do
  1723.     begin
  1724.       DXDraw.Surface.Fill(c);
  1725.       DXDraw.Flip;
  1726.     end;
  1727.     if ChangePalette then
  1728.     begin
  1729.       DXDraw.ColorTable := DXDraw.DefColorTable;
  1730.       DXDraw.UpdatePalette;
  1731.     end;
  1732.     DXDraw.Surface.Fill(c);
  1733.     DXDraw.Flip;
  1734.   end;
  1735. end;
  1736.  
  1737. procedure TMainForm.StartScene(Scene: TGameScene);
  1738. begin
  1739.   EndScene;
  1740.   DXInput.States := DXInput.States - DXInputButton;
  1741.   FScene := Scene;
  1742.   BlinkStart;
  1743.   case FScene of
  1744.     gsTitle   : StartSceneTitle;
  1745.     gsMain    : StartSceneMain;
  1746.     gsGameOver: StartSceneGameOver;
  1747.     gsWin     : StartSceneWin;
  1748.     gsNewLevel: StartSceneNewLevel;
  1749.   end;
  1750. end;
  1751.  
  1752. procedure TMainForm.StartSceneTitle;
  1753. begin
  1754.   sleep(500);
  1755.   FCheat := false;
  1756.   BossExists := false;
  1757.   FLife := Lives;
  1758.   FLevel := 0;
  1759.   FScore := 0;
  1760.   FNotSave := true;
  1761.   Cheat.enabled := false;
  1762.   Neustart.enabled := false;
  1763.   GamePause.enabled := false;
  1764.   GameStart.enabled := false;
  1765.   Spielgeschwindigkeit.enabled := false;
  1766.   mainform.Visible := true;
  1767.   MusicSwitchTrack(mtTitle);
  1768. end;
  1769.  
  1770. procedure TMainForm.StartSceneMain;
  1771. {var
  1772.   i, j: Integer;}
  1773. begin
  1774.   sleep(500);
  1775.   FCounter := 0;
  1776.   NewLevel(FLevel);
  1777.   BossExists := false;
  1778.   MusicSwitchTrack(mtGame);
  1779.   FEnemyAdventPos := 0;
  1780.   FFrame := -4;
  1781.   PlayerSprite := TPlayerSprite.Create(SpriteEngine.Engine);
  1782.   with TBackground.Create(SpriteEngine.Engine) do
  1783.   begin
  1784.     SetMapSize(1, 1);
  1785.     Image := mainform.ImageList.Items.Find('Star3');
  1786.     Z := -13;
  1787.     Y := 40;
  1788.     Speed := 1 / 2;
  1789.     Tile := True;
  1790.   end;
  1791.   with TBackground.Create(SpriteEngine.Engine) do
  1792.   begin
  1793.     SetMapSize(1, 1);
  1794.     Image := mainform.ImageList.Items.Find('Star2');
  1795.     Z := -12;
  1796.     Y := 30;
  1797.     Speed := 1;
  1798.     Tile := True;
  1799.   end;
  1800.   with TBackground.Create(SpriteEngine.Engine) do
  1801.   begin
  1802.     SetMapSize(1, 1);
  1803.     Image := mainform.ImageList.Items.Find('Star1');
  1804.     Z := -11;
  1805.     Y := 10;
  1806.     Speed := 2;
  1807.     Tile := True;
  1808.   end;
  1809.   {with TBackground.Create(SpriteEngine.Engine) do
  1810.   begin
  1811.     SetMapSize(200, 10);
  1812.     Y := 10;
  1813.     Z := -13;
  1814.     Speed := 1 / 2;
  1815.     Tile := True;
  1816.     for i := 0 to MapHeight-1 do
  1817.     begin
  1818.       for j := 0 to MapWidth-1 do
  1819.       begin
  1820.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8);
  1821.         if Random(100)<95 then Chips[j, i] := -1;
  1822.       end;
  1823.     end;
  1824.   end;
  1825.   with TBackground.Create(SpriteEngine.Engine) do
  1826.   begin
  1827.     SetMapSize(200, 10);
  1828.     Y := 30;
  1829.     Z := -12;
  1830.     Speed := 1;
  1831.     Tile := True;
  1832.     for i := 0 to MapHeight-1 do
  1833.     begin
  1834.       for j := 0 to MapWidth-1 do
  1835.       begin
  1836.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4);
  1837.         if Random(100)<95 then Chips[j, i] := -1;
  1838.       end;
  1839.     end;
  1840.   end;
  1841.   with TBackground.Create(SpriteEngine.Engine) do
  1842.   begin
  1843.     SetMapSize(200, 10);
  1844.     Y := 40;
  1845.     Z := -11;
  1846.     Speed := 2;
  1847.     Tile := True;
  1848.     for i := 0 to MapHeight-1 do
  1849.     begin
  1850.       for j := 0 to MapWidth-1 do
  1851.       begin
  1852.         Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2);
  1853.         if Random(100)<95 then Chips[j, i] := -1;
  1854.       end;
  1855.     end;
  1856.   end;}
  1857.   FNotSave := false;
  1858.   Cheat.enabled := true;
  1859.   Neustart.enabled := true;
  1860.   GamePause.enabled := true;
  1861.   GameStart.enabled := true;
  1862.   Spielgeschwindigkeit.enabled := true;
  1863. end;
  1864.  
  1865. procedure TMainForm.StartSceneGameOver;
  1866. begin
  1867.   sleep(500);
  1868.   FNotSave := true;
  1869.   Cheat.enabled := false;
  1870.   Spielgeschwindigkeit.enabled := false;
  1871.   Neustart.enabled := false;
  1872.   GamePause.enabled := false;
  1873.   MusicSwitchTrack(mtScene);
  1874.   BossExists := false;
  1875. end;
  1876.  
  1877. procedure TMainForm.StartSceneWin;
  1878. begin
  1879.   sleep(500);
  1880.   FNotSave := true;
  1881.   Cheat.enabled := false;
  1882.   Spielgeschwindigkeit.enabled := false;
  1883.   Neustart.enabled := false;
  1884.   GamePause.enabled := false;
  1885.   MusicSwitchTrack(mtScene);
  1886.   BossExists := false;
  1887. end;
  1888.  
  1889. procedure TMainForm.EndScene;
  1890. begin
  1891.   case FScene of
  1892.     gsTitle   : EndSceneTitle;
  1893.     gsMain    : EndSceneMain;
  1894.     gsGameOver: EndSceneGameOver;
  1895.     gsWin     : EndSceneWin;
  1896.     gsNewLevel: EndSceneNewLevel;
  1897.   end;
  1898. end;
  1899.  
  1900. procedure TMainForm.EndSceneTitle;
  1901. begin
  1902.   {  Ende Title  }
  1903. end;
  1904.  
  1905. procedure TMainForm.EndSceneMain;
  1906. begin
  1907.   SpriteEngine.Engine.Clear;
  1908. end;
  1909.  
  1910. procedure TMainForm.EndSceneGameOver;
  1911. begin
  1912.   {  Ende GameOver  }
  1913. end;
  1914.  
  1915. procedure TMainForm.EndSceneWin;
  1916. begin
  1917.   {  Ende Win  }
  1918. end;
  1919.  
  1920. procedure TMainForm.ResetLevelData;
  1921. begin
  1922.   LevelData.Clear;
  1923.   FRestEnemies := 0;
  1924. end;
  1925.  
  1926. procedure TMainForm.NewLevel(lev: integer);
  1927. resourcestring
  1928.   LNG_LEVEL_INVALID = 'Das Level Nr. %d ist ungültig!'+#13#10+'Das Programm wird beendet.';
  1929. var
  1930.   act: integer;
  1931.   Enemies: array[1..27] of TEnemyType;
  1932.   e: TEnemyAdvent;
  1933. begin
  1934.   ResetLevelData;
  1935.   if FGameMode = gmRandom then
  1936.   begin
  1937.     {$REGION 'Random game'}
  1938.     Enemies[1] := etEnemyAttacker;
  1939.     Enemies[2] := etEnemyMeteor;
  1940.     Enemies[3] := etEnemyUFO;
  1941.     Enemies[4] := etEnemyAttacker;
  1942.     Enemies[5] := etEnemyMeteor;
  1943.     Enemies[6] := etEnemyUFO;
  1944.     Enemies[7] := etEnemyAttacker;
  1945.     Enemies[8] := etEnemyMeteor;
  1946.     Enemies[9] := etEnemyUFO;
  1947.     Enemies[10] := etEnemyAttacker;
  1948.     Enemies[11] := etEnemyMeteor;
  1949.     Enemies[12] := etEnemyUFO;
  1950.     Enemies[13] := etEnemyAttacker;
  1951.     Enemies[14] := etEnemyMeteor;
  1952.     Enemies[15] := etEnemyUFO;
  1953.     Enemies[16] := etEnemyAttacker3;
  1954.     Enemies[17] := etEnemyAttacker;
  1955.     Enemies[18] := etEnemyMeteor;
  1956.     Enemies[19] := etEnemyUFO;
  1957.     Enemies[20] := etEnemyUFO2;
  1958.     Enemies[21] := etEnemyAttacker;
  1959.     Enemies[22] := etEnemyMeteor;
  1960.     Enemies[23] := etEnemyUFO;
  1961.     Enemies[24] := etEnemyAttacker2;
  1962.     Enemies[25] := etEnemyMeteor;
  1963.     Enemies[26] := etEnemyUFO;
  1964.     Enemies[27] := etEnemyAttacker;
  1965.     randomize;
  1966.     FRestEnemies := lev*ADDITIONAL_ENEMIES_PER_LEVEL+1;
  1967.     SetLength(LevelData.EnemyAdventTable, FRestEnemies);
  1968.     for act := 0 to lev*ADDITIONAL_ENEMIES_PER_LEVEL-1 do
  1969.     begin
  1970.       e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))];
  1971.       if e.enemyType = etEnemyAttacker2 then
  1972.       begin
  1973.         e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))]; {O_o}
  1974.       end;
  1975.       e.x := act*30 + random(85-(lev+(random(lev))*2)){O_o};
  1976.       e.y := random(dxdraw.surfaceheight);
  1977.       if e.enemyType = etEnemyAttacker2 then
  1978.       begin
  1979.         e.lifes := random(6)+1{O_o};
  1980.       end
  1981.       else
  1982.       begin
  1983.         e.lifes := random(lev)+1;
  1984.       end;
  1985.  
  1986.       LevelData.EnemyAdventTable[act] := e;
  1987.     end;
  1988.     e.enemyType := etEnemyBoss;
  1989.     e.x := lev*75*30{O_o} div lev;
  1990.     e.y := (dxdraw.surfaceheight div 2) - (MainForm.ImageList.Items.Find('Enemy-boss').height div 2);
  1991.     e.lifes := lev*5;
  1992.     LevelData.EnemyAdventTable[lev*ADDITIONAL_ENEMIES_PER_LEVEL] := e;
  1993.     Assert(FRestEnemies = Length(LevelData.EnemyAdventTable));
  1994.     {$ENDREGION}
  1995.   end
  1996.   else
  1997.   begin
  1998.     {$REGION 'Normal game'}
  1999.     if fileexists(GetLevelFileName(lev)) then
  2000.     begin
  2001.       try
  2002.         LevelData.Load(GetLevelFileName(lev));
  2003.         FRestEnemies := Length(LevelData.EnemyAdventTable);
  2004.       except
  2005.         showmessage(Format(LNG_LEVEL_INVALID, [lev]));
  2006.         ResetLevelData;
  2007.       end;
  2008.     end;
  2009.     {$ENDREGION}
  2010.   end;
  2011. end;
  2012.  
  2013. procedure TMainForm.SceneTitle;
  2014. var
  2015.   Logo: TPictureCollectionItem;
  2016. begin
  2017.   DXDraw.Surface.Fill(0);
  2018.   Logo := ImageList.Items.Find('Logo');
  2019.   {Logo.DrawWaveX(DXDraw.Surface, (dxdraw.surfaceWidth div 2) - 181, 65, Logo.Width, Logo.Height, 0,
  2020.     Trunc(16 - Cos256(FBlink div 60) * 16), 32, -FBlink div 5);}
  2021.   Logo.DrawWaveX(DXDraw.Surface, trunc((dxdraw.surfaceWidth / 2) - (Logo.Width / 2)), 65, Logo.Width, Logo.Height, 0,
  2022.     2, 80, Fangle * 4);
  2023.   inc(Fangle);
  2024.  
  2025.   if (isDown in MainForm.DXInput.States) and (FGameMode=gmLevels) then FGameMode := gmRandom;
  2026.   if ((isUp in MainForm.DXInput.States) and (FGameMode=gmRandom)) or (FGameMode=gmUnknown) then FGameMode := gmLevels;
  2027.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2028.   DXDraw.Surface.Canvas.Font.Size := 30;
  2029.   if FGameMode = gmLevels then
  2030.   begin
  2031.     DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2032.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-52, 'Normales Spiel');
  2033.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, (dxdraw.surfaceheight div 2)-52, '>');
  2034.     DXDraw.Surface.Canvas.Font.Color := clRed;
  2035.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)-50, 'Normales Spiel');
  2036.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)-50, '>');
  2037.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2038.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-2, 'Zufallslevel');
  2039.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2040.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2), 'Zufallslevel');
  2041.   end
  2042.   else
  2043.   begin
  2044.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2045.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-52, 'Normales Spiel');
  2046.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2047.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)-50, 'Normales Spiel');
  2048.     DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2049.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-2, 'Zufallslevel');
  2050.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, (dxdraw.surfaceheight div 2)-2, '>');
  2051.     DXDraw.Surface.Canvas.Font.Color := clRed;
  2052.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2), 'Zufallslevel');
  2053.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2), '>');
  2054.   end;
  2055.   { if (FBlink div 300) mod 2=0 then
  2056.   begin
  2057.     DXDraw.Surface.Canvas.Font.Color := clGreen;
  2058.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2059.     DXDraw.Surface.Canvas.Font.Color := clLime;
  2060.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2061.   end; }
  2062.   BlinkUpdate;
  2063.   DXDraw.Surface.Canvas.Release;
  2064.  
  2065.   // Weiter mit Leertaste oder Enter
  2066.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2067.   begin
  2068.     FLevel := 1;
  2069.     if ((FGameMode=gmLevels) and not fileexists(GetLevelFileName(FLevel))) or ((FGameMode=gmRandom) and (FLevel > 20)) then
  2070.     begin
  2071.       //PlaySound('Frage', False);
  2072.       exit;
  2073.     end;
  2074.     NewLevel(FLevel);
  2075.     PlaySound('SceneMov', False);
  2076.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2077.     Sleep(200);
  2078.     StartScene(gsMain);
  2079.   end;
  2080. end;
  2081.  
  2082. procedure TMainForm.SceneMain;
  2083. var
  2084.   Enemy: TSprite;
  2085.   spriteClass: TEnemyClass;
  2086. begin
  2087.   case FInterval of
  2088.     giMittel: SpriteEngine.Move(conleicht);
  2089.     giLeicht: SpriteEngine.Move(conmittel);
  2090.     giSchwer: SpriteEngine.Move(conschwer);
  2091.     giMaster: SpriteEngine.Move(conmaster);
  2092.   end;
  2093.   SpriteEngine.Dead;
  2094.   while (FEnemyAdventPos >= Low(LevelData.EnemyAdventTable)) and
  2095.     (FEnemyAdventPos <= High(LevelData.EnemyAdventTable)) and
  2096.     ((LevelData.EnemyAdventTable[FEnemyAdventPos].x / 4) <= FFrame) and
  2097.     (FRestEnemies > 0) do
  2098.   begin
  2099.     Dec(FRestEnemies);
  2100.     with LevelData.EnemyAdventTable[FEnemyAdventPos] do
  2101.     begin
  2102.       spriteClass := nil;
  2103.       case enemyType of
  2104.         //etUnknown: ;
  2105.         etEnemyAttacker:  spriteClass := TEnemyAttacker;
  2106.         etEnemyAttacker2: spriteClass := TEnemyAttacker2;
  2107.         etEnemyAttacker3: spriteClass := TEnemyAttacker3;
  2108.         etEnemyMeteor:    spriteClass := TEnemyMeteor;
  2109.         etEnemyUFO:       spriteClass := TEnemyUFO;
  2110.         etEnemyUFO2:      spriteClass := TEnemyUFO2;
  2111.         etEnemyBoss:      spriteClass := TEnemyBoss;
  2112.       end;
  2113.       if spriteClass <> nil then
  2114.       begin
  2115.         Enemy := spriteClass.Create(SpriteEngine.Engine, lifes);
  2116.         Enemy.x := dxdraw.surfacewidth;
  2117.         //Enemy.y := y;
  2118.         if y <> 0 then
  2119.           Enemy.y := dxdraw.surfaceheight / (480{maximale Bandbreite im alten Format} / y)
  2120.         else
  2121.           Enemy.y := 0;
  2122.       end;
  2123.     end;
  2124.     Inc(FEnemyAdventPos);
  2125.   end;
  2126.   Inc(FFrame);
  2127.   DXDraw.Surface.Fill(0);
  2128.   if FNextScene=gsNone then
  2129.   begin
  2130.     SpriteEngine.Draw;
  2131.     if MainForm.flife > 0 then
  2132.     begin
  2133.       DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2134.       DXDraw.Surface.Canvas.Font.Size := 20;
  2135.       DXDraw.Surface.Canvas.Font.Color := clOlive;
  2136.       DXDraw.Surface.Canvas.Textout(9, 9, 'Punkte: ' + FloatToStrF(FScore,ffNumber,14,0));
  2137.       DXDraw.Surface.Canvas.Font.Color := clYellow;
  2138.       DXDraw.Surface.Canvas.Textout(10, 10, 'Punkte: ' + FloatToStrF(FScore,ffNumber,14,0));
  2139.       DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2140.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-141, 9, 'Level: ' + IntToStr(MainForm.flevel));
  2141.       DXDraw.Surface.Canvas.Font.Color := clRed;
  2142.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-140, 10, 'Level: ' + IntToStr(MainForm.flevel));
  2143.       if FLife<0 then mainform.FLife := 0;
  2144.       if FCheat then
  2145.       begin
  2146.         DXDraw.Surface.Canvas.Font.Color := clPurple;
  2147.         DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, 'Leben: ?');
  2148.         DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2149.         DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, 'Leben: ?');
  2150.       end
  2151.       else
  2152.       begin
  2153.         if ((Flife = 1) and ((FBlink div 300) mod 2=0)) or (Flife <> 1) then
  2154.         begin
  2155.           DXDraw.Surface.Canvas.Font.Color := clPurple;
  2156.           DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, 'Leben: ' + IntToStr(MainForm.flife));
  2157.           DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2158.           DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, 'Leben: ' + IntToStr(MainForm.flife));
  2159.         end;
  2160.         if Flife = 1 then BlinkUpdate;
  2161.       end;
  2162.       {if BossExists and (FBossLife>0) then
  2163.       begin
  2164.         DXDraw.Surface.Canvas.Font.Color := clPurple;
  2165.         DXDraw.Surface.Canvas.Textout(449, 439, 'Boss: ' + IntToStr(FBossLife));
  2166.         DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2167.         DXDraw.Surface.Canvas.Textout(450, 440, 'Boss: ' + IntToStr(FBossLife));
  2168.       end
  2169.       else
  2170.         if RestlicheEinheiten>0 then
  2171.         begin
  2172.           DXDraw.Surface.Canvas.Font.Color := clPurple;
  2173.           DXDraw.Surface.Canvas.Textout(449, 439, 'Einheiten: ' + IntToStr(RestlicheEinheiten));
  2174.           DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2175.           DXDraw.Surface.Canvas.Textout(450, 440, 'Einheiten: ' + IntToStr(RestlicheEinheiten));
  2176.         end;}
  2177.       if BossExists and (FBossLife>0) then
  2178.       begin
  2179.         if (FRestEnemies>0) then
  2180.         begin
  2181.           DXDraw.Surface.Canvas.Font.Color := clGreen;
  2182.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-81, 'Boss: ' + IntToStr(FBossLife));
  2183.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Einheiten: ' + IntToStr(FRestEnemies));
  2184.           DXDraw.Surface.Canvas.Font.Color := clLime;
  2185.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-80, 'Boss: ' + IntToStr(FBossLife));
  2186.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Einheiten: ' + IntToStr(FRestEnemies));
  2187.         end;
  2188.         if (FRestEnemies<1) then
  2189.         begin
  2190.           DXDraw.Surface.Canvas.Font.Color := clGreen;
  2191.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Boss: ' + IntToStr(FBossLife));
  2192.           DXDraw.Surface.Canvas.Font.Color := clLime;
  2193.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Boss: ' + IntToStr(FBossLife));
  2194.         end;
  2195.       end;
  2196.       if (FRestEnemies>0) and not Bossexists then
  2197.       begin
  2198.         DXDraw.Surface.Canvas.Font.Color := clGreen;
  2199.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Einheiten: ' + IntToStr(FRestEnemies));
  2200.         DXDraw.Surface.Canvas.Font.Color := clLime;
  2201.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Einheiten: ' + IntToStr(FRestEnemies));
  2202.       end;
  2203.       if (EnemyCounter=0) and (FRestEnemies=0) and ((BossExists and (FBossLife=0)) or not BossExists) then
  2204.       begin
  2205.         DXDraw.Surface.Canvas.Font.Color := clGreen;
  2206.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, 'Mission erfolgreich!');
  2207.         DXDraw.Surface.Canvas.Font.Color := clLime;
  2208.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, 'Mission erfolgreich!');
  2209.         DXDraw.Surface.Canvas.Release;
  2210.         Sleep(1); // TODO: man merkt hier einen lag!
  2211.         inc(FCounter);
  2212.         if FCounter>150{200} then PlayerSprite.FlyAway;
  2213.       end;
  2214.     end
  2215.     else
  2216.     begin
  2217.       DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2218.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, 'Mission gescheitert!');
  2219.       DXDraw.Surface.Canvas.Font.Color := clRed;
  2220.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, 'Mission gescheitert!');
  2221.     end;
  2222.     DXDraw.Surface.Canvas.Release;
  2223.   end;
  2224. end;
  2225.  
  2226. procedure TMainForm.SceneGameOver;
  2227. begin
  2228.   DXDraw.Surface.Fill(0);
  2229.  
  2230.   FNotSave := true;
  2231.   Cheat.enabled := false;
  2232.   GamePause.enabled := false;
  2233.   Neustart.enabled := false;
  2234.   Brush.Style := bsClear;
  2235.   DXDraw.Surface.Canvas.Font.Size := 35;
  2236.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2237.   DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-127, 98, 'Game over!');
  2238.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2239.   DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-125, 100, 'Game over!');
  2240.   if (FBlink div 300) mod 2=0 then
  2241.   begin
  2242.     DXDraw.Surface.Canvas.Font.Size := 30;
  2243.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2244.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2245.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2246.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2247.   end;
  2248.   BlinkUpdate;
  2249.   DXDraw.Surface.Canvas.Release;
  2250.  
  2251.   // Weiter mit Leertaste oder Enter
  2252.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2253.   begin
  2254.     PlaySound('SceneMov', False);
  2255.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2256.     Sleep(200);
  2257.     StartScene(gsTitle);
  2258.   end;
  2259. end;
  2260.  
  2261. procedure TMainForm.SceneWin;
  2262. begin
  2263.   DXDraw.Surface.Fill(0);
  2264.  
  2265.   FNotSave := true;
  2266.   Cheat.enabled := false;
  2267.   GamePause.enabled := false;
  2268.   Neustart.enabled := false;
  2269.  
  2270.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2271.   DXDraw.Surface.Canvas.Font.Size := 35;
  2272.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2273.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-127, 98, 'Gewonnen!');
  2274.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2275.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-125, 100, 'Gewonnen!');
  2276.   if (FBlink div 300) mod 2=0 then
  2277.   begin
  2278.     DXDraw.Surface.Canvas.Font.Size := 30;
  2279.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2280.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2281.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2282.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2283.   end;
  2284.   BlinkUpdate;
  2285.   DXDraw.Surface.Canvas.Release;
  2286.  
  2287.   // Weiter mit Leertaste oder Enter
  2288.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2289.   begin
  2290.     PlaySound('SceneMov', False);
  2291.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2292.     Sleep(200);
  2293.     StartScene(gsTitle);
  2294.   end;
  2295. end;
  2296.  
  2297. procedure TMainForm.StartSceneNewLevel;
  2298. begin
  2299.   sleep(500);
  2300.   FNotSave := false;
  2301.   Cheat.enabled := false;
  2302.   Neustart.enabled := false;
  2303.   GamePause.enabled := false;
  2304.   GameStart.enabled := true;
  2305.   Spielgeschwindigkeit.enabled := false;
  2306.   BossExists := false;
  2307.   Spielgeschwindigkeit.enabled := false;
  2308.   if ((FGameMode=gmLevels) and (not fileexists(GetLevelFileName(FLevel)))) or ((FGameMode=gmRandom) and (FLevel > 25)) then
  2309.   begin
  2310.     //PlaySound('SceneMov', False);
  2311.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2312.     Sleep(200);
  2313.     StartScene(gsWin);
  2314.     exit;
  2315.   end;
  2316.   MusicSwitchTrack(mtScene);
  2317. end;
  2318.  
  2319. procedure TMainForm.EndSceneNewLevel;
  2320. begin
  2321.   {  Ende NewLevel  }
  2322. end;
  2323.  
  2324. procedure TMainForm.SceneNewLevel;
  2325. begin
  2326.   DXDraw.Surface.Fill(0);
  2327.  
  2328.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2329.   DXDraw.Surface.Canvas.Font.Size := 40;
  2330.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2331.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(83+(length(inttostr(flevel))*22)), 98, 'Level '+inttostr(flevel));
  2332.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2333.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(81+(length(inttostr(flevel))*22)), 100, 'Level '+inttostr(flevel));
  2334.   if (FBlink div 300) mod 2=0 then
  2335.   begin
  2336.     DXDraw.Surface.Canvas.Font.Size := 30;
  2337.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2338.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2339.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2340.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2341.   end;
  2342.   BlinkUpdate;
  2343.   DXDraw.Surface.Canvas.Release;
  2344.  
  2345.   // Weiter mit Leertaste oder Enter
  2346.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2347.   begin
  2348.     PlaySound('SceneMov', False);
  2349.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2350.     Sleep(200);
  2351.     StartScene(gsMain);
  2352.   end;
  2353. end;
  2354.  
  2355. procedure TMainForm.OptionMusicClick(Sender: TObject);
  2356. begin
  2357.   OptionMusic.Checked := not OptionMusic.Checked;
  2358.   if OptionMusic.Checked then
  2359.   begin
  2360.     MusicSwitchTrack(FMusic)
  2361.   end
  2362.   else
  2363.   begin
  2364.     StopMusic(FMusic);
  2365.   end;
  2366.   WriteOptions;
  2367. end;
  2368.  
  2369. procedure TMainForm.MasterClick(Sender: TObject);
  2370. begin
  2371.   master.checked := true;
  2372.   FInterval := giMaster;
  2373.   writeoptions;
  2374. end;
  2375.  
  2376. procedure TMainForm.PlayMusic(Name: TMusicTrack);
  2377. begin
  2378.   if not OptionMusic.checked then exit;
  2379.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2380.   dxmusic.Midis.Items[Ord(Name)-1].Play;
  2381. end;
  2382.  
  2383. procedure TMainForm.StopMusic(Name: TMusicTrack);
  2384. begin
  2385.   if Name = mtNone then exit;
  2386.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2387.   dxmusic.Midis.Items[Ord(Name)-1].Stop;
  2388. end;
  2389.  
  2390. procedure TMainForm.ResumeMusic(Name: TMusicTrack);
  2391. begin
  2392.   if not OptionMusic.checked then exit;
  2393.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2394.   dxmusic.Midis.Items[Ord(Name)-1].Play; // TODO: how to pause/resume instead play/stop
  2395. end;
  2396.  
  2397. procedure TMainForm.PauseMusic(Name: TMusicTrack);
  2398. begin
  2399.   if Name = mtNone then exit;
  2400.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2401.   dxmusic.Midis.Items[Ord(Name)-1].Stop; // TODO: how to pause/resume instead play/stop
  2402. end;
  2403.  
  2404. procedure TMainForm.SpielstandClick(Sender: TObject);
  2405. begin
  2406.   speicherungform.showmodal;
  2407. end;
  2408.  
  2409. procedure TMainForm.NeustartClick(Sender: TObject);
  2410. begin
  2411.   FLife := Lives;
  2412.   FLevel := 1; // ???
  2413.   FScore := 0;
  2414.   EnemyCounter := 0;
  2415.   StartScene(gsMain);
  2416.   MusicSwitchTrack(mtGame);
  2417. end;
  2418.  
  2419. procedure TMainForm.LeichtClick(Sender: TObject);
  2420. begin
  2421.   leicht.checked := true;
  2422.   FInterval := giLeicht;
  2423.   writeoptions;
  2424. end;
  2425.  
  2426. procedure TMainForm.MittelClick(Sender: TObject);
  2427. begin
  2428.   mittel.checked := true;
  2429.   FInterval := giMittel;
  2430.   writeoptions;
  2431. end;
  2432.  
  2433. procedure TMainForm.SchwerClick(Sender: TObject);
  2434. begin
  2435.   schwer.checked := true;
  2436.   FInterval := giSchwer;
  2437.   writeoptions;
  2438. end;
  2439.  
  2440. procedure TMainForm.FormShow(Sender: TObject);
  2441. begin
  2442.   if Assigned(SplashForm) then
  2443.   begin
  2444.     SplashForm.Hide;
  2445.     FreeAndNil(SplashForm);
  2446.   end;
  2447.  
  2448.   dxtimer.Enabled := true;
  2449.   dxtimer.ActiveOnly := true;
  2450. end;
  2451.  
  2452. procedure TMainForm.InformationenClick(Sender: TObject);
  2453. begin
  2454.   dxtimer.enabled := false;
  2455.   InfoForm.showmodal;
  2456.   if not mainform.gamepause.checked then mainform.dxtimer.enabled := true;
  2457. end;
  2458.  
  2459. procedure TMainForm.CheatClick(Sender: TObject);
  2460. begin
  2461.   CheatForm.showmodal;
  2462. end;
  2463.  
  2464. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
  2465. begin
  2466.   if optionMusic.checked then StopMusic(FMusic);
  2467.   SpriteEngine.Engine.Clear;
  2468.   dxsound.Finalize;
  2469.   dxinput.Destroy;
  2470.   DXTimer.Enabled := False;
  2471. end;
  2472.  
  2473. procedure TMainForm.FormDestroy(Sender: TObject);
  2474. begin
  2475.   FreeAndNil(imagelist);
  2476.   FreeAndNil(spriteengine);
  2477.   FreeAndNil(dxdraw);
  2478.   FreeAndNil(wavelist);
  2479.   FreeAndNil(dxsound);
  2480.   //FreeAndNil(dxinput);
  2481.   FreeAndNil(dxtimer);
  2482.   FreeAndNil(dxmusic);
  2483.   DeleteCriticalSection(TimerCS);
  2484.   FreeAndNil(LevelData);
  2485. end;
  2486.  
  2487. end.
  2488.  
  2489.