Subversion Repositories spacemission

Rev

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