Subversion Repositories spacemission

Rev

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