Subversion Repositories spacemission

Rev

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