Subversion Repositories spacemission

Rev

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