Subversion Repositories spacemission

Rev

Rev 88 | Rev 90 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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