Subversion Repositories spacemission

Rev

Rev 90 | 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;
90 daniel-mar 195
    destructor Destroy; override;
3 daniel-mar 196
  end;
197
 
72 daniel-mar 198
  TItemClass = class of TItem;
199
  TItem = class abstract (TPlayerOrEnemyOrItem)
200
  strict protected
201
    procedure DoMove(MoveCount: Integer); override;
202
  public
203
    procedure Collected; virtual;
204
  end;
205
 
206
  TItemMedikit = class(TItem)
207
  public
208
    procedure Collected; override;
209
    constructor Create(AParent: TSprite); override;
210
  end;
211
 
3 daniel-mar 212
  TMainForm = class(TDXForm)
213
    MainMenu: TMainMenu;
214
    Spiel: TMenuItem;
215
    GameStart: TMenuItem;
216
    GamePause: TMenuItem;
217
    Beenden: TMenuItem;
218
    Einstellungen: TMenuItem;
219
    OptionMusic: TMenuItem;
220
    Hilfe: TMenuItem;
221
    OptionSound: TMenuItem;
222
    Leer3: TMenuItem;
223
    Spielstand: TMenuItem;
224
    Leer5: TMenuItem;
225
    Neustart: TMenuItem;
226
    Spielgeschwindigkeit: TMenuItem;
227
    Leicht: TMenuItem;
228
    Mittel: TMenuItem;
229
    Schwer: TMenuItem;
230
    Informationen: TMenuItem;
231
    Leer6: TMenuItem;
232
    Leer1: TMenuItem;
233
    Cheat: TMenuItem;
234
    CheckUpdates: TMenuItem;
235
    Master: TMenuItem;
63 daniel-mar 236
    Hilfe1: TMenuItem;
64 daniel-mar 237
    N1: TMenuItem;
238
    Wasgibtesneues1: TMenuItem;
3 daniel-mar 239
    procedure DXDrawFinalize(Sender: TObject);
240
    procedure DXDrawInitialize(Sender: TObject);
241
    procedure FormCreate(Sender: TObject);
242
    procedure DXTimerTimer(Sender: TObject; LagCount: Integer);
243
    procedure DXTimerActivate(Sender: TObject);
244
    procedure DXTimerDeactivate(Sender: TObject);
245
    procedure DXDrawInitializing(Sender: TObject);
246
    procedure GameStartClick(Sender: TObject);
247
    procedure GamePauseClick(Sender: TObject);
248
    procedure BeendenClick(Sender: TObject);
249
    procedure OptionSoundClick(Sender: TObject);
250
    procedure OptionMusicClick(Sender: TObject);
251
    procedure SpielstandClick(Sender: TObject);
252
    procedure NeustartClick(Sender: TObject);
253
    procedure LeichtClick(Sender: TObject);
254
    procedure MittelClick(Sender: TObject);
255
    procedure SchwerClick(Sender: TObject);
80 daniel-mar 256
    procedure MasterClick(Sender: TObject);
3 daniel-mar 257
    procedure FormShow(Sender: TObject);
258
    procedure InformationenClick(Sender: TObject);
259
    procedure CheatClick(Sender: TObject);
260
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
261
    procedure FormDestroy(Sender: TObject);
262
    procedure CheckUpdatesClick(Sender: TObject);
36 daniel-mar 263
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
64 daniel-mar 264
    procedure HilfeTopicClick(Sender: TObject);
3 daniel-mar 265
  private
266
    ProgrammGestartet: boolean;
80 daniel-mar 267
    FSpeed: integer;
3 daniel-mar 268
    FScene: TGameScene;
31 daniel-mar 269
    FMusic: TSpaceMissionMusicTrack;
3 daniel-mar 270
    FBlink: DWORD;
271
    FBlinkTime: DWORD;
272
    FFrame, FAngle, FCounter, FEnemyAdventPos: Integer;
273
    PlayerSprite: TPlayerSprite;
7 daniel-mar 274
    TimerCS: TRTLCriticalSection;
3 daniel-mar 275
    procedure StartScene(Scene: TGameScene);
276
    procedure EndScene;
277
    procedure BlinkStart;
278
    procedure BlinkUpdate;
279
    procedure StartSceneTitle;
280
    procedure SceneTitle;
281
    procedure EndSceneTitle;
282
    procedure StartSceneMain;
283
    procedure SceneMain;
284
    procedure EndSceneMain;
285
    procedure StartSceneGameOver;
286
    procedure SceneGameOver;
287
    procedure EndSceneGameOver;
288
    procedure StartSceneWin;
289
    procedure SceneWin;
290
    procedure EndSceneWin;
291
    procedure StartSceneNewLevel;
292
    procedure SceneNewLevel;
293
    procedure EndSceneNewLevel;
38 daniel-mar 294
    procedure LevelNeuStarten;
47 daniel-mar 295
  private
296
    { Diverse temporäre Variablen }
297
    Crash2: integer;
298
    EnemyCounter: integer;
299
    Crash: boolean;
300
    crashsound: boolean;
3 daniel-mar 301
  public
302
    FNextScene: TGameScene;
303
    FScore: Integer;
90 daniel-mar 304
    FBoss: TEnemyBoss;
3 daniel-mar 305
    FNotSave: boolean;
306
    FLife: integer;
307
    FLevel: integer;
15 daniel-mar 308
    FGameMode: TGameMode;
51 daniel-mar 309
    FLifeAtLevelStart: integer;
310
    FScoreAtLevelStart: integer;
311
    FLevelDataAlreadyLoaded: boolean;
7 daniel-mar 312
    FRestEnemies: integer;
89 daniel-mar 313
    FCheats: TCheatSet;
3 daniel-mar 314
    { VCL-Ersatz }
315
    dxdraw: TDxDraw;
316
    imagelist: TDxImageList;
317
    spriteengine: tdxspriteengine;
318
    dxsound: tdxsound;
18 daniel-mar 319
    dxmusic: tdxmusic;
3 daniel-mar 320
    wavelist: tdxwavelist;
321
    dxinput: tdxinput;
322
    dxtimer: tdxtimer;
323
    { Level-Routinen }
40 daniel-mar 324
    LevelData: TLevelData;
3 daniel-mar 325
    procedure NewLevel(lev: integer);
14 daniel-mar 326
    procedure ResetLevelData;
19 daniel-mar 327
    { Musik-Routinen }
31 daniel-mar 328
    procedure MusicSwitchTrack(Name: TSpaceMissionMusicTrack);
329
    procedure PlayMusic(Name: TSpaceMissionMusicTrack);
330
    procedure StopMusic(Name: TSpaceMissionMusicTrack);
331
    procedure ResumeMusic(Name: TSpaceMissionMusicTrack);
332
    procedure PauseMusic(Name: TSpaceMissionMusicTrack);
3 daniel-mar 333
    { Sound-Routinen }
31 daniel-mar 334
    procedure PlaySound(Sound: TSpaceMissionSound; Wait: Boolean);
335
    { Grafik-Routinen }
336
    function GetSpriteGraphic(Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
3 daniel-mar 337
    { Initialisiations-Routinen }
338
    procedure DXInit;
339
    procedure SoundInit;
340
    procedure MusicInit;
341
    { Einstellungs-Routinen }
342
    procedure LoadOptions;
343
    procedure WriteOptions;
344
    { Farb-Routinen }
345
    function ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
346
    procedure PalleteAnim(Col: TRGBQuad; Time: Integer);
347
  end;
348
 
349
var
350
  MainForm: TMainForm;
351
 
7 daniel-mar 352
implementation
353
 
354
uses
63 daniel-mar 355
  GamSplash, GamSpeicherung, ComInfo, GamCheat, MMSystem, Registry,
356
  ComHilfe;
7 daniel-mar 357
 
3 daniel-mar 358
{$R *.DFM}
359
 
360
const
361
  DXInputButton = [isButton1, isButton2, isButton3,
362
    isButton4, isButton5, isButton6, isButton7, isButton8, isButton9, isButton10, isButton11,
363
    isButton12, isButton13, isButton14, isButton15, isButton16, isButton17, isButton18,
364
    isButton19, isButton20, isButton21, isButton22, isButton23, isButton24, isButton25,
365
    isButton26, isButton27, isButton28, isButton29, isButton30, isButton31, isButton32];
366
 
83 daniel-mar 367
resourcestring
368
  SWeiterMitLeertaste = 'Weiter mit Leertaste';
369
 
24 daniel-mar 370
{ TBackground }
371
 
372
procedure TBackground.DoMove(MoveCount: Integer);
373
var
374
  ran: integer;
35 daniel-mar 375
  bgs: TBackgroundSpecial;
24 daniel-mar 376
begin
377
  inherited DoMove(MoveCount);
378
  X := X - MoveCount*(60/1000)*FSpeed;
379
  ran := Random(1500);
380
  if ran = 150 then
381
  begin
35 daniel-mar 382
    bgs := TBackgroundSpecial.Create(mainform.SpriteEngine.Engine);
383
    bgs.SetMapSize(1, 1);
384
    bgs.Image := MainForm.GetSpriteGraphic(smgBackgroundPlanet1);
385
    bgs.Width := Image.Width;
386
    bgs.Height := Image.Height;
387
    bgs.Y := random(mainform.dxdraw.height);
388
    bgs.X := mainform.dxdraw.width;
389
    ran := Random(2);
390
    if ran = 0 then
24 daniel-mar 391
    begin
35 daniel-mar 392
      bgs.Z := -20;
393
      bgs.Speed := 1.8;
394
    end
395
    else if ran = 1 then
396
    begin
397
      bgs.Z := -40;
398
      bgs.Speed := 0.8;
399
    end
400
    else if ran = 2 then
401
    begin
402
      bgs.Z := -60;
403
      bgs.Speed := 0.3;
24 daniel-mar 404
    end;
405
  end
406
  else if ran = 500 then
407
  begin
35 daniel-mar 408
    bgs := TBackgroundSpecial.Create(mainform.SpriteEngine.Engine);
409
    bgs.SetMapSize(1, 1);
410
    ran := Random(4);
411
    if ran = 0 then
412
      bgs.Image := MainForm.GetSpriteGraphic(smgBackgroundRed)
413
    else if ran = 1 then
414
      bgs.Image := MainForm.GetSpriteGraphic(smgBackgroundBlue)
415
    else if ran = 2 then
416
      bgs.Image := MainForm.GetSpriteGraphic(smgBackgroundYellow)
417
    else if ran = 3 then
418
      bgs.Image := MainForm.GetSpriteGraphic(smgHintergrundRot);
419
    bgs.Width := Image.Width;
420
    bgs.Height := Image.Height;
24 daniel-mar 421
 
35 daniel-mar 422
    bgs.Y := random(mainform.dxdraw.height);
423
    bgs.X := mainform.dxdraw.width;
24 daniel-mar 424
 
35 daniel-mar 425
    { ran := Random(2);
426
    if ran = 0 then
427
    begin
428
      bgs.Z := -20;
429
      bgs.Speed := 1.8;
430
    end
431
    else if ran = 1 then
432
    begin
433
      bgs.Z := -40;
434
      bgs.Speed := 0.8;
435
    end
436
    else if ran = 2 then
437
    begin }
438
      bgs.Z := -60;
439
      bgs.Speed := 0.3;
440
    { end; }
24 daniel-mar 441
  end;
442
end;
443
 
444
{ TBackgroundSpecial }
445
 
446
procedure TBackgroundSpecial.DoMove(MoveCount: Integer);
447
begin
448
  inherited DoMove(MoveCount);
449
  X := X - MoveCount*(60/1000)*FSpeed;
25 daniel-mar 450
  if X < -Width then Dead;
24 daniel-mar 451
end;
452
 
453
{ TExplosion }
454
 
455
constructor TExplosion.Create(AParent: TSprite);
456
begin
457
  inherited Create(AParent);
31 daniel-mar 458
  mainform.PlaySound(smsExplosion, false);
459
  Image := MainForm.GetSpriteGraphic(smgExplosion);
24 daniel-mar 460
  Width := Image.Width;
461
  Height := Image.Height;
462
  AnimCount := Image.PatternCount;
463
  AnimLooped := True;
464
  AnimSpeed := DEFAULT_ANIMSPEED;
465
  AnimPos := Random(AnimCount);
466
end;
467
 
468
procedure TExplosion.DoMove(MoveCount: Integer);
469
begin
470
  inherited DoMove(MoveCount);
471
  inc(FCounter, MoveCount);
472
  if FCounter > 2999 then dead;
473
end;
474
 
475
{ TPlayerSprite }
476
 
3 daniel-mar 477
constructor TPlayerSprite.Create(AParent: TSprite);
478
begin
479
  inherited Create(AParent);
83 daniel-mar 480
  FState := pesEntering;
31 daniel-mar 481
  Image := MainForm.GetSpriteGraphic(smgMachine);
3 daniel-mar 482
  Width := Image.Width;
483
  Height := Image.Height;
484
  X := -70{20};
485
  Y := mainform.dxdraw.surfaceHeight / 2 - (height / 2);
486
  Z := 2;
487
  AnimCount := Image.PatternCount;
488
  AnimLooped := True;
4 daniel-mar 489
  AnimSpeed := DEFAULT_ANIMSPEED;
3 daniel-mar 490
end;
491
 
492
procedure TPlayerSprite.DoCollision(Sprite: TSprite; var Done: Boolean);
493
begin
72 daniel-mar 494
  if (Sprite is TItem) then
3 daniel-mar 495
  begin
72 daniel-mar 496
    TItem(Sprite).Collected;
497
  end
89 daniel-mar 498
  else if ((Sprite is TEnemy) or (Sprite is TEnemyTama)) and not (ctInfiniteLives in mainform.FCheats) then
72 daniel-mar 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
 
90 daniel-mar 1118
destructor TEnemyBoss.Destroy;
1119
begin
1120
  MainForm.FBoss := nil;
1121
  inherited;
1122
end;
1123
 
24 daniel-mar 1124
procedure TEnemyBoss.DoMove(MoveCount: Integer);
1125
begin
1126
  inherited DoMove(MoveCount);
25 daniel-mar 1127
  if State = pesEntering then
24 daniel-mar 1128
  begin
1129
    if X>((mainform.dxdraw.width/4) + (mainform.dxdraw.width/2) - (width/4)){450} then
3 daniel-mar 1130
      X := X - MoveCount*(300/1000)
1131
    else
1132
    begin
1133
      Collisioned := True;
83 daniel-mar 1134
      FState := pesHovering;
3 daniel-mar 1135
      FPutTama := True;
1136
    end;
1137
    Y := Y + Cos256(FCounter div 15)*5;
7 daniel-mar 1138
  end
25 daniel-mar 1139
  else if State = pesHovering then
3 daniel-mar 1140
  begin
1141
    Y := Y + Cos256(FCounter div 15)*5;
1142
    if FPutTama then
1143
    begin
1144
      if FTamaT>100 then
1145
      begin
23 daniel-mar 1146
        with TEnemyTama.Create(Engine, Self) do
3 daniel-mar 1147
        begin
1148
          Z := 1;
1149
          X := Self.X-Width;
1150
          Y := Self.Y+Self.Height div 2-Height div 2;
1151
        end;
1152
        Inc(FTamaF);
1153
        if FTamaF>Random(30) then FPutTama := False;
1154
        FTamaT := 0;
1155
      end;
1156
      FTamaT := FTamaT + MoveCount;
7 daniel-mar 1157
    end
1158
    else
3 daniel-mar 1159
    begin
1160
      FTamaT := FTamaT + MoveCount;
1161
      if FTamaT>2000+Random(500) then
1162
      begin
1163
        FPutTama := True;
1164
        FTamaF := 0;
1165
        FTamaT := 0;
1166
      end;
1167
    end;
7 daniel-mar 1168
  end
25 daniel-mar 1169
  else if State = pesExploding then
3 daniel-mar 1170
  begin
24 daniel-mar 1171
    inc(waiter1);
1172
    if waiter1 = 3 then
3 daniel-mar 1173
    begin
24 daniel-mar 1174
      waiter1 := 0;
1175
      inc(waiter2);
1176
      if waiter2 <= 20 then
3 daniel-mar 1177
      begin
24 daniel-mar 1178
        with TExplosion.Create(Engine) do
1179
        begin
1180
          Z := 10;
1181
          X := Self.X+Random(Self.Width)-16;
1182
          Y := Self.Y+Random(Self.Height)-16;
1183
        end;
1184
      end
1185
      else
1186
      begin
25 daniel-mar 1187
        Inc(MainForm.FScore, 10000);
83 daniel-mar 1188
        FState := pesDead;
3 daniel-mar 1189
      end;
24 daniel-mar 1190
    end;
7 daniel-mar 1191
  end
25 daniel-mar 1192
  else if State = pesDead then
3 daniel-mar 1193
  begin
25 daniel-mar 1194
    if FCounter>4000 then
1195
    begin
83 daniel-mar 1196
      FState := pesDeadVanished;
25 daniel-mar 1197
      Dead;
1198
    end;
3 daniel-mar 1199
  end;
1200
  inc(FCounter, MoveCount);
1201
end;
1202
 
72 daniel-mar 1203
{ TItem }
1204
 
1205
procedure TItem.Collected;
1206
begin
1207
  MainForm.PlaySound(smsItemCollected, false);
1208
  Dead;
1209
end;
1210
 
1211
procedure TItem.DoMove(MoveCount: Integer);
1212
begin
1213
  X := X - MoveCount*(250/1000);
1214
  if X < -Width then Dead;
1215
end;
1216
 
1217
{ TItemMedikit }
1218
 
1219
procedure TItemMedikit.Collected;
1220
begin
1221
  Inc(MainForm.FLife);
1222
  inherited;
1223
end;
1224
 
1225
constructor TItemMedikit.Create(AParent: TSprite);
1226
begin
1227
  inherited Create(AParent);
83 daniel-mar 1228
  FState := pesNormal;
72 daniel-mar 1229
  Image := MainForm.GetSpriteGraphic(smgItemMedikit);
1230
  Width := Image.Width;
1231
  Height := Image.Height;
1232
  AnimCount := Image.PatternCount;
1233
  AnimLooped := True;
1234
  AnimSpeed := DEFAULT_ANIMSPEED;
1235
  PixelCheck := True;
1236
end;
1237
 
24 daniel-mar 1238
{ TMainForm }
3 daniel-mar 1239
 
1240
procedure TMainForm.FormCreate(Sender: TObject);
79 daniel-mar 1241
resourcestring
1242
  SAppTitle = 'SpaceMission %s';
3 daniel-mar 1243
begin
35 daniel-mar 1244
  Randomize;
1245
 
14 daniel-mar 1246
  LevelData := TLevelData.Create;
35 daniel-mar 1247
 
3 daniel-mar 1248
  { Beginne VCL-Ersatz }
1249
  dxtimer := tdxtimer.Create(self);
1250
  dxtimer.Interval := 33;
1251
  dxtimer.OnActivate := DXTimerActivate;
1252
  dxtimer.OnDeactivate := DXTimerDeactivate;
1253
  dxtimer.OnTimer := DXTimerTimer;
1254
  dxtimer.ActiveOnly := false;
1255
  dxtimer.Enabled := false;
1256
 
1257
  dxdraw := tdxdraw.Create(self);
1258
  dxdraw.Parent := self;
1259
  dxdraw.Align := alClient;
1260
  dxdraw.Left := 0;
1261
  dxdraw.Top := 0;
47 daniel-mar 1262
  dxdraw.Width := ClientWidth;
1263
  dxdraw.Height := ClientHeight;
3 daniel-mar 1264
  dxdraw.AutoInitialize := False;
1265
  dxdraw.AutoSize := False;
1266
  dxdraw.Color := clBlack;
19 daniel-mar 1267
  (*
3 daniel-mar 1268
  dxdraw.Display.BitCount := 24;
1269
  dxdraw.Display.FixedBitCount := False;
1270
  dxdraw.Display.FixedRatio := False;
1271
  dxdraw.Display.FixedSize := False;
1272
  dxdraw.Display.Height := 600;
1273
  dxdraw.Display.Width := 800;
19 daniel-mar 1274
  *)
4 daniel-mar 1275
  dxdraw.Options := [doAllowReboot, doWaitVBlank, doAllowPalette256, doCenter, {doRetainedMode,} doHardware, doSelectDriver];
3 daniel-mar 1276
  dxdraw.TabOrder := 0;
1277
  dxdraw.Visible := true;
1278
  dxdraw.OnFinalize := DXDrawFinalize;
1279
  dxdraw.OnInitialize := DXDrawInitialize;
1280
  dxdraw.OnInitializing := DXDrawInitializing;
1281
 
1282
  dxsound := tdxsound.Create(self);
1283
  dxsound.AutoInitialize := false;
1284
 
18 daniel-mar 1285
  dxmusic := TDXMusic.Create(self);
1286
  dxmusic.DXSound := dxsound;
1287
 
3 daniel-mar 1288
  dxinput := tdxinput.Create(self);
1289
  dxinput.Joystick.ForceFeedback := true;
1290
  dxinput.Keyboard.ForceFeedback := true;
1291
 
1292
  wavelist := tdxwavelist.Create(self);
1293
  wavelist.DXSound := dxsound;
1294
 
1295
  imagelist := tdximagelist.create(self);
1296
  imagelist.DXDraw := dxdraw;
1297
 
1298
  spriteengine := tdxspriteengine.create(self);
1299
  spriteengine.DXDraw := dxdraw;
1300
 
7 daniel-mar 1301
  InitializeCriticalSection(TimerCS);
1302
 
3 daniel-mar 1303
  { Ende VCL-Ersatz }
1304
 
79 daniel-mar 1305
  Application.Title := Format(SAppTitle, [ProgramVersion]);
3 daniel-mar 1306
  LoadOptions;
1307
  DXInit;
1308
  SoundInit;
1309
  MusicInit;
54 daniel-mar 1310
 
3 daniel-mar 1311
  GameStartClick(GameStart);
1312
end;
1313
 
1314
procedure TMainForm.GameStartClick(Sender: TObject);
1315
begin
1316
  StartScene(gsTitle);
1317
end;
1318
 
31 daniel-mar 1319
function TMainForm.GetSpriteGraphic(
1320
  Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
1321
begin
1322
  if (Sprite<>smgNone) and (imagelist.Items.Count >= Ord(Sprite)) then
1323
    result := imagelist.Items.Items[Ord(Sprite)-1]
1324
  else
1325
    result := nil;
1326
end;
1327
 
64 daniel-mar 1328
procedure TMainForm.HilfeTopicClick(Sender: TObject);
1329
// Please keep this code in-sync with LevMain.pas
1330
var
1331
  bakTimerEnabled: boolean;
63 daniel-mar 1332
begin
64 daniel-mar 1333
  bakTimerEnabled := dxtimer.Enabled;
1334
  try
1335
    dxtimer.Enabled := false;
1336
    HilfeForm.Caption := TMenuItem(Sender).Caption;
1337
    HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&&', #1, [rfReplaceAll]);
1338
    HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&', '', [rfReplaceAll]);
1339
    HilfeForm.Caption := StringReplace(HilfeForm.Caption, #1, '&', [rfReplaceAll]);
1340
    HilfeForm.ShowMarkDownHelp(OwnDirectory+TMenuItem(Sender).Hint);
1341
    HilfeForm.ShowModal;
1342
  finally
1343
    dxtimer.Enabled := bakTimerEnabled;
1344
  end;
63 daniel-mar 1345
end;
1346
 
3 daniel-mar 1347
procedure TMainForm.GamePauseClick(Sender: TObject);
1348
begin
1349
  GamePause.Checked := not GamePause.Checked;
1350
  DXTimer.Enabled := not GamePause.Checked;
7 daniel-mar 1351
  if GamePause.Checked then
19 daniel-mar 1352
  begin
1353
    if Assigned(DXTimer.OnDeactivate) then
1354
      DXTimer.OnDeactivate(DXTimer);
1355
  end
7 daniel-mar 1356
  else
19 daniel-mar 1357
  begin
1358
    if Assigned(DXTimer.OnActivate) then
1359
      DXTimer.OnActivate(DXTimer);
1360
  end;
3 daniel-mar 1361
end;
1362
 
24 daniel-mar 1363
procedure TMainForm.DXInit;
3 daniel-mar 1364
begin
24 daniel-mar 1365
  try
79 daniel-mar 1366
    Imagelist.Items.LoadFromFile(OwnDirectory+DxgFile);
24 daniel-mar 1367
    ImageList.Items.MakeColorTable;
1368
    DXDraw.ColorTable := ImageList.Items.ColorTable;
1369
    DXDraw.DefColorTable := ImageList.Items.ColorTable;
1370
    DXDraw.UpdatePalette;
1371
    DXDraw.Finalize;
1372
    DXDraw.Options := DXDraw.Options - [doFullScreen];
1373
    DXDraw.autosize := true;
1374
    DXDraw.Initialize;
1375
  except
1376
    //Imagelist.Items.clear;
1377
    //application.terminate;
3 daniel-mar 1378
  end;
1379
end;
1380
 
1381
procedure TMainForm.CheckUpdatesClick(Sender: TObject);
1382
begin
79 daniel-mar 1383
  CheckForUpdates('spacemission', ProgramVersion); // do not localize
3 daniel-mar 1384
end;
1385
 
1386
procedure TMainForm.BeendenClick(Sender: TObject);
1387
begin
1388
  close;
1389
end;
1390
 
1391
procedure TMainForm.OptionSoundClick(Sender: TObject);
1392
begin
1393
  OptionSound.Checked := not OptionSound.Checked;
1394
  SoundInit;
1395
  WriteOptions;
1396
end;
1397
 
1398
procedure TMainForm.SoundInit;
1399
begin
79 daniel-mar 1400
  if (WaveOutGetNumDevs < 1) or not FileExists(OwnDirectory+DxwFile) then
24 daniel-mar 1401
  begin
1402
    OptionSound.Checked := false;
1403
    OptionSound.Enabled := False;
1404
    exit;
1405
  end;
1406
 
3 daniel-mar 1407
  if OptionSound.Checked then
1408
  begin
1409
    if not DXSound.Initialized then
1410
    begin
1411
      try
1412
        DXSound.Initialize;
79 daniel-mar 1413
        WaveList.Items.LoadFromFile(OwnDirectory+DxwFile);
3 daniel-mar 1414
      except
1415
        OptionSound.enabled := False;
1416
        WaveList.items.clear;
1417
      end;
1418
    end;
1419
  end
1420
  else DXSound.Finalize;
1421
end;
1422
 
1423
procedure TMainForm.MusicInit;
19 daniel-mar 1424
var
1425
  i: integer;
3 daniel-mar 1426
begin
79 daniel-mar 1427
  if (WaveOutGetNumDevs < 1) or not FileExists(OwnDirectory+DxmFile) then
24 daniel-mar 1428
  begin
1429
    optionmusic.Checked := false;
1430
    optionmusic.Enabled := False;
1431
    exit;
1432
  end;
1433
 
18 daniel-mar 1434
  try
79 daniel-mar 1435
    dxmusic.Midis.LoadFromFile(OwnDirectory+DxmFile);
19 daniel-mar 1436
    for i := 0 to dxmusic.Midis.Count-1 do
1437
    begin
1438
      if not dxmusic.Midis.Items[i].IsInitialized then
1439
      begin
97 daniel-mar 1440
        dxmusic.Midis.Items[i].Init; // TODO: for some reason, AddPort is very slow!
19 daniel-mar 1441
        dxmusic.Midis.Items[i].Load;
1442
      end;
1443
    end;
18 daniel-mar 1444
  except
1445
    optionmusic.enabled := false;
1446
  end;
3 daniel-mar 1447
end;
1448
 
1449
procedure TMainForm.DXDrawInitializing(Sender: TObject);
1450
begin
1451
  if doFullScreen in DXDraw.Options then
1452
  begin
1453
    BorderStyle := bsNone;
1454
    DXDraw.Cursor := crNone;
7 daniel-mar 1455
  end
1456
  else
3 daniel-mar 1457
  begin
1458
    BorderStyle := bsSingle;
1459
    DXDraw.Cursor := crDefault;
1460
  end;
1461
end;
1462
 
1463
procedure TMainForm.DXDrawInitialize(Sender: TObject);
1464
begin
42 daniel-mar 1465
  if Assigned(DXTimer) then DXTimer.Enabled := True;
3 daniel-mar 1466
end;
1467
 
1468
procedure TMainForm.DXDrawFinalize(Sender: TObject);
1469
begin
42 daniel-mar 1470
  if Assigned(DXTimer) then DXTimer.Enabled := False;
3 daniel-mar 1471
end;
1472
 
1473
procedure TMainForm.DXTimerActivate(Sender: TObject);
1474
begin
19 daniel-mar 1475
  if TDxTimer(Sender).Tag > 0 then
1476
    TDxTimer(Sender).Tag := TDxTimer(Sender).Tag - 1; // es können mehrere activate/deactivate vorkommen, wegen dem Pause-Button
1477
  if TDxTimer(Sender).Tag > 0 then
1478
    exit;
3 daniel-mar 1479
  Caption := Application.Title;
1480
  if not ProgrammGestartet then
1481
  begin
1482
    Programmgestartet := true;
1483
    exit;
1484
  end;
1485
  ResumeMusic(FMusic);
1486
end;
1487
 
1488
procedure TMainForm.DXTimerDeactivate(Sender: TObject);
79 daniel-mar 1489
resourcestring
1490
  SPauseTitle = '%s [Pause]';
3 daniel-mar 1491
begin
19 daniel-mar 1492
  TDxTimer(Sender).Tag := TDxTimer(Sender).Tag + 1;
79 daniel-mar 1493
  Caption := Format(SPauseTitle, [Application.Title]);
3 daniel-mar 1494
  PauseMusic(FMusic);
1495
end;
1496
 
1497
procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
1498
begin
7 daniel-mar 1499
  EnterCriticalSection(TimerCS);
1500
  try
1501
    if crash then
3 daniel-mar 1502
    begin
7 daniel-mar 1503
      inc(Crash2);
1504
      if crash2 = 30 then
1505
      begin
1506
        Crash2 := 0;
1507
        crash := false;
1508
        crashsound := false;
1509
      end;
3 daniel-mar 1510
    end;
7 daniel-mar 1511
    if not DXDraw.CanDraw then exit;
1512
    DXInput.Update;
1513
    case FScene of
1514
      gsTitle   : SceneTitle;
1515
      gsMain    : SceneMain;
1516
      gsGameOver: SceneGameOver;
1517
      gsWin     : SceneWin;
1518
      gsNewLevel: SceneNewLevel;
1519
    end;
1520
    if FNextScene<>gsNone then
1521
    begin
1522
      StartScene(FNextScene);
1523
      FNextScene := gsNone;
1524
    end;
1525
    DXDraw.Flip;
1526
  finally
1527
    LeaveCriticalSection(TimerCS);
3 daniel-mar 1528
  end;
1529
end;
1530
 
1531
procedure TMainForm.BlinkStart;
1532
begin
1533
  FBlink := 0;
1534
  FBlinkTime := GetTickCount;
1535
end;
1536
 
1537
procedure TMainForm.WriteOptions;
1538
var
26 daniel-mar 1539
  Reg: TRegistry;
3 daniel-mar 1540
begin
26 daniel-mar 1541
  Reg := TRegistry.Create;
7 daniel-mar 1542
  try
26 daniel-mar 1543
    Reg.RootKey := HKEY_CURRENT_USER;
1544
    if Reg.OpenKey(RegistrySettingsKey, true) then
1545
    begin
79 daniel-mar 1546
      Reg.WriteBool(MusicSettingKey, OptionMusic.checked);
1547
      Reg.WriteBool(SoundSettingKey, OptionSound.checked);
80 daniel-mar 1548
      Reg.WriteInteger(SpeedSettingKey, Ord(FSpeed));
1549
      Reg.DeleteValue('Speed'); // deprecated. Replaced by GameSpeed
26 daniel-mar 1550
      Reg.CloseKey;
1551
    end;
7 daniel-mar 1552
  finally
26 daniel-mar 1553
    FreeAndNil(Reg);
7 daniel-mar 1554
  end;
3 daniel-mar 1555
end;
1556
 
1557
procedure TMainForm.LoadOptions;
1558
var
26 daniel-mar 1559
  Reg: TRegistry;
3 daniel-mar 1560
begin
26 daniel-mar 1561
  Reg := TRegistry.Create;
7 daniel-mar 1562
  try
26 daniel-mar 1563
    Reg.RootKey := HKEY_CURRENT_USER;
1564
    if Reg.OpenKey(RegistrySettingsKey, true) then
7 daniel-mar 1565
    begin
79 daniel-mar 1566
      if Reg.ValueExists(MusicSettingKey) then
1567
        optionmusic.checked := Reg.ReadBool(MusicSettingKey)
26 daniel-mar 1568
      else
1569
        optionmusic.checked := true; // default
1570
 
79 daniel-mar 1571
      if Reg.ValueExists(SoundSettingKey) then
1572
        optionsound.checked := Reg.ReadBool(SoundSettingKey)
26 daniel-mar 1573
      else
1574
        optionsound.checked := true; // default
1575
 
79 daniel-mar 1576
      if Reg.ValueExists(SpeedSettingKey) then
80 daniel-mar 1577
        FSpeed := Reg.ReadInteger(SpeedSettingKey)
26 daniel-mar 1578
      else
81 daniel-mar 1579
        FSpeed := SpeedMedium; // default
26 daniel-mar 1580
 
81 daniel-mar 1581
      Leicht.Checked := FSpeed = SpeedEasy;
1582
      Mittel.Checked := FSpeed = SpeedMedium;
1583
      Schwer.Checked := FSpeed = SpeedHard;
1584
      Master.Checked := FSpeed = SpeedMaster;
80 daniel-mar 1585
 
26 daniel-mar 1586
      Reg.CloseKey;
7 daniel-mar 1587
    end;
1588
  finally
26 daniel-mar 1589
    FreeAndNil(Reg);
3 daniel-mar 1590
  end;
1591
  WriteOptions;
1592
end;
1593
 
1594
procedure TMainForm.BlinkUpdate;
1595
begin
1596
  if GetTickCount<>FBlinkTime then
1597
  begin
1598
    FBlink := FBlink + (GetTickCount-FBlinkTime);
1599
    FBlinkTime := GetTickCount;
1600
  end;
1601
end;
1602
 
31 daniel-mar 1603
procedure TMainForm.PlaySound(Sound: TSpaceMissionSound; Wait: Boolean);
3 daniel-mar 1604
begin
31 daniel-mar 1605
  if (Sound<>smsNone) and (OptionSound.Checked) and (OptionSound.Enabled) and (WaveList.Items.Count >= Ord(Sound)) then
1606
    WaveList.Items.Items[Ord(Sound)-1].Play(Wait);
3 daniel-mar 1607
end;
1608
 
31 daniel-mar 1609
procedure TMainForm.MusicSwitchTrack(Name: TSpaceMissionMusicTrack);
3 daniel-mar 1610
begin
1611
  if (not mainform.active) and (mainform.visible) then //1st Programmstart
1612
    exit;
1613
  if (OptionMusic.checked) and (OptionMusic.enabled) then
1614
  begin
19 daniel-mar 1615
    StopMusic(FMusic);
1616
    PlayMusic(Name);
3 daniel-mar 1617
  end;
1618
  FMusic := Name;
1619
end;
1620
 
1621
function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
1622
begin
1623
  with Result do
1624
  begin
1625
    rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256);
1626
    rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256);
1627
    rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256);
1628
    rgbReserved := 0;
1629
  end;
1630
end;
1631
 
1632
procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer);
1633
var
1634
  i: Integer;
1635
  t, t2: DWORD;
1636
  ChangePalette: Boolean;
1637
  c: Integer;
1638
begin
1639
  if DXDraw.Initialized then
1640
  begin
1641
    c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue));
1642
    ChangePalette := False;
1643
    if DXDraw.CanPaletteAnimation then
1644
    begin
1645
      t := GetTickCount;
1646
      while Abs(GetTickCount-t)<Time do
1647
      begin
1648
        t2 := Trunc(Abs(GetTickCount-t)/Time*255);
1649
        for i := 0 to 255 do
1650
          DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2);
1651
        DXDraw.UpdatePalette;
1652
        ChangePalette := True;
1653
      end;
7 daniel-mar 1654
    end
1655
    else
1656
    begin
3 daniel-mar 1657
      Sleep(Time);
7 daniel-mar 1658
    end;
3 daniel-mar 1659
    for i := 0 to 4 do
1660
    begin
1661
      DXDraw.Surface.Fill(c);
1662
      DXDraw.Flip;
1663
    end;
1664
    if ChangePalette then
1665
    begin
1666
      DXDraw.ColorTable := DXDraw.DefColorTable;
1667
      DXDraw.UpdatePalette;
1668
    end;
1669
    DXDraw.Surface.Fill(c);
1670
    DXDraw.Flip;
1671
  end;
1672
end;
1673
 
1674
procedure TMainForm.StartScene(Scene: TGameScene);
1675
begin
1676
  EndScene;
1677
  DXInput.States := DXInput.States - DXInputButton;
1678
  FScene := Scene;
1679
  BlinkStart;
1680
  case FScene of
1681
    gsTitle   : StartSceneTitle;
1682
    gsMain    : StartSceneMain;
1683
    gsGameOver: StartSceneGameOver;
1684
    gsWin     : StartSceneWin;
1685
    gsNewLevel: StartSceneNewLevel;
1686
  end;
1687
end;
1688
 
1689
procedure TMainForm.StartSceneTitle;
1690
begin
1691
  sleep(500);
89 daniel-mar 1692
  FCheats := [];
37 daniel-mar 1693
  FLife := StartLives;
3 daniel-mar 1694
  FLevel := 0;
1695
  FScore := 0;
46 daniel-mar 1696
  FLevelDataAlreadyLoaded := false; // do allow NewLevel() to work again
3 daniel-mar 1697
  FNotSave := true;
1698
  Cheat.enabled := false;
1699
  Neustart.enabled := false;
1700
  GamePause.enabled := false;
1701
  GameStart.enabled := false;
1702
  Spielgeschwindigkeit.enabled := false;
1703
  mainform.Visible := true;
31 daniel-mar 1704
  MusicSwitchTrack(smmTitle);
3 daniel-mar 1705
end;
1706
 
1707
procedure TMainForm.StartSceneMain;
1708
{var
1709
  i, j: Integer;}
1710
begin
1711
  sleep(500);
1712
  FCounter := 0;
40 daniel-mar 1713
  if not FLevelDataAlreadyLoaded then NewLevel(FLevel);
1714
  FRestEnemies := Length(LevelData.EnemyAdventTable);
1715
  FLifeAtLevelStart := FLife;     // Das ist wichtig, wenn man neu starten möchte
1716
  FScoreAtLevelStart := FScore;   //
31 daniel-mar 1717
  MusicSwitchTrack(smmGame);
7 daniel-mar 1718
  FEnemyAdventPos := 0;
3 daniel-mar 1719
  FFrame := -4;
1720
  PlayerSprite := TPlayerSprite.Create(SpriteEngine.Engine);
1721
  with TBackground.Create(SpriteEngine.Engine) do
1722
  begin
1723
    SetMapSize(1, 1);
31 daniel-mar 1724
    Image := MainForm.GetSpriteGraphic(smgStar3);
3 daniel-mar 1725
    Z := -13;
1726
    Y := 40;
23 daniel-mar 1727
    Speed := 1 / 2;
3 daniel-mar 1728
    Tile := True;
1729
  end;
1730
  with TBackground.Create(SpriteEngine.Engine) do
1731
  begin
1732
    SetMapSize(1, 1);
31 daniel-mar 1733
    Image := MainForm.GetSpriteGraphic(smgStar2);
3 daniel-mar 1734
    Z := -12;
1735
    Y := 30;
23 daniel-mar 1736
    Speed := 1;
3 daniel-mar 1737
    Tile := True;
1738
  end;
1739
  with TBackground.Create(SpriteEngine.Engine) do
1740
  begin
1741
    SetMapSize(1, 1);
31 daniel-mar 1742
    Image := MainForm.GetSpriteGraphic(smgStar1);
3 daniel-mar 1743
    Z := -11;
1744
    Y := 10;
23 daniel-mar 1745
    Speed := 2;
3 daniel-mar 1746
    Tile := True;
1747
  end;
1748
  {with TBackground.Create(SpriteEngine.Engine) do
1749
  begin
1750
    SetMapSize(200, 10);
1751
    Y := 10;
1752
    Z := -13;
23 daniel-mar 1753
    Speed := 1 / 2;
3 daniel-mar 1754
    Tile := True;
1755
    for i := 0 to MapHeight-1 do
1756
    begin
1757
      for j := 0 to MapWidth-1 do
1758
      begin
1759
        Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8);
1760
        if Random(100)<95 then Chips[j, i] := -1;
1761
      end;
1762
    end;
1763
  end;
1764
  with TBackground.Create(SpriteEngine.Engine) do
1765
  begin
1766
    SetMapSize(200, 10);
1767
    Y := 30;
1768
    Z := -12;
23 daniel-mar 1769
    Speed := 1;
3 daniel-mar 1770
    Tile := True;
1771
    for i := 0 to MapHeight-1 do
1772
    begin
1773
      for j := 0 to MapWidth-1 do
1774
      begin
1775
        Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4);
1776
        if Random(100)<95 then Chips[j, i] := -1;
1777
      end;
1778
    end;
1779
  end;
1780
  with TBackground.Create(SpriteEngine.Engine) do
1781
  begin
1782
    SetMapSize(200, 10);
1783
    Y := 40;
1784
    Z := -11;
23 daniel-mar 1785
    Speed := 2;
3 daniel-mar 1786
    Tile := True;
1787
    for i := 0 to MapHeight-1 do
1788
    begin
1789
      for j := 0 to MapWidth-1 do
1790
      begin
1791
        Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2);
1792
        if Random(100)<95 then Chips[j, i] := -1;
1793
      end;
1794
    end;
1795
  end;}
1796
  FNotSave := false;
1797
  Cheat.enabled := true;
1798
  Neustart.enabled := true;
1799
  GamePause.enabled := true;
1800
  GameStart.enabled := true;
1801
  Spielgeschwindigkeit.enabled := true;
1802
end;
1803
 
1804
procedure TMainForm.StartSceneGameOver;
1805
begin
1806
  sleep(500);
46 daniel-mar 1807
  FNotSave := true; // Wenn man speichert, würde man LevelAdventTable vom vorherigen Level machen, das wär müll!
3 daniel-mar 1808
  Cheat.enabled := false;
1809
  Spielgeschwindigkeit.enabled := false;
1810
  Neustart.enabled := false;
1811
  GamePause.enabled := false;
31 daniel-mar 1812
  MusicSwitchTrack(smmScene);
3 daniel-mar 1813
end;
1814
 
1815
procedure TMainForm.StartSceneWin;
1816
begin
1817
  sleep(500);
46 daniel-mar 1818
  FNotSave := true; // Wenn man speichert, würde man LevelAdventTable vom vorherigen Level machen, das wär müll!
3 daniel-mar 1819
  Cheat.enabled := false;
1820
  Spielgeschwindigkeit.enabled := false;
1821
  Neustart.enabled := false;
1822
  GamePause.enabled := false;
31 daniel-mar 1823
  MusicSwitchTrack(smmScene);
3 daniel-mar 1824
end;
1825
 
1826
procedure TMainForm.EndScene;
1827
begin
1828
  case FScene of
1829
    gsTitle   : EndSceneTitle;
1830
    gsMain    : EndSceneMain;
1831
    gsGameOver: EndSceneGameOver;
1832
    gsWin     : EndSceneWin;
1833
    gsNewLevel: EndSceneNewLevel;
1834
  end;
1835
end;
1836
 
1837
procedure TMainForm.EndSceneTitle;
1838
begin
1839
  {  Ende Title  }
1840
end;
1841
 
1842
procedure TMainForm.EndSceneMain;
1843
begin
1844
  SpriteEngine.Engine.Clear;
1845
end;
1846
 
1847
procedure TMainForm.EndSceneGameOver;
1848
begin
1849
  {  Ende GameOver  }
1850
end;
1851
 
1852
procedure TMainForm.EndSceneWin;
1853
begin
1854
  {  Ende Win  }
1855
end;
1856
 
14 daniel-mar 1857
procedure TMainForm.ResetLevelData;
3 daniel-mar 1858
begin
14 daniel-mar 1859
  LevelData.Clear;
7 daniel-mar 1860
  FRestEnemies := 0;
3 daniel-mar 1861
end;
1862
 
1863
procedure TMainForm.NewLevel(lev: integer);
1864
resourcestring
90 daniel-mar 1865
  SLevelInvalid = 'Die Datei für Level %d ist ungültig. Level wird übersprungen!';
3 daniel-mar 1866
var
1867
  act: integer;
78 daniel-mar 1868
  Enemies: array[1..32] of TEnemyType;
40 daniel-mar 1869
  numEnemies: integer;
7 daniel-mar 1870
  e: TEnemyAdvent;
78 daniel-mar 1871
  bossPosition: integer;
61 daniel-mar 1872
  levFile: TLevelFile;
3 daniel-mar 1873
begin
14 daniel-mar 1874
  ResetLevelData;
15 daniel-mar 1875
  if FGameMode = gmRandom then
3 daniel-mar 1876
  begin
14 daniel-mar 1877
    {$REGION 'Random game'}
49 daniel-mar 1878
    Enemies[1] := etEnemyAttacker;     // ab Lev 1
1879
    Enemies[2] := etEnemyMeteor;       // ab Lev 1
1880
    Enemies[3] := etEnemyUFO;          // ab Lev 1
1881
    Enemies[4] := etEnemyAttacker;     // ab Lev 2
1882
    Enemies[5] := etEnemyMeteor;       // ab Lev 3
78 daniel-mar 1883
    Enemies[6] := etEnemyUFO;          // ab Lev 4
1884
    Enemies[7] := etEnemyAttacker;     // ab Lev 5
1885
    Enemies[8] := etEnemyMeteor;       // ab Lev 6
1886
    Enemies[9] := etEnemyUFO;          // ab Lev 7
1887
    Enemies[10] := etEnemyAttacker;    // ab Lev 8
1888
    Enemies[11] := etEnemyMeteor;      // ab Lev 9
1889
    Enemies[12] := etEnemyUFO;         // ab Lev 10
1890
    Enemies[13] := etEnemyAttacker;    // ab Lev 11
1891
    Enemies[14] := etEnemyMeteor;      // ab Lev 12
1892
    Enemies[15] := etEnemyUFO;         // ab Lev 13
1893
    Enemies[16] := etEnemyAttacker3;   // ab Lev 14
1894
    Enemies[17] := etEnemyAttacker;    // ab Lev 15
1895
    Enemies[18] := etEnemyMeteor;      // ab Lev 16
1896
    Enemies[19] := etEnemyUFO;         // ab Lev 17
1897
    Enemies[20] := etEnemyUFO2;        // ab Lev 18
1898
    Enemies[21] := etEnemyAttacker;    // ab Lev 19
1899
    Enemies[22] := etEnemyMeteor;      // ab Lev 20
1900
    Enemies[23] := etEnemyUFO;         // ab Lev 21
1901
    Enemies[24] := etEnemyAttacker2;   // ab Lev 22
1902
    Enemies[25] := etEnemyMeteor;      // ab Lev 23
1903
    Enemies[26] := etEnemyUFO;         // ab Lev 24
1904
    Enemies[27] := etEnemyAttacker;    // ab Lev 25
1905
    Enemies[28] := etEnemyAttacker;    // ab Lev 26
1906
    Enemies[29] := etEnemyAttacker2;   // ab Lev 27
1907
    Enemies[30] := etEnemyAttacker3;   // ab Lev 28
1908
    Enemies[31] := etEnemyUFO;         // ab Lev 29
1909
    Enemies[32] := etEnemyUFO2;        // ab Lev 30
81 daniel-mar 1910
    numEnemies := lev*RandomLevelAdditionalEnemiesPerLevel;
40 daniel-mar 1911
    SetLength(LevelData.EnemyAdventTable, numEnemies);
1912
    for act := 0 to numEnemies-1 do
3 daniel-mar 1913
    begin
14 daniel-mar 1914
      e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))];
1915
      if e.enemyType = etEnemyAttacker2 then
7 daniel-mar 1916
      begin
49 daniel-mar 1917
        //e.enemyType := Enemies[min(random(lev+2)+1, High(Enemies))];
1918
        if Random(2) = 0 then e.enemyType := etEnemyAttacker3;
7 daniel-mar 1919
      end;
39 daniel-mar 1920
      e.x := 85-(lev+(random(lev))*2){O_o};
1921
      if e.x < 1 then e.x := 1; // passiert bei großen Levels
1922
      e.x := act*30 + random(e.x);
81 daniel-mar 1923
      e.y := random((LevEditRows-1)*LevEditRasterH);
14 daniel-mar 1924
      if e.enemyType = etEnemyAttacker2 then
7 daniel-mar 1925
      begin
1926
        e.lifes := random(6)+1{O_o};
1927
      end
1928
      else
1929
      begin
39 daniel-mar 1930
        if lev > RandomLevelMaxEnemyLives then
37 daniel-mar 1931
        begin
39 daniel-mar 1932
          e.lifes := random(RandomLevelMaxEnemyLives)+1;
37 daniel-mar 1933
        end
1934
        else
1935
        begin
1936
          e.lifes := random(lev)+1;
1937
        end;
7 daniel-mar 1938
      end;
1939
 
81 daniel-mar 1940
      if (act-1) mod RandomLevelMedikitEveryX = 0 then
78 daniel-mar 1941
      begin
1942
        e.enemyType := etItemMedikit;
1943
        e.lifes := 0;
1944
      end;
1945
 
14 daniel-mar 1946
      LevelData.EnemyAdventTable[act] := e;
3 daniel-mar 1947
    end;
37 daniel-mar 1948
 
1949
    if lev < 5 then
1950
    begin
1951
      // Level 1-4: No boss
1952
      bossPosition := -1;
1953
    end
1954
    else if lev < 10 then
1955
    begin
1956
      // Level 5-9: Boss is at the end of the level
40 daniel-mar 1957
      bossPosition := numEnemies-1;
37 daniel-mar 1958
    end
1959
    else
1960
    begin
39 daniel-mar 1961
      // Starting with Level 10: Boss at 75% of the level
40 daniel-mar 1962
      bossPosition := round(0.75 * numEnemies);
37 daniel-mar 1963
    end;
1964
 
78 daniel-mar 1965
    if LevelData.EnemyAdventTable[bossPosition].enemyType = etItemMedikit then
1966
      Inc(bossPosition);
1967
 
37 daniel-mar 1968
    if bossPosition >= 0 then
1969
    begin
1970
      e.enemyType := etEnemyBoss;
39 daniel-mar 1971
      //e.x := lev*75*30{O_o} div lev;
1972
      e.x := LevelData.EnemyAdventTable[bossPosition-1].x;
37 daniel-mar 1973
      e.y := (dxdraw.surfaceheight div 2) - (MainForm.GetSpriteGraphic(smgEnemyBoss).height div 2);
1974
      e.lifes := lev*5;
1975
      LevelData.EnemyAdventTable[bossPosition] := e;
1976
    end;
72 daniel-mar 1977
 
14 daniel-mar 1978
    {$ENDREGION}
3 daniel-mar 1979
  end
1980
  else
1981
  begin
14 daniel-mar 1982
    {$REGION 'Normal game'}
61 daniel-mar 1983
    levFile := GetLevelFileName(lev,false);
1984
    if levFile.found then
3 daniel-mar 1985
    begin
7 daniel-mar 1986
      try
44 daniel-mar 1987
        LevelData.RasterErzwingen := false;
61 daniel-mar 1988
        LevelData.LoadFromFile(levFile.fileLocation);
7 daniel-mar 1989
      except
79 daniel-mar 1990
        showmessage(Format(SLevelInvalid, [lev]));
90 daniel-mar 1991
        ResetLevelData; // empty level = the player will continue with the next level
3 daniel-mar 1992
      end;
1993
    end;
14 daniel-mar 1994
    {$ENDREGION}
3 daniel-mar 1995
  end;
46 daniel-mar 1996
  FLevelDataAlreadyLoaded := true; // nicht nochmal NewLevel() aufrufen. Erst wieder wenn man gewonnen hat.
3 daniel-mar 1997
end;
1998
 
65 daniel-mar 1999
var
2000
  TitleWasPressed: TDxInputState = isButton32;
2001
 
3 daniel-mar 2002
procedure TMainForm.SceneTitle;
90 daniel-mar 2003
resourcestring
2004
  SNormalGame = 'Normales Spiel';
2005
  SRandomGame = 'Zufalls-Level';
2006
  SLevelEditor = 'Level-Editor';
3 daniel-mar 2007
var
2008
  Logo: TPictureCollectionItem;
65 daniel-mar 2009
  colo1, colo2: TColor;
3 daniel-mar 2010
begin
2011
  DXDraw.Surface.Fill(0);
31 daniel-mar 2012
  Logo := GetSpriteGraphic(smgLogo);
3 daniel-mar 2013
  {Logo.DrawWaveX(DXDraw.Surface, (dxdraw.surfaceWidth div 2) - 181, 65, Logo.Width, Logo.Height, 0,
2014
    Trunc(16 - Cos256(FBlink div 60) * 16), 32, -FBlink div 5);}
2015
  Logo.DrawWaveX(DXDraw.Surface, trunc((dxdraw.surfaceWidth / 2) - (Logo.Width / 2)), 65, Logo.Width, Logo.Height, 0,
2016
    2, 80, Fangle * 4);
2017
  inc(Fangle);
23 daniel-mar 2018
 
65 daniel-mar 2019
  if FGameMode = gmUnknown then FGameMode := gmLevels;
2020
 
2021
  if (isUp in MainForm.DXInput.States) then TitleWasPressed := isUp;
2022
  if (TitleWasPressed=isUp) and not (isUp in MainForm.DXInput.States) then
2023
  begin
2024
    TitleWasPressed := isButton32;
2025
    if (Ord(FGameMode) <> 1) then
2026
      FGameMode := TGameMode(Ord(FGameMode)-1);
2027
  end;
2028
 
2029
  if (isDown in MainForm.DXInput.States) then TitleWasPressed := isDown;
2030
  if (TitleWasPressed=isDown) and not (isDown in MainForm.DXInput.States) then
2031
  begin
2032
    TitleWasPressed := isButton32;
2033
    if (FGameMode <> High(TGameMode)) then
2034
      FGameMode := TGameMode(Ord(FGameMode)+1);
2035
  end;
2036
 
23 daniel-mar 2037
  DXDraw.Surface.Canvas.Brush.Style := bsClear;
2038
  DXDraw.Surface.Canvas.Font.Size := 30;
65 daniel-mar 2039
 
2040
  {$REGION 'Menu point: Normal Level'}
23 daniel-mar 2041
  if FGameMode = gmLevels then
3 daniel-mar 2042
  begin
65 daniel-mar 2043
    colo1 := clMaroon;
2044
    colo2 := clRed;
2045
  end
2046
  else
2047
  begin
2048
    colo1 := clOlive;
2049
    colo2 := clYellow;
2050
  end;
2051
  DXDraw.Surface.Canvas.Font.Color := colo1;
90 daniel-mar 2052
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-52, SNormalGame);
65 daniel-mar 2053
  if FGameMode = gmLevels then
2054
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)-52, '>');
2055
  DXDraw.Surface.Canvas.Font.Color := colo2;
90 daniel-mar 2056
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)-50, SNormalGame);
65 daniel-mar 2057
  if FGameMode = gmLevels then
23 daniel-mar 2058
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)-50, '>');
65 daniel-mar 2059
  {$ENDREGION}
2060
 
2061
  {$REGION 'Menu point: Random Level'}
2062
  if FGameMode = gmRandom then
2063
  begin
2064
    colo1 := clMaroon;
2065
    colo2 := clRed;
23 daniel-mar 2066
  end
2067
  else
2068
  begin
65 daniel-mar 2069
    colo1 := clOlive;
2070
    colo2 := clYellow;
2071
  end;
2072
  DXDraw.Surface.Canvas.Font.Color := colo1;
90 daniel-mar 2073
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)-2, SRandomGame);
65 daniel-mar 2074
  if FGameMode = gmRandom then
23 daniel-mar 2075
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, (dxdraw.surfaceheight div 2)-2, '>');
65 daniel-mar 2076
  DXDraw.Surface.Canvas.Font.Color := colo2;
90 daniel-mar 2077
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2), SRandomGame);
65 daniel-mar 2078
  if FGameMode = gmRandom then
23 daniel-mar 2079
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2), '>');
65 daniel-mar 2080
  {$ENDREGION}
2081
 
2082
  {$REGION 'Menu point: Level Editor'}
2083
  if FGameMode = gmEditor then
2084
  begin
2085
    colo1 := clMaroon;
2086
    colo2 := clRed;
2087
  end
2088
  else
2089
  begin
2090
    colo1 := clOlive;
2091
    colo2 := clYellow;
3 daniel-mar 2092
  end;
65 daniel-mar 2093
  DXDraw.Surface.Canvas.Font.Color := colo1;
90 daniel-mar 2094
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-152, (dxdraw.surfaceheight div 2)+48, SLevelEditor);
65 daniel-mar 2095
  if FGameMode = gmEditor then
2096
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)+48, '>');
2097
  DXDraw.Surface.Canvas.Font.Color := colo2;
90 daniel-mar 2098
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-150, (dxdraw.surfaceheight div 2)+50, SLevelEditor);
65 daniel-mar 2099
  if FGameMode = gmEditor then
2100
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, (dxdraw.surfaceheight div 2)+50, '>');
2101
  {$ENDREGION}
2102
 
23 daniel-mar 2103
  { if (FBlink div 300) mod 2=0 then
2104
  begin
2105
    DXDraw.Surface.Canvas.Font.Color := clGreen;
90 daniel-mar 2106
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, SWeiterMitLeertaste);
23 daniel-mar 2107
    DXDraw.Surface.Canvas.Font.Color := clLime;
90 daniel-mar 2108
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, SWeiterMitLeertaste);
23 daniel-mar 2109
  end; }
2110
  BlinkUpdate;
2111
  DXDraw.Surface.Canvas.Release;
2112
 
3 daniel-mar 2113
  // Weiter mit Leertaste oder Enter
2114
  if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
2115
  begin
2116
    FLevel := 1;
65 daniel-mar 2117
    if FGameMode = gmEditor then
3 daniel-mar 2118
    begin
79 daniel-mar 2119
      ShellExecute(0, 'open', PChar(OwnDirectory+LevEditExe), '', PChar(OwnDirectory), SW_NORMAL); // do not localize
65 daniel-mar 2120
      Close;
2121
      exit;
2122
    end;
2123
    if ((FGameMode=gmLevels) and not GetLevelFileName(FLevel,false).found) or
2124
       ((FGameMode=gmRandom) and (FLevel > MaxPossibleLevels)) then
2125
    begin
3 daniel-mar 2126
      //PlaySound('Frage', False);
2127
      exit;
2128
    end;
31 daniel-mar 2129
    PlaySound(smsSceneMov, False);
3 daniel-mar 2130
    PalleteAnim(RGBQuad(0, 0, 0), 300);
2131
    Sleep(200);
2132
    StartScene(gsMain);
2133
  end;
2134
end;
2135
 
2136
procedure TMainForm.SceneMain;
79 daniel-mar 2137
resourcestring
83 daniel-mar 2138
  SMissionSuccessful = 'Mission erfolgreich!';
79 daniel-mar 2139
  SMissionFailed = 'Mission gescheitert!';
83 daniel-mar 2140
  SPunkte = 'Punkte: %s';
79 daniel-mar 2141
  SLevel = 'Level: %d';
2142
  SLifes = 'Leben: %d';
2143
  SInfLifes = '';
2144
  SBossLifes = 'Boss: %d';
2145
  SEinheiten = 'Einheiten: %d';
3 daniel-mar 2146
var
2147
  Enemy: TSprite;
72 daniel-mar 2148
  spriteClass: TClass;
37 daniel-mar 2149
  tmpEnemyAnzeige: integer;
3 daniel-mar 2150
begin
80 daniel-mar 2151
  SpriteEngine.Move(FSpeed);
3 daniel-mar 2152
  SpriteEngine.Dead;
14 daniel-mar 2153
  while (FEnemyAdventPos >= Low(LevelData.EnemyAdventTable)) and
2154
    (FEnemyAdventPos <= High(LevelData.EnemyAdventTable)) and
2155
    ((LevelData.EnemyAdventTable[FEnemyAdventPos].x / 4) <= FFrame) and
7 daniel-mar 2156
    (FRestEnemies > 0) do
3 daniel-mar 2157
  begin
7 daniel-mar 2158
    Dec(FRestEnemies);
14 daniel-mar 2159
    with LevelData.EnemyAdventTable[FEnemyAdventPos] do
3 daniel-mar 2160
    begin
14 daniel-mar 2161
      spriteClass := nil;
2162
      case enemyType of
2163
        //etUnknown: ;
2164
        etEnemyAttacker:  spriteClass := TEnemyAttacker;
2165
        etEnemyAttacker2: spriteClass := TEnemyAttacker2;
2166
        etEnemyAttacker3: spriteClass := TEnemyAttacker3;
2167
        etEnemyMeteor:    spriteClass := TEnemyMeteor;
2168
        etEnemyUFO:       spriteClass := TEnemyUFO;
2169
        etEnemyUFO2:      spriteClass := TEnemyUFO2;
2170
        etEnemyBoss:      spriteClass := TEnemyBoss;
72 daniel-mar 2171
        etItemMedikit:    spriteClass := TItemMedikit;
14 daniel-mar 2172
      end;
2173
      if spriteClass <> nil then
2174
      begin
72 daniel-mar 2175
        Enemy := nil;
2176
        if spriteClass.InheritsFrom(TEnemy) then
2177
          Enemy := TEnemyClass(spriteClass).Create(SpriteEngine.Engine, lifes)
2178
        else if spriteClass.InheritsFrom(TItem) then
2179
          Enemy := TItemClass(spriteClass).Create(SpriteEngine.Engine)
2180
        else
2181
          Assert(False);
14 daniel-mar 2182
        Enemy.x := dxdraw.surfacewidth;
2183
        //Enemy.y := y;
2184
        if y <> 0 then
81 daniel-mar 2185
          Enemy.y := dxdraw.surfaceheight / ((LevEditRows*LevEditRasterH) / y)
14 daniel-mar 2186
        else
2187
          Enemy.y := 0;
2188
      end;
3 daniel-mar 2189
    end;
2190
    Inc(FEnemyAdventPos);
2191
  end;
2192
  Inc(FFrame);
2193
  DXDraw.Surface.Fill(0);
2194
  if FNextScene=gsNone then
2195
  begin
2196
    SpriteEngine.Draw;
40 daniel-mar 2197
    DXDraw.Surface.Canvas.Brush.Style := bsClear;
2198
    DXDraw.Surface.Canvas.Font.Size := 20;
47 daniel-mar 2199
    if flife > 0 then
3 daniel-mar 2200
    begin
40 daniel-mar 2201
      {$REGION 'Anzeige Punkte'}
23 daniel-mar 2202
      DXDraw.Surface.Canvas.Font.Color := clOlive;
79 daniel-mar 2203
      DXDraw.Surface.Canvas.Textout(9, 9, Format(SPunkte, [FloatToStrF(FScore,ffNumber,14,0)]));
23 daniel-mar 2204
      DXDraw.Surface.Canvas.Font.Color := clYellow;
79 daniel-mar 2205
      DXDraw.Surface.Canvas.Textout(10, 10, Format(SPunkte, [FloatToStrF(FScore,ffNumber,14,0)]));
37 daniel-mar 2206
      {$ENDREGION}
2207
 
2208
      {$REGION 'Anzeige Level'}
40 daniel-mar 2209
      DXDraw.Surface.Canvas.Font.Color := clMaroon;
79 daniel-mar 2210
      DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-141, 9, Format(SLevel, [flevel]));
23 daniel-mar 2211
      DXDraw.Surface.Canvas.Font.Color := clRed;
79 daniel-mar 2212
      DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-140, 10, Format(SLevel, [flevel]));
37 daniel-mar 2213
      {$ENDREGION}
2214
 
2215
      {$REGION 'Lebensanzeige'}
47 daniel-mar 2216
      if FLife<0 then FLife := 0;
89 daniel-mar 2217
      if ctInfiniteLives in FCheats 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, SInfLifes);
23 daniel-mar 2221
        DXDraw.Surface.Canvas.Font.Color := clFuchsia;
79 daniel-mar 2222
        DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, SInfLifes);
23 daniel-mar 2223
      end
2224
      else
2225
      begin
2226
        if ((Flife = 1) and ((FBlink div 300) mod 2=0)) or (Flife <> 1) then
3 daniel-mar 2227
        begin
23 daniel-mar 2228
          DXDraw.Surface.Canvas.Font.Color := clPurple;
79 daniel-mar 2229
          DXDraw.Surface.Canvas.Textout(9, dxdraw.surfaceheight-41, Format(SLifes, [flife]));
23 daniel-mar 2230
          DXDraw.Surface.Canvas.Font.Color := clFuchsia;
79 daniel-mar 2231
          DXDraw.Surface.Canvas.Textout(10, dxdraw.surfaceheight-40, Format(SLifes, [flife]));
3 daniel-mar 2232
        end;
23 daniel-mar 2233
        if Flife = 1 then BlinkUpdate;
2234
      end;
37 daniel-mar 2235
      {$ENDREGION}
2236
 
2237
      {$REGION 'Anzeige Einheiten und Boss Leben'}
2238
 
2239
      tmpEnemyAnzeige := EnemyCounter{Auf Bildschirm} + FRestEnemies{In der Warteschlange};
90 daniel-mar 2240
      if Assigned(FBoss) and (FBoss.State<>pesDeadVanished) then Dec(tmpEnemyAnzeige);
37 daniel-mar 2241
 
83 daniel-mar 2242
      if Assigned(FBoss) and (FBoss.Life>0) then
23 daniel-mar 2243
      begin
37 daniel-mar 2244
        if (tmpEnemyAnzeige>0) then
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-81, Format(SBossLifes, [FBoss.Life]));
79 daniel-mar 2248
          DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, Format(SEinheiten, [tmpEnemyAnzeige]));
23 daniel-mar 2249
          DXDraw.Surface.Canvas.Font.Color := clLime;
83 daniel-mar 2250
          DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-80, Format(SBossLifes, [FBoss.Life]));
79 daniel-mar 2251
          DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, Format(SEinheiten, [tmpEnemyAnzeige]));
50 daniel-mar 2252
        end
2253
        else
3 daniel-mar 2254
        begin
23 daniel-mar 2255
          DXDraw.Surface.Canvas.Font.Color := clGreen;
83 daniel-mar 2256
          DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, Format(SBossLifes, [FBoss.Life]));
23 daniel-mar 2257
          DXDraw.Surface.Canvas.Font.Color := clLime;
83 daniel-mar 2258
          DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, Format(SBossLifes, [FBoss.Life]));
3 daniel-mar 2259
        end;
50 daniel-mar 2260
      end
83 daniel-mar 2261
      else if tmpEnemyAnzeige>0 then
23 daniel-mar 2262
      begin
2263
        DXDraw.Surface.Canvas.Font.Color := clGreen;
79 daniel-mar 2264
        DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-191, dxdraw.surfaceheight-41, Format(SEinheiten, [tmpEnemyAnzeige]));
23 daniel-mar 2265
        DXDraw.Surface.Canvas.Font.Color := clLime;
79 daniel-mar 2266
        DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-190, dxdraw.surfaceheight-40, Format(SEinheiten, [tmpEnemyAnzeige]));
23 daniel-mar 2267
      end;
37 daniel-mar 2268
      {$ENDREGION}
2269
 
2270
      {$REGION 'Anzeige Mission erfolgreich/gescheitert'}
83 daniel-mar 2271
      if (EnemyCounter=0) and (FRestEnemies=0) then
23 daniel-mar 2272
      begin
2273
        DXDraw.Surface.Canvas.Font.Color := clGreen;
83 daniel-mar 2274
        DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, SMissionSuccessful);
23 daniel-mar 2275
        DXDraw.Surface.Canvas.Font.Color := clLime;
83 daniel-mar 2276
        DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, SMissionSuccessful);
23 daniel-mar 2277
        DXDraw.Surface.Canvas.Release;
35 daniel-mar 2278
        Sleep(1);
23 daniel-mar 2279
        inc(FCounter);
2280
        if FCounter>150{200} then PlayerSprite.FlyAway;
2281
      end;
37 daniel-mar 2282
      {$ENDREGION}
3 daniel-mar 2283
    end
2284
    else
2285
    begin
23 daniel-mar 2286
      DXDraw.Surface.Canvas.Font.Color := clMaroon;
79 daniel-mar 2287
      DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-251, dxdraw.surfaceheight-41, SMissionFailed);
23 daniel-mar 2288
      DXDraw.Surface.Canvas.Font.Color := clRed;
79 daniel-mar 2289
      DXDraw.Surface.Canvas.Textout(dxdraw.surfacewidth-250, dxdraw.surfaceheight-40, SMissionFailed);
3 daniel-mar 2290
    end;
23 daniel-mar 2291
    DXDraw.Surface.Canvas.Release;
3 daniel-mar 2292
  end;
2293
end;
2294
 
2295
procedure TMainForm.SceneGameOver;
83 daniel-mar 2296
resourcestring
2297
  SGameOver = 'Game Over!';
3 daniel-mar 2298
begin
2299
  DXDraw.Surface.Fill(0);
23 daniel-mar 2300
 
2301
  FNotSave := true;
2302
  Cheat.enabled := false;
2303
  GamePause.enabled := false;
2304
  Neustart.enabled := false;
2305
  Brush.Style := bsClear;
2306
  DXDraw.Surface.Canvas.Font.Size := 35;
2307
  DXDraw.Surface.Canvas.Font.Color := clMaroon;
83 daniel-mar 2308
  DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-127, 98, SGameOver);
23 daniel-mar 2309
  DXDraw.Surface.Canvas.Font.Color := clRed;
83 daniel-mar 2310
  DXDraw.Surface.Canvas.Textout((dxdraw.surfacewidth div 2)-125, 100, SGameOver);
23 daniel-mar 2311
  if (FBlink div 300) mod 2=0 then
3 daniel-mar 2312
  begin
23 daniel-mar 2313
    DXDraw.Surface.Canvas.Font.Size := 30;
2314
    DXDraw.Surface.Canvas.Font.Color := clOlive;
83 daniel-mar 2315
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, SWeiterMitLeertaste);
23 daniel-mar 2316
    DXDraw.Surface.Canvas.Font.Color := clYellow;
83 daniel-mar 2317
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, SWeiterMitLeertaste);
3 daniel-mar 2318
  end;
23 daniel-mar 2319
  BlinkUpdate;
2320
  DXDraw.Surface.Canvas.Release;
2321
 
20 daniel-mar 2322
  // Weiter mit Leertaste oder Enter
2323
  if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
3 daniel-mar 2324
  begin
31 daniel-mar 2325
    PlaySound(smsSceneMov, False);
3 daniel-mar 2326
    PalleteAnim(RGBQuad(0, 0, 0), 300);
2327
    Sleep(200);
2328
    StartScene(gsTitle);
2329
  end;
2330
end;
2331
 
2332
procedure TMainForm.SceneWin;
83 daniel-mar 2333
resourcestring
2334
  SGewonnen = 'Gewonnen!';
3 daniel-mar 2335
begin
2336
  DXDraw.Surface.Fill(0);
23 daniel-mar 2337
 
2338
  FNotSave := true;
2339
  Cheat.enabled := false;
2340
  GamePause.enabled := false;
2341
  Neustart.enabled := false;
2342
 
2343
  DXDraw.Surface.Canvas.Brush.Style := bsClear;
2344
  DXDraw.Surface.Canvas.Font.Size := 35;
2345
  DXDraw.Surface.Canvas.Font.Color := clMaroon;
83 daniel-mar 2346
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-127, 98, SGewonnen);
23 daniel-mar 2347
  DXDraw.Surface.Canvas.Font.Color := clRed;
83 daniel-mar 2348
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-125, 100, SGewonnen);
23 daniel-mar 2349
  if (FBlink div 300) mod 2=0 then
3 daniel-mar 2350
  begin
23 daniel-mar 2351
    DXDraw.Surface.Canvas.Font.Size := 30;
2352
    DXDraw.Surface.Canvas.Font.Color := clOlive;
83 daniel-mar 2353
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, SWeiterMitLeertaste);
23 daniel-mar 2354
    DXDraw.Surface.Canvas.Font.Color := clYellow;
83 daniel-mar 2355
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, SWeiterMitLeertaste);
3 daniel-mar 2356
  end;
23 daniel-mar 2357
  BlinkUpdate;
2358
  DXDraw.Surface.Canvas.Release;
2359
 
25 daniel-mar 2360
  // Weiter mit Leertaste oder Enter
2361
  if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
3 daniel-mar 2362
  begin
31 daniel-mar 2363
    PlaySound(smsSceneMov, False);
3 daniel-mar 2364
    PalleteAnim(RGBQuad(0, 0, 0), 300);
2365
    Sleep(200);
2366
    StartScene(gsTitle);
2367
  end;
2368
end;
2369
 
2370
procedure TMainForm.StartSceneNewLevel;
2371
begin
2372
  sleep(500);
46 daniel-mar 2373
  FNotSave := true; // Wenn man speichert, würde man LevelAdventTable vom vorherigen Level machen, das wär müll!
3 daniel-mar 2374
  Cheat.enabled := false;
2375
  Neustart.enabled := false;
2376
  GamePause.enabled := false;
2377
  GameStart.enabled := true;
2378
  Spielgeschwindigkeit.enabled := false;
2379
  Spielgeschwindigkeit.enabled := false;
61 daniel-mar 2380
  if ((FGameMode=gmLevels) and not GetLevelFileName(FLevel,false).found)
40 daniel-mar 2381
     // or ((FGameMode=gmRandom) and (FLevel > 25))
2382
     or (FLevel > MaxPossibleLevels) then
3 daniel-mar 2383
  begin
2384
    //PlaySound('SceneMov', False);
2385
    PalleteAnim(RGBQuad(0, 0, 0), 300);
2386
    Sleep(200);
2387
    StartScene(gsWin);
2388
    exit;
2389
  end;
31 daniel-mar 2390
  MusicSwitchTrack(smmScene);
3 daniel-mar 2391
end;
2392
 
2393
procedure TMainForm.EndSceneNewLevel;
2394
begin
2395
  {  Ende NewLevel  }
2396
end;
2397
 
2398
procedure TMainForm.SceneNewLevel;
90 daniel-mar 2399
resourcestring
2400
  SLevelScene = 'Level %d';
3 daniel-mar 2401
begin
2402
  DXDraw.Surface.Fill(0);
23 daniel-mar 2403
 
2404
  DXDraw.Surface.Canvas.Brush.Style := bsClear;
2405
  DXDraw.Surface.Canvas.Font.Size := 40;
2406
  DXDraw.Surface.Canvas.Font.Color := clMaroon;
90 daniel-mar 2407
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(83+(length(inttostr(flevel))*22)), 98, Format(SLevelScene, [flevel]));
23 daniel-mar 2408
  DXDraw.Surface.Canvas.Font.Color := clRed;
90 daniel-mar 2409
  DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-(81+(length(inttostr(flevel))*22)), 100, Format(SLevelScene, [flevel]));
23 daniel-mar 2410
  if (FBlink div 300) mod 2=0 then
3 daniel-mar 2411
  begin
23 daniel-mar 2412
    DXDraw.Surface.Canvas.Font.Size := 30;
2413
    DXDraw.Surface.Canvas.Font.Color := clOlive;
90 daniel-mar 2414
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-187, dxdraw.surfaceheight-117, SWeiterMitLeertaste);
23 daniel-mar 2415
    DXDraw.Surface.Canvas.Font.Color := clYellow;
90 daniel-mar 2416
    DXDraw.Surface.Canvas.Textout((dxdraw.surfaceWidth div 2)-185, dxdraw.surfaceheight-115, SWeiterMitLeertaste);
3 daniel-mar 2417
  end;
23 daniel-mar 2418
  BlinkUpdate;
2419
  DXDraw.Surface.Canvas.Release;
2420
 
25 daniel-mar 2421
  // Weiter mit Leertaste oder Enter
2422
  if (isButton1 in DXInput.States) or (isButton2 in DXInput.States) then
3 daniel-mar 2423
  begin
31 daniel-mar 2424
    PlaySound(smsSceneMov, False);
3 daniel-mar 2425
    PalleteAnim(RGBQuad(0, 0, 0), 300);
2426
    Sleep(200);
2427
    StartScene(gsMain);
2428
  end;
2429
end;
2430
 
2431
procedure TMainForm.OptionMusicClick(Sender: TObject);
2432
begin
2433
  OptionMusic.Checked := not OptionMusic.Checked;
2434
  if OptionMusic.Checked then
2435
  begin
19 daniel-mar 2436
    MusicSwitchTrack(FMusic)
3 daniel-mar 2437
  end
2438
  else
2439
  begin
19 daniel-mar 2440
    StopMusic(FMusic);
3 daniel-mar 2441
  end;
2442
  WriteOptions;
2443
end;
2444
 
31 daniel-mar 2445
procedure TMainForm.PlayMusic(Name: TSpaceMissionMusicTrack);
3 daniel-mar 2446
begin
19 daniel-mar 2447
  if not OptionMusic.checked then exit;
24 daniel-mar 2448
  if Ord(Name) > dxmusic.Midis.Count then exit;
19 daniel-mar 2449
  dxmusic.Midis.Items[Ord(Name)-1].Play;
2450
end;
3 daniel-mar 2451
 
31 daniel-mar 2452
procedure TMainForm.StopMusic(Name: TSpaceMissionMusicTrack);
19 daniel-mar 2453
begin
31 daniel-mar 2454
  if Name = smmNone then exit;
24 daniel-mar 2455
  if Ord(Name) > dxmusic.Midis.Count then exit;
19 daniel-mar 2456
  dxmusic.Midis.Items[Ord(Name)-1].Stop;
2457
end;
2458
 
31 daniel-mar 2459
procedure TMainForm.ResumeMusic(Name: TSpaceMissionMusicTrack);
3 daniel-mar 2460
begin
2461
  if not OptionMusic.checked then exit;
24 daniel-mar 2462
  if Ord(Name) > dxmusic.Midis.Count then exit;
19 daniel-mar 2463
  dxmusic.Midis.Items[Ord(Name)-1].Play; // TODO: how to pause/resume instead play/stop
3 daniel-mar 2464
end;
2465
 
31 daniel-mar 2466
procedure TMainForm.PauseMusic(Name: TSpaceMissionMusicTrack);
19 daniel-mar 2467
begin
31 daniel-mar 2468
  if Name = smmNone then exit;
24 daniel-mar 2469
  if Ord(Name) > dxmusic.Midis.Count then exit;
19 daniel-mar 2470
  dxmusic.Midis.Items[Ord(Name)-1].Stop; // TODO: how to pause/resume instead play/stop
2471
end;
2472
 
3 daniel-mar 2473
procedure TMainForm.SpielstandClick(Sender: TObject);
2474
begin
2475
  speicherungform.showmodal;
2476
end;
2477
 
38 daniel-mar 2478
procedure TMainForm.LevelNeuStarten;
3 daniel-mar 2479
begin
38 daniel-mar 2480
  FNextScene := gsNewLevel;
40 daniel-mar 2481
  FLife := FLifeAtLevelStart;
2482
  FScore := FScoreAtLevelStart;
3 daniel-mar 2483
end;
2484
 
38 daniel-mar 2485
procedure TMainForm.NeustartClick(Sender: TObject);
2486
begin
2487
  LevelNeuStarten;
2488
end;
2489
 
3 daniel-mar 2490
procedure TMainForm.LeichtClick(Sender: TObject);
2491
begin
2492
  leicht.checked := true;
81 daniel-mar 2493
  FSpeed := SpeedEasy;
3 daniel-mar 2494
  writeoptions;
2495
end;
2496
 
2497
procedure TMainForm.MittelClick(Sender: TObject);
2498
begin
2499
  mittel.checked := true;
81 daniel-mar 2500
  FSpeed := SpeedMedium;
3 daniel-mar 2501
  writeoptions;
2502
end;
2503
 
2504
procedure TMainForm.SchwerClick(Sender: TObject);
2505
begin
2506
  schwer.checked := true;
81 daniel-mar 2507
  FSpeed := SpeedHard;
3 daniel-mar 2508
  writeoptions;
2509
end;
2510
 
80 daniel-mar 2511
procedure TMainForm.MasterClick(Sender: TObject);
2512
begin
2513
  master.checked := true;
81 daniel-mar 2514
  FSpeed := SpeedMaster;
80 daniel-mar 2515
  writeoptions;
2516
end;
2517
 
3 daniel-mar 2518
procedure TMainForm.FormShow(Sender: TObject);
54 daniel-mar 2519
resourcestring
2520
  SFileError = 'Die Datei kann von SpaceMission nicht geöffnet werden!';
2521
var
2522
  SavGame: TSaveData;
3 daniel-mar 2523
begin
7 daniel-mar 2524
  if Assigned(SplashForm) then
2525
  begin
2526
    SplashForm.Hide;
2527
    FreeAndNil(SplashForm);
2528
  end;
3 daniel-mar 2529
 
2530
  dxtimer.Enabled := true;
2531
  dxtimer.ActiveOnly := true;
54 daniel-mar 2532
 
2533
  ResetLevelData;
2534
  if (paramcount > 0) and (fileexists(paramstr(1))) and (ExtractFileExt(paramstr(1)).ToLower = '.sav') then
2535
  begin
2536
    SavGame := TSaveData.Create;
2537
    try
2538
      try
2539
        SavGame.LoadFromFile(paramstr(1));
2540
        FScore := SavGame.Score;
2541
        FLife := SavGame.Life;
2542
        FLevel := SavGame.Level;
2543
        FGameMode := SavGame.GameMode;
2544
        FLevelDataAlreadyLoaded := true; // do not call NewLevel() in StartSceneMain
2545
        if Assigned(SavGame.LevelData) then
2546
        begin
2547
          LevelData.Assign(SavGame.LevelData);
2548
        end;
2549
      except
2550
        on E: Exception do
2551
        begin
2552
          showmessage(SFileError + ' ' +E.Message);
2553
          GameStartClick(GameStart);
2554
          exit;
2555
        end;
2556
      end;
2557
    finally
2558
      FreeAndNil(SavGame);
2559
    end;
2560
    //FNextScene := gsNewLevel;
2561
    StartScene(gsNewLevel);
2562
    exit;
2563
  end;
3 daniel-mar 2564
end;
2565
 
2566
procedure TMainForm.InformationenClick(Sender: TObject);
2567
begin
2568
  dxtimer.enabled := false;
2569
  InfoForm.showmodal;
2570
  if not mainform.gamepause.checked then mainform.dxtimer.enabled := true;
2571
end;
2572
 
2573
procedure TMainForm.CheatClick(Sender: TObject);
2574
begin
2575
  CheatForm.showmodal;
2576
end;
2577
 
2578
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
2579
begin
19 daniel-mar 2580
  if optionMusic.checked then StopMusic(FMusic);
3 daniel-mar 2581
  SpriteEngine.Engine.Clear;
2582
  dxsound.Finalize;
2583
  dxinput.Destroy;
2584
  DXTimer.Enabled := False;
2585
end;
2586
 
2587
procedure TMainForm.FormDestroy(Sender: TObject);
2588
begin
23 daniel-mar 2589
  FreeAndNil(imagelist);
2590
  FreeAndNil(spriteengine);
2591
  FreeAndNil(dxdraw);
2592
  FreeAndNil(wavelist);
56 daniel-mar 2593
  FreeAndNil(dxmusic);
23 daniel-mar 2594
  FreeAndNil(dxsound);
2595
  //FreeAndNil(dxinput);
2596
  FreeAndNil(dxtimer);
7 daniel-mar 2597
  DeleteCriticalSection(TimerCS);
23 daniel-mar 2598
  FreeAndNil(LevelData);
3 daniel-mar 2599
end;
2600
 
36 daniel-mar 2601
procedure PostKeyEx32(key: Word; const shift: TShiftState; specialkey: Boolean);
2602
{************************************************************
2603
* Procedure PostKeyEx32
2604
*
2605
* Parameters:
2606
*  key    : virtual keycode of the key to send. For printable
2607
*           keys this is simply the ANSI code (Ord(character)).
2608
*  shift  : state of the modifier keys. This is a set, so you
2609
*           can set several of these keys (shift, control, alt,
2610
*           mouse buttons) in tandem. The TShiftState type is
2611
*           declared in the Classes Unit.
2612
*  specialkey: normally this should be False. Set it to True to
2613
*           specify a key on the numeric keypad, for example.
2614
* Description:
2615
*  Uses keybd_event to manufacture a series of key events matching
2616
*  the passed parameters. The events go to the control with focus.
2617
*  Note that for characters key is always the upper-case version of
2618
*  the character. Sending without any modifier keys will result in
2619
*  a lower-case character, sending it with [ssShift] will result
2620
*  in an upper-case character!
2621
// Code by P. Below
2622
************************************************************}
2623
type
2624
  TShiftKeyInfo = record
2625
    shift: Byte;
2626
    vkey: Byte;
2627
  end;
2628
  byteset = set of 0..7;
2629
const
2630
  shiftkeys: array [1..3] of TShiftKeyInfo =
2631
    ((shift: Ord(ssCtrl); vkey: VK_CONTROL),
2632
    (shift: Ord(ssShift); vkey: VK_SHIFT),
2633
    (shift: Ord(ssAlt); vkey: VK_MENU));
2634
var
2635
  flag: DWORD;
2636
  bShift: ByteSet absolute shift;
2637
  i: Integer;
2638
begin
2639
  for i := 1 to 3 do
2640
  begin
2641
    if shiftkeys[i].shift in bShift then
2642
      keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0), 0, 0);
2643
  end; { For }
2644
  if specialkey then
2645
    flag := KEYEVENTF_EXTENDEDKEY
2646
  else
2647
    flag := 0;
2648
 
2649
  keybd_event(key, MapvirtualKey(key, 0), flag, 0);
2650
  flag := flag or KEYEVENTF_KEYUP;
2651
  keybd_event(key, MapvirtualKey(key, 0), flag, 0);
2652
 
2653
  for i := 3 downto 1 do
2654
  begin
2655
    if shiftkeys[i].shift in bShift then
2656
      keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0),
2657
        KEYEVENTF_KEYUP, 0);
2658
  end; { For }
2659
end; { PostKeyEx32 }
2660
 
2661
procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
2662
  Shift: TShiftState);
2663
begin
2664
  if Key = VK_ESCAPE then
2665
  begin
2666
    // TODO: Unfortunately, you cannot see if it is already popup. It would be great if ESC closes the main menu...
2667
    Key := 0;
2668
    PostKeyEx32(Ord('S'), [ssAlt], False);
2669
  end;
2670
end;
2671
 
3 daniel-mar 2672
end.
2673