Subversion Repositories spacemission

Rev

Rev 71 | Rev 74 | 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');
  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..27] of TEnemyType;
  1855.   numEnemies: integer;
  1856.   e: TEnemyAdvent;
  1857.   bossPosition, medikitPosition: 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;          // ...
  1870.     Enemies[7] := etEnemyAttacker;
  1871.     Enemies[8] := etEnemyMeteor;
  1872.     Enemies[9] := etEnemyUFO;
  1873.     Enemies[10] := etEnemyAttacker;
  1874.     Enemies[11] := etEnemyMeteor;
  1875.     Enemies[12] := etEnemyUFO;
  1876.     Enemies[13] := etEnemyAttacker;
  1877.     Enemies[14] := etEnemyMeteor;
  1878.     Enemies[15] := etEnemyUFO;
  1879.     Enemies[16] := etEnemyAttacker3;
  1880.     Enemies[17] := etEnemyAttacker;
  1881.     Enemies[18] := etEnemyMeteor;
  1882.     Enemies[19] := etEnemyUFO;
  1883.     Enemies[20] := etEnemyUFO2;
  1884.     Enemies[21] := etEnemyAttacker;
  1885.     Enemies[22] := etEnemyMeteor;
  1886.     Enemies[23] := etEnemyUFO;
  1887.     Enemies[24] := etEnemyAttacker2;
  1888.     Enemies[25] := etEnemyMeteor;
  1889.     Enemies[26] := etEnemyUFO;
  1890.     Enemies[27] := etEnemyAttacker;
  1891.     numEnemies := lev*ADDITIONAL_ENEMIES_PER_LEVEL;
  1892.     SetLength(LevelData.EnemyAdventTable, numEnemies);
  1893.     for act := 0 to numEnemies-1 do
  1894.     begin
  1895.       e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))];
  1896.       if e.enemyType = etEnemyAttacker2 then
  1897.       begin
  1898.         //e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))];
  1899.         if Random(2) = 0 then e.enemyType := etEnemyAttacker3;
  1900.       end;
  1901.       e.x := 85-(lev+(random(lev))*2){O_o};
  1902.       if e.x < 1 then e.x := 1; // passiert bei groƟen Levels
  1903.       e.x := act*30 + random(e.x);
  1904.       e.y := random(dxdraw.surfaceheight);
  1905.       if e.enemyType = etEnemyAttacker2 then
  1906.       begin
  1907.         e.lifes := random(6)+1{O_o};
  1908.       end
  1909.       else
  1910.       begin
  1911.         if lev > RandomLevelMaxEnemyLives then
  1912.         begin
  1913.           e.lifes := random(RandomLevelMaxEnemyLives)+1;
  1914.         end
  1915.         else
  1916.         begin
  1917.           e.lifes := random(lev)+1;
  1918.         end;
  1919.       end;
  1920.  
  1921.       LevelData.EnemyAdventTable[act] := e;
  1922.     end;
  1923.  
  1924.     if lev < 5 then
  1925.     begin
  1926.       // Level 1-4: No boss
  1927.       bossPosition := -1;
  1928.     end
  1929.     else if lev < 10 then
  1930.     begin
  1931.       // Level 5-9: Boss is at the end of the level
  1932.       bossPosition := numEnemies-1;
  1933.     end
  1934.     else
  1935.     begin
  1936.       // Starting with Level 10: Boss at 75% of the level
  1937.       bossPosition := round(0.75 * numEnemies);
  1938.     end;
  1939.  
  1940.     if bossPosition >= 0 then
  1941.     begin
  1942.       e.enemyType := etEnemyBoss;
  1943.       //e.x := lev*75*30{O_o} div lev;
  1944.       e.x := LevelData.EnemyAdventTable[bossPosition-1].x;
  1945.       e.y := (dxdraw.surfaceheight div 2) - (MainForm.GetSpriteGraphic(smgEnemyBoss).height div 2);
  1946.       e.lifes := lev*5;
  1947.       LevelData.EnemyAdventTable[bossPosition] := e;
  1948.     end;
  1949.  
  1950.     medikitPosition := 0;
  1951.     LevelData.EnemyAdventTable[medikitPosition].enemyType := etItemMedikit;
  1952.     LevelData.EnemyAdventTable[medikitPosition].lifes := 0;
  1953.  
  1954.     {$ENDREGION}
  1955.   end
  1956.   else
  1957.   begin
  1958.     {$REGION 'Normal game'}
  1959.     levFile := GetLevelFileName(lev,false);
  1960.     if levFile.found then
  1961.     begin
  1962.       try
  1963.         LevelData.RasterErzwingen := false;
  1964.         LevelData.LoadFromFile(levFile.fileLocation);
  1965.       except
  1966.         showmessage(Format(LNG_LEVEL_INVALID, [lev]));
  1967.         ResetLevelData;
  1968.       end;
  1969.     end;
  1970.     {$ENDREGION}
  1971.   end;
  1972.   FLevelDataAlreadyLoaded := true; // nicht nochmal NewLevel() aufrufen. Erst wieder wenn man gewonnen hat.
  1973. end;
  1974.  
  1975. var
  1976.   TitleWasPressed: TDxInputState = isButton32;
  1977.  
  1978. procedure TMainForm.SceneTitle;
  1979. var
  1980.   Logo: TPictureCollectionItem;
  1981.   colo1, colo2: TColor;
  1982. begin
  1983.   DXDraw.Surface.Fill(0);
  1984.   Logo := GetSpriteGraphic(smgLogo);
  1985.   {Logo.DrawWaveX(DXDraw.Surface, (dxdraw.surfaceWidth div 2) - 181, 65, Logo.Width, Logo.Height, 0,
  1986.     Trunc(16 - Cos256(FBlink div 60) * 16), 32, -FBlink div 5);}
  1987.   Logo.DrawWaveX(DXDraw.Surface, trunc((dxdraw.surfaceWidth / 2) - (Logo.Width / 2)), 65, Logo.Width, Logo.Height, 0,
  1988.     2, 80, Fangle * 4);
  1989.   inc(Fangle);
  1990.  
  1991.   if FGameMode = gmUnknown then FGameMode := gmLevels;
  1992.  
  1993.   if (isUp in MainForm.DXInput.States) then TitleWasPressed := isUp;
  1994.   if (TitleWasPressed=isUp) and not (isUp in MainForm.DXInput.States) then
  1995.   begin
  1996.     TitleWasPressed := isButton32;
  1997.     if (Ord(FGameMode) <> 1) then
  1998.       FGameMode := TGameMode(Ord(FGameMode)-1);
  1999.   end;
  2000.  
  2001.   if (isDown in MainForm.DXInput.States) then TitleWasPressed := isDown;
  2002.   if (TitleWasPressed=isDown) and not (isDown in MainForm.DXInput.States) then
  2003.   begin
  2004.     TitleWasPressed := isButton32;
  2005.     if (FGameMode <> High(TGameMode)) then
  2006.       FGameMode := TGameMode(Ord(FGameMode)+1);
  2007.   end;
  2008.  
  2009.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2010.   DXDraw.Surface.Canvas.Font.Size := 30;
  2011.  
  2012.   {$REGION 'Menu point: Normal Level'}
  2013.   if FGameMode = gmLevels then
  2014.   begin
  2015.     colo1 := clMaroon;
  2016.     colo2 := clRed;
  2017.   end
  2018.   else
  2019.   begin
  2020.     colo1 := clOlive;
  2021.     colo2 := clYellow;
  2022.   end;
  2023.   DXDraw.Surface.Canvas.Font.Color := colo1;
  2024.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-52, 'Normales Spiel');
  2025.   if FGameMode = gmLevels then
  2026.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)-52, '>');
  2027.   DXDraw.Surface.Canvas.Font.Color := colo2;
  2028.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)-50, 'Normales Spiel');
  2029.   if FGameMode = gmLevels then
  2030.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)-50, '>');
  2031.   {$ENDREGION}
  2032.  
  2033.   {$REGION 'Menu point: Random Level'}
  2034.   if FGameMode = gmRandom then
  2035.   begin
  2036.     colo1 := clMaroon;
  2037.     colo2 := clRed;
  2038.   end
  2039.   else
  2040.   begin
  2041.     colo1 := clOlive;
  2042.     colo2 := clYellow;
  2043.   end;
  2044.   DXDraw.Surface.Canvas.Font.Color := colo1;
  2045.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-2, 'Zufallslevel');
  2046.   if FGameMode = gmRandom then
  2047.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, (dxdraw.surfaceheight div 2)-2, '>');
  2048.   DXDraw.Surface.Canvas.Font.Color := colo2;
  2049.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2), 'Zufallslevel');
  2050.   if FGameMode = gmRandom then
  2051.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2), '>');
  2052.   {$ENDREGION}
  2053.  
  2054.   {$REGION 'Menu point: Level Editor'}
  2055.   if FGameMode = gmEditor then
  2056.   begin
  2057.     colo1 := clMaroon;
  2058.     colo2 := clRed;
  2059.   end
  2060.   else
  2061.   begin
  2062.     colo1 := clOlive;
  2063.     colo2 := clYellow;
  2064.   end;
  2065.   DXDraw.Surface.Canvas.Font.Color := colo1;
  2066.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)+48, 'Level-Editor');
  2067.   if FGameMode = gmEditor then
  2068.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)+48, '>');
  2069.   DXDraw.Surface.Canvas.Font.Color := colo2;
  2070.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)+50, 'Level-Editor');
  2071.   if FGameMode = gmEditor then
  2072.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)+50, '>');
  2073.   {$ENDREGION}
  2074.  
  2075.   { if (FBlink div 300) mod 2=0 then
  2076.   begin
  2077.     DXDraw.Surface.Canvas.Font.Color := clGreen;
  2078.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2079.     DXDraw.Surface.Canvas.Font.Color := clLime;
  2080.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2081.   end; }
  2082.   BlinkUpdate;
  2083.   DXDraw.Surface.Canvas.Release;
  2084.  
  2085.   // Weiter mit Leertaste oder Enter
  2086.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2087.   begin
  2088.     FLevel := 1;
  2089.     if FGameMode = gmEditor then
  2090.     begin
  2091.       ShellExecute(0, 'open', PChar(OwnDirectory+'LevEdit.exe'), '', PChar(OwnDirectory), SW_NORMAL);
  2092.       Close;
  2093.       exit;
  2094.     end;
  2095.     if ((FGameMode=gmLevels) and not GetLevelFileName(FLevel,false).found) or
  2096.        ((FGameMode=gmRandom) and (FLevel > MaxPossibleLevels)) then
  2097.     begin
  2098.       //PlaySound('Frage', False);
  2099.       exit;
  2100.     end;
  2101.     PlaySound(smsSceneMov, False);
  2102.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2103.     Sleep(200);
  2104.     StartScene(gsMain);
  2105.   end;
  2106. end;
  2107.  
  2108. procedure TMainForm.SceneMain;
  2109. var
  2110.   Enemy: TSprite;
  2111.   spriteClass: TClass;
  2112.   tmpEnemyAnzeige: integer;
  2113. begin
  2114.   case FInterval of
  2115.     giLeicht: SpriteEngine.Move(conleicht);
  2116.     giMittel: SpriteEngine.Move(conmittel);
  2117.     giSchwer: SpriteEngine.Move(conschwer);
  2118.     giMaster: SpriteEngine.Move(conmaster);
  2119.   end;
  2120.   SpriteEngine.Dead;
  2121.   while (FEnemyAdventPos >= Low(LevelData.EnemyAdventTable)) and
  2122.     (FEnemyAdventPos <= High(LevelData.EnemyAdventTable)) and
  2123.     ((LevelData.EnemyAdventTable[FEnemyAdventPos].x / 4) <= FFrame) and
  2124.     (FRestEnemies > 0) do
  2125.   begin
  2126.     Dec(FRestEnemies);
  2127.     with LevelData.EnemyAdventTable[FEnemyAdventPos] do
  2128.     begin
  2129.       spriteClass := nil;
  2130.       case enemyType of
  2131.         //etUnknown: ;
  2132.         etEnemyAttacker:  spriteClass := TEnemyAttacker;
  2133.         etEnemyAttacker2: spriteClass := TEnemyAttacker2;
  2134.         etEnemyAttacker3: spriteClass := TEnemyAttacker3;
  2135.         etEnemyMeteor:    spriteClass := TEnemyMeteor;
  2136.         etEnemyUFO:       spriteClass := TEnemyUFO;
  2137.         etEnemyUFO2:      spriteClass := TEnemyUFO2;
  2138.         etEnemyBoss:      spriteClass := TEnemyBoss;
  2139.         etItemMedikit:    spriteClass := TItemMedikit;
  2140.       end;
  2141.       if spriteClass <> nil then
  2142.       begin
  2143.         Enemy := nil;
  2144.         if spriteClass.InheritsFrom(TEnemy) then
  2145.           Enemy := TEnemyClass(spriteClass).Create(SpriteEngine.Engine, lifes)
  2146.         else if spriteClass.InheritsFrom(TItem) then
  2147.           Enemy := TItemClass(spriteClass).Create(SpriteEngine.Engine)
  2148.         else
  2149.           Assert(False);
  2150.         Enemy.x := dxdraw.surfacewidth;
  2151.         //Enemy.y := y;
  2152.         if y <> 0 then
  2153.           Enemy.y := dxdraw.surfaceheight / (480{maximale Bandbreite im alten Format} / y)
  2154.         else
  2155.           Enemy.y := 0;
  2156.       end;
  2157.     end;
  2158.     Inc(FEnemyAdventPos);
  2159.   end;
  2160.   Inc(FFrame);
  2161.   DXDraw.Surface.Fill(0);
  2162.   if FNextScene=gsNone then
  2163.   begin
  2164.     SpriteEngine.Draw;
  2165.     DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2166.     DXDraw.Surface.Canvas.Font.Size := 20;
  2167.     if flife > 0 then
  2168.     begin
  2169.       {$REGION 'Anzeige Punkte'}
  2170.       DXDraw.Surface.Canvas.Font.Color := clOlive;
  2171.       DXDraw.Surface.Canvas.Textout(9, 9, 'Punkte: ' + FloatToStrF(FScore,ffNumber,14,0));
  2172.       DXDraw.Surface.Canvas.Font.Color := clYellow;
  2173.       DXDraw.Surface.Canvas.Textout(10, 10, 'Punkte: ' + FloatToStrF(FScore,ffNumber,14,0));
  2174.       {$ENDREGION}
  2175.  
  2176.       {$REGION 'Anzeige Level'}
  2177.       DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2178.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-141, 9, 'Level: ' + IntToStr(flevel));
  2179.       DXDraw.Surface.Canvas.Font.Color := clRed;
  2180.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-140, 10, 'Level: ' + IntToStr(flevel));
  2181.       {$ENDREGION}
  2182.  
  2183.       {$REGION 'Lebensanzeige'}
  2184.       if FLife<0 then FLife := 0;
  2185.       if FCheat then
  2186.       begin
  2187.         DXDraw.Surface.Canvas.Font.Color := clPurple;
  2188.         DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, 'Leben: ?');
  2189.         DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2190.         DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, 'Leben: ?');
  2191.       end
  2192.       else
  2193.       begin
  2194.         if ((Flife = 1) and ((FBlink div 300) mod 2=0)) or (Flife <> 1) then
  2195.         begin
  2196.           DXDraw.Surface.Canvas.Font.Color := clPurple;
  2197.           DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, 'Leben: ' + IntToStr(flife));
  2198.           DXDraw.Surface.Canvas.Font.Color := clFuchsia;
  2199.           DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, 'Leben: ' + IntToStr(flife));
  2200.         end;
  2201.         if Flife = 1 then BlinkUpdate;
  2202.       end;
  2203.       {$ENDREGION}
  2204.  
  2205.       {$REGION 'Anzeige Einheiten und Boss Leben'}
  2206.  
  2207.       tmpEnemyAnzeige := EnemyCounter{Auf Bildschirm} + FRestEnemies{In der Warteschlange};
  2208.       if FBossImLevel and (FBossLife<>0) then Dec(tmpEnemyAnzeige);
  2209.  
  2210.       if FBossLife > 0 then
  2211.       begin
  2212.         if (tmpEnemyAnzeige>0) then
  2213.         begin
  2214.           DXDraw.Surface.Canvas.Font.Color := clGreen;
  2215.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-81, 'Boss: ' + IntToStr(FBossLife));
  2216.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Einheiten: ' + IntToStr(tmpEnemyAnzeige));
  2217.           DXDraw.Surface.Canvas.Font.Color := clLime;
  2218.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-80, 'Boss: ' + IntToStr(FBossLife));
  2219.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Einheiten: ' + IntToStr(tmpEnemyAnzeige));
  2220.         end
  2221.         else
  2222.         begin
  2223.           DXDraw.Surface.Canvas.Font.Color := clGreen;
  2224.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Boss: ' + IntToStr(FBossLife));
  2225.           DXDraw.Surface.Canvas.Font.Color := clLime;
  2226.           DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Boss: ' + IntToStr(FBossLife));
  2227.         end;
  2228.       end
  2229.       else if (FBossLife<=0) and (tmpEnemyAnzeige>0) then
  2230.       begin
  2231.         DXDraw.Surface.Canvas.Font.Color := clGreen;
  2232.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, 'Einheiten: ' + IntToStr(tmpEnemyAnzeige));
  2233.         DXDraw.Surface.Canvas.Font.Color := clLime;
  2234.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, 'Einheiten: ' + IntToStr(tmpEnemyAnzeige));
  2235.       end;
  2236.       {$ENDREGION}
  2237.  
  2238.       {$REGION 'Anzeige Mission erfolgreich/gescheitert'}
  2239.       if (EnemyCounter=0) and (FRestEnemies=0) and ((FBossImLevel and (FBossLife=0)) or not FBossImLevel) then
  2240.       begin
  2241.         DXDraw.Surface.Canvas.Font.Color := clGreen;
  2242.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, 'Mission erfolgreich!');
  2243.         DXDraw.Surface.Canvas.Font.Color := clLime;
  2244.         DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, 'Mission erfolgreich!');
  2245.         DXDraw.Surface.Canvas.Release;
  2246.         Sleep(1);
  2247.         inc(FCounter);
  2248.         if FCounter>150{200} then PlayerSprite.FlyAway;
  2249.       end;
  2250.       {$ENDREGION}
  2251.     end
  2252.     else
  2253.     begin
  2254.       DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2255.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, 'Mission gescheitert!');
  2256.       DXDraw.Surface.Canvas.Font.Color := clRed;
  2257.       DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, 'Mission gescheitert!');
  2258.     end;
  2259.     DXDraw.Surface.Canvas.Release;
  2260.   end;
  2261. end;
  2262.  
  2263. procedure TMainForm.SceneGameOver;
  2264. begin
  2265.   DXDraw.Surface.Fill(0);
  2266.  
  2267.   FNotSave := true;
  2268.   Cheat.enabled := false;
  2269.   GamePause.enabled := false;
  2270.   Neustart.enabled := false;
  2271.   Brush.Style := bsClear;
  2272.   DXDraw.Surface.Canvas.Font.Size := 35;
  2273.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2274.   DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-127, 98, 'Game over!');
  2275.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2276.   DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-125, 100, 'Game over!');
  2277.   if (FBlink div 300) mod 2=0 then
  2278.   begin
  2279.     DXDraw.Surface.Canvas.Font.Size := 30;
  2280.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2281.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2282.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2283.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2284.   end;
  2285.   BlinkUpdate;
  2286.   DXDraw.Surface.Canvas.Release;
  2287.  
  2288.   // Weiter mit Leertaste oder Enter
  2289.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2290.   begin
  2291.     PlaySound(smsSceneMov, False);
  2292.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2293.     Sleep(200);
  2294.     StartScene(gsTitle);
  2295.   end;
  2296. end;
  2297.  
  2298. procedure TMainForm.SceneWin;
  2299. begin
  2300.   DXDraw.Surface.Fill(0);
  2301.  
  2302.   FNotSave := true;
  2303.   Cheat.enabled := false;
  2304.   GamePause.enabled := false;
  2305.   Neustart.enabled := false;
  2306.  
  2307.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2308.   DXDraw.Surface.Canvas.Font.Size := 35;
  2309.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2310.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-127, 98, 'Gewonnen!');
  2311.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2312.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-125, 100, 'Gewonnen!');
  2313.   if (FBlink div 300) mod 2=0 then
  2314.   begin
  2315.     DXDraw.Surface.Canvas.Font.Size := 30;
  2316.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2317.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2318.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2319.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2320.   end;
  2321.   BlinkUpdate;
  2322.   DXDraw.Surface.Canvas.Release;
  2323.  
  2324.   // Weiter mit Leertaste oder Enter
  2325.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2326.   begin
  2327.     PlaySound(smsSceneMov, False);
  2328.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2329.     Sleep(200);
  2330.     StartScene(gsTitle);
  2331.   end;
  2332. end;
  2333.  
  2334. procedure TMainForm.StartSceneNewLevel;
  2335. begin
  2336.   sleep(500);
  2337.   FNotSave := true; // Wenn man speichert, wĆ¼rde man LevelAdventTable vom vorherigen Level machen, das wƤr mĆ¼ll!
  2338.   Cheat.enabled := false;
  2339.   Neustart.enabled := false;
  2340.   GamePause.enabled := false;
  2341.   GameStart.enabled := true;
  2342.   Spielgeschwindigkeit.enabled := false;
  2343.   Spielgeschwindigkeit.enabled := false;
  2344.   if ((FGameMode=gmLevels) and not GetLevelFileName(FLevel,false).found)
  2345.      // or ((FGameMode=gmRandom) and (FLevel > 25))
  2346.      or (FLevel > MaxPossibleLevels) then
  2347.   begin
  2348.     //PlaySound('SceneMov', False);
  2349.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2350.     Sleep(200);
  2351.     StartScene(gsWin);
  2352.     exit;
  2353.   end;
  2354.   MusicSwitchTrack(smmScene);
  2355. end;
  2356.  
  2357. procedure TMainForm.EndSceneNewLevel;
  2358. begin
  2359.   {  Ende NewLevel  }
  2360. end;
  2361.  
  2362. procedure TMainForm.SceneNewLevel;
  2363. begin
  2364.   DXDraw.Surface.Fill(0);
  2365.  
  2366.   DXDraw.Surface.Canvas.Brush.Style := bsClear;
  2367.   DXDraw.Surface.Canvas.Font.Size := 40;
  2368.   DXDraw.Surface.Canvas.Font.Color := clMaroon;
  2369.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(83+(length(inttostr(flevel))*22)), 98, 'Level '+inttostr(flevel));
  2370.   DXDraw.Surface.Canvas.Font.Color := clRed;
  2371.   DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(81+(length(inttostr(flevel))*22)), 100, 'Level '+inttostr(flevel));
  2372.   if (FBlink div 300) mod 2=0 then
  2373.   begin
  2374.     DXDraw.Surface.Canvas.Font.Size := 30;
  2375.     DXDraw.Surface.Canvas.Font.Color := clOlive;
  2376.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, 'Weiter mit Leertaste');
  2377.     DXDraw.Surface.Canvas.Font.Color := clYellow;
  2378.     DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, 'Weiter mit Leertaste');
  2379.   end;
  2380.   BlinkUpdate;
  2381.   DXDraw.Surface.Canvas.Release;
  2382.  
  2383.   // Weiter mit Leertaste oder Enter
  2384.   if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
  2385.   begin
  2386.     PlaySound(smsSceneMov, False);
  2387.     PalleteAnim(RGBQuad(0, 0, 0), 300);
  2388.     Sleep(200);
  2389.     StartScene(gsMain);
  2390.   end;
  2391. end;
  2392.  
  2393. procedure TMainForm.OptionMusicClick(Sender: TObject);
  2394. begin
  2395.   OptionMusic.Checked := not OptionMusic.Checked;
  2396.   if OptionMusic.Checked then
  2397.   begin
  2398.     MusicSwitchTrack(FMusic)
  2399.   end
  2400.   else
  2401.   begin
  2402.     StopMusic(FMusic);
  2403.   end;
  2404.   WriteOptions;
  2405. end;
  2406.  
  2407. procedure TMainForm.MasterClick(Sender: TObject);
  2408. begin
  2409.   master.checked := true;
  2410.   FInterval := giMaster;
  2411.   writeoptions;
  2412. end;
  2413.  
  2414. procedure TMainForm.PlayMusic(Name: TSpaceMissionMusicTrack);
  2415. begin
  2416.   if not OptionMusic.checked then exit;
  2417.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2418.   dxmusic.Midis.Items[Ord(Name)-1].Play;
  2419. end;
  2420.  
  2421. procedure TMainForm.StopMusic(Name: TSpaceMissionMusicTrack);
  2422. begin
  2423.   if Name = smmNone then exit;
  2424.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2425.   dxmusic.Midis.Items[Ord(Name)-1].Stop;
  2426. end;
  2427.  
  2428. procedure TMainForm.ResumeMusic(Name: TSpaceMissionMusicTrack);
  2429. begin
  2430.   if not OptionMusic.checked then exit;
  2431.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2432.   dxmusic.Midis.Items[Ord(Name)-1].Play; // TODO: how to pause/resume instead play/stop
  2433. end;
  2434.  
  2435. procedure TMainForm.PauseMusic(Name: TSpaceMissionMusicTrack);
  2436. begin
  2437.   if Name = smmNone then exit;
  2438.   if Ord(Name) > dxmusic.Midis.Count then exit;
  2439.   dxmusic.Midis.Items[Ord(Name)-1].Stop; // TODO: how to pause/resume instead play/stop
  2440. end;
  2441.  
  2442. procedure TMainForm.SpielstandClick(Sender: TObject);
  2443. begin
  2444.   speicherungform.showmodal;
  2445. end;
  2446.  
  2447. procedure TMainForm.LevelNeuStarten;
  2448. begin
  2449.   FNextScene := gsNewLevel;
  2450.   FLife := FLifeAtLevelStart;
  2451.   FScore := FScoreAtLevelStart;
  2452. end;
  2453.  
  2454. procedure TMainForm.NeustartClick(Sender: TObject);
  2455. begin
  2456.   LevelNeuStarten;
  2457. end;
  2458.  
  2459. procedure TMainForm.LeichtClick(Sender: TObject);
  2460. begin
  2461.   leicht.checked := true;
  2462.   FInterval := giLeicht;
  2463.   writeoptions;
  2464. end;
  2465.  
  2466. procedure TMainForm.MittelClick(Sender: TObject);
  2467. begin
  2468.   mittel.checked := true;
  2469.   FInterval := giMittel;
  2470.   writeoptions;
  2471. end;
  2472.  
  2473. procedure TMainForm.SchwerClick(Sender: TObject);
  2474. begin
  2475.   schwer.checked := true;
  2476.   FInterval := giSchwer;
  2477.   writeoptions;
  2478. end;
  2479.  
  2480. procedure TMainForm.FormShow(Sender: TObject);
  2481. resourcestring
  2482.   SFileError = 'Die Datei kann von SpaceMission nicht geƶffnet werden!';
  2483. var
  2484.   SavGame: TSaveData;
  2485. begin
  2486.   if Assigned(SplashForm) then
  2487.   begin
  2488.     SplashForm.Hide;
  2489.     FreeAndNil(SplashForm);
  2490.   end;
  2491.  
  2492.   dxtimer.Enabled := true;
  2493.   dxtimer.ActiveOnly := true;
  2494.  
  2495.   ResetLevelData;
  2496.   if (paramcount > 0) and (fileexists(paramstr(1))) and (ExtractFileExt(paramstr(1)).ToLower = '.sav') then
  2497.   begin
  2498.     SavGame := TSaveData.Create;
  2499.     try
  2500.       try
  2501.         SavGame.LoadFromFile(paramstr(1));
  2502.         FScore := SavGame.Score;
  2503.         FLife := SavGame.Life;
  2504.         FLevel := SavGame.Level;
  2505.         FGameMode := SavGame.GameMode;
  2506.         FLevelDataAlreadyLoaded := true; // do not call NewLevel() in StartSceneMain
  2507.         if Assigned(SavGame.LevelData) then
  2508.         begin
  2509.           LevelData.Assign(SavGame.LevelData);
  2510.         end;
  2511.       except
  2512.         on E: Exception do
  2513.         begin
  2514.           showmessage(SFileError + ' ' +E.Message);
  2515.           GameStartClick(GameStart);
  2516.           exit;
  2517.         end;
  2518.       end;
  2519.     finally
  2520.       FreeAndNil(SavGame);
  2521.     end;
  2522.     //FNextScene := gsNewLevel;
  2523.     StartScene(gsNewLevel);
  2524.     exit;
  2525.   end;
  2526. end;
  2527.  
  2528. procedure TMainForm.InformationenClick(Sender: TObject);
  2529. begin
  2530.   dxtimer.enabled := false;
  2531.   InfoForm.showmodal;
  2532.   if not mainform.gamepause.checked then mainform.dxtimer.enabled := true;
  2533. end;
  2534.  
  2535. procedure TMainForm.CheatClick(Sender: TObject);
  2536. begin
  2537.   CheatForm.showmodal;
  2538. end;
  2539.  
  2540. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
  2541. begin
  2542.   if optionMusic.checked then StopMusic(FMusic);
  2543.   SpriteEngine.Engine.Clear;
  2544.   dxsound.Finalize;
  2545.   dxinput.Destroy;
  2546.   DXTimer.Enabled := False;
  2547. end;
  2548.  
  2549. procedure TMainForm.FormDestroy(Sender: TObject);
  2550. begin
  2551.   FreeAndNil(imagelist);
  2552.   FreeAndNil(spriteengine);
  2553.   FreeAndNil(dxdraw);
  2554.   FreeAndNil(wavelist);
  2555.   FreeAndNil(dxmusic);
  2556.   FreeAndNil(dxsound);
  2557.   //FreeAndNil(dxinput);
  2558.   FreeAndNil(dxtimer);
  2559.   DeleteCriticalSection(TimerCS);
  2560.   FreeAndNil(LevelData);
  2561. end;
  2562.  
  2563. procedure PostKeyEx32(key: Word; const shift: TShiftState; specialkey: Boolean);
  2564. {************************************************************
  2565. * Procedure PostKeyEx32
  2566. *
  2567. * Parameters:
  2568. *  key    : virtual keycode of the key to send. For printable
  2569. *           keys this is simply the ANSI code (Ord(character)).
  2570. *  shift  : state of the modifier keys. This is a set, so you
  2571. *           can set several of these keys (shift, control, alt,
  2572. *           mouse buttons) in tandem. The TShiftState type is
  2573. *           declared in the Classes Unit.
  2574. *  specialkey: normally this should be False. Set it to True to
  2575. *           specify a key on the numeric keypad, for example.
  2576. * Description:
  2577. *  Uses keybd_event to manufacture a series of key events matching
  2578. *  the passed parameters. The events go to the control with focus.
  2579. *  Note that for characters key is always the upper-case version of
  2580. *  the character. Sending without any modifier keys will result in
  2581. *  a lower-case character, sending it with [ssShift] will result
  2582. *  in an upper-case character!
  2583. // Code by P. Below
  2584. ************************************************************}
  2585. type
  2586.   TShiftKeyInfo = record
  2587.     shift: Byte;
  2588.     vkey: Byte;
  2589.   end;
  2590.   byteset = set of 0..7;
  2591. const
  2592.   shiftkeys: array [1..3] of TShiftKeyInfo =
  2593.     ((shift: Ord(ssCtrl); vkey: VK_CONTROL),
  2594.     (shift: Ord(ssShift); vkey: VK_SHIFT),
  2595.     (shift: Ord(ssAlt); vkey: VK_MENU));
  2596. var
  2597.   flag: DWORD;
  2598.   bShift: ByteSet absolute shift;
  2599.   i: Integer;
  2600. begin
  2601.   for i := 1 to 3 do
  2602.   begin
  2603.     if shiftkeys[i].shift in bShift then
  2604.       keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0), 0, 0);
  2605.   end; { For }
  2606.   if specialkey then
  2607.     flag := KEYEVENTF_EXTENDEDKEY
  2608.   else
  2609.     flag := 0;
  2610.  
  2611.   keybd_event(key, MapvirtualKey(key, 0), flag, 0);
  2612.   flag := flag or KEYEVENTF_KEYUP;
  2613.   keybd_event(key, MapvirtualKey(key, 0), flag, 0);
  2614.  
  2615.   for i := 3 downto 1 do
  2616.   begin
  2617.     if shiftkeys[i].shift in bShift then
  2618.       keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0),
  2619.         KEYEVENTF_KEYUP, 0);
  2620.   end; { For }
  2621. end; { PostKeyEx32 }
  2622.  
  2623. procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
  2624.   Shift: TShiftState);
  2625. begin
  2626.   if Key = VK_ESCAPE then
  2627.   begin
  2628.     // TODO: Unfortunately, you cannot see if it is already popup. It would be great if ESC closes the main menu...
  2629.     Key := 0;
  2630.     PostKeyEx32(Ord('S'), [ssAlt], False);
  2631.   end;
  2632. end;
  2633.  
  2634. end.
  2635.  
  2636.