Subversion Repositories spacemission

Rev

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