Subversion Repositories spacemission

Rev

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