Subversion Repositories spacemission

Rev

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

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