Subversion Repositories spacemission

Rev

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