Subversion Repositories spacemission

Rev

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

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