Subversion Repositories spacemission

Rev

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