Subversion Repositories spacemission

Rev

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