Subversion Repositories spacemission

Rev

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

Rev Author Line No. Line
1 daniel-mar 1
unit LevMain;
2
 
3
interface
4
 
5
uses
6
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, MMSystem,
7
  Dialogs, StdCtrls, ExtCtrls, Menus, DIB, DXClass, DXSprite, DXDraws,
6 daniel-mar 8
  DXSounds, Spin, ComCtrls{$IF CompilerVersion >= 23.0}, System.UITypes,
54 daniel-mar 9
  WinAPI.DirectDraw{$ENDIF}, DirectX, ComLevelReader, Global, IOUtils;
1 daniel-mar 10
 
11
type
12
  TMainForm = class(TDXForm)
13
    MainMenu: TMainMenu;
14
    Spiel: TMenuItem;
15
    Beenden: TMenuItem;
16
    Hilfe: TMenuItem;
17
    Leer1: TMenuItem;
18
    Level: TMenuItem;
19
    Informationen: TMenuItem;
20
    Enemy1: TRadioButton;
21
    Enemy2: TRadioButton;
22
    Enemy3: TRadioButton;
23
    Enemy4: TRadioButton;
24
    Enemy5: TRadioButton;
25
    Enemy6: TRadioButton;
26
    Enemy7: TRadioButton;
27
    ScrollBar: TScrollBar;
28
    Bevel1: TBevel;
29
    Bevel2: TBevel;
30
    SelLabel: TLabel;
31
    SelPanel: TPanel;
32
    Bevel3: TBevel;
33
    SLabel1a: TLabel;
34
    SLabel2a: TLabel;
35
    SLabel1b: TLabel;
36
    SLabel2b: TLabel;
37
    SLabel0: TLabel;
38
    Neu: TMenuItem;
39
    Image1: TImage;
40
    SLabel3a: TLabel;
41
    SLabel3b: TLabel;
42
    SLabel4a: TLabel;
43
    SLabel4b: TLabel;
44
    LivesLabel: TLabel;
45
    StatusBar: TStatusBar;
46
    N1: TMenuItem;
47
    Spielfelderweitern1: TMenuItem;
24 daniel-mar 48
    SidePanel: TPanel;
49
    LivesEdit: TSpinEdit;
30 daniel-mar 50
    AlleLeveldateienaktualisieren1: TMenuItem;
54 daniel-mar 51
    N2: TMenuItem;
52
    Leveltesten1: TMenuItem;
63 daniel-mar 53
    Hilfe1: TMenuItem;
54
    N3: TMenuItem;
55
    AufUpdatesprfen1: TMenuItem;
1 daniel-mar 56
    procedure DXDrawFinalize(Sender: TObject);
57
    procedure DXDrawInitialize(Sender: TObject);
58
    procedure FormCreate(Sender: TObject);
59
    procedure DXTimerTimer(Sender: TObject; LagCount: Integer);
60
    procedure BeendenClick(Sender: TObject);
61
    procedure FormDestroy(Sender: TObject);
62
    procedure LevelClick(Sender: TObject);
63
    procedure FormShow(Sender: TObject);
64
    procedure InformationenClick(Sender: TObject);
65
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
66
    procedure DXDrawMouseDown(Sender: TObject; Button: TMouseButton;
67
      Shift: TShiftState; X, Y: Integer);
68
    procedure EnemyClick(Sender: TObject);
69
    procedure NeuClick(Sender: TObject);
70
    procedure DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X,
71
      Y: Integer);
72
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
73
    procedure Spielfelderweitern1Click(Sender: TObject);
74
    procedure ScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode;
75
      var ScrollPos: Integer);
30 daniel-mar 76
    procedure AlleLeveldateienaktualisieren1Click(Sender: TObject);
54 daniel-mar 77
    procedure Leveltesten1Click(Sender: TObject);
63 daniel-mar 78
    procedure Hilfe1Click(Sender: TObject);
79
    procedure AufUpdatesprfen1Click(Sender: TObject);
54 daniel-mar 80
  private
81
    function GetTestlevelFilename: string;
1 daniel-mar 82
  public
83
    { VCL-Ersatz }
84
    spriteengine: tdxspriteengine;
85
    dxtimer: tdxtimer;
86
    imagelist: tdximagelist;
87
    dxdraw: tdxdraw;
88
    { Variablen }
89
    FMenuItem: integer;
27 daniel-mar 90
    LevData: TLevelData;
1 daniel-mar 91
    ScrollP: integer;
92
    AltScrollPos: integer;
93
    Boss: boolean;
94
    LevChanged: boolean;
95
    NumEnemys: integer;
24 daniel-mar 96
    function SelectedEnemyType: TEnemyType;
31 daniel-mar 97
    { Grafik-Routinen }
98
    function GetSpriteGraphic(Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
1 daniel-mar 99
    { Level-Routinen }
27 daniel-mar 100
    procedure EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer);
1 daniel-mar 101
    procedure DestroyLevel;
30 daniel-mar 102
    procedure RefreshFromLevData;
1 daniel-mar 103
    procedure AnzeigeAct;
104
    { Initialisiations-Routinen }
105
    procedure DXInit;
106
    procedure ProgramInit;
107
    { Farb-Routinen }
108
    function ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
109
    procedure PalleteAnim(Col: TRGBQuad; Time: Integer);
110
  end;
111
 
112
var
113
  MainForm: TMainForm;
114
 
115
implementation
116
 
117
uses
63 daniel-mar 118
  LevSplash, LevSpeicherung, ComInfo, LevOptions, ShellAPI, ComHilfe;
1 daniel-mar 119
 
120
{$R *.DFM}
121
 
122
type
123
  TBackground = class(TBackgroundSprite)
24 daniel-mar 124
  strict protected
1 daniel-mar 125
    procedure DoMove(MoveCount: Integer); override;
126
  end;
127
 
128
  TEnemy = class(TImageSprite)
24 daniel-mar 129
  strict private
130
    FLives: integer;
131
    FEnemyType: TEnemyType;
132
    FXCor: integer;
133
    FCorInit: boolean;
134
  strict protected
1 daniel-mar 135
    procedure DoMove(MoveCount: Integer); override;
136
  public
24 daniel-mar 137
    constructor Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer); reintroduce;
1 daniel-mar 138
  end;
139
 
24 daniel-mar 140
{ TBackground }
141
 
142
procedure TBackground.DoMove(MoveCount: Integer);
1 daniel-mar 143
begin
24 daniel-mar 144
  X := -(MainForm.ScrollP * RasterW);
1 daniel-mar 145
end;
146
 
24 daniel-mar 147
{ TEnemy }
148
 
1 daniel-mar 149
procedure TEnemy.DoMove(MoveCount: Integer);
150
begin
24 daniel-mar 151
  if not FCorInit then
1 daniel-mar 152
  begin
24 daniel-mar 153
    FXCor := trunc(x) + (MainForm.ScrollP * RasterW);
154
    FCorInit := true;
1 daniel-mar 155
  end;
27 daniel-mar 156
  if MainForm.LevData.IndexOfEnemy(FXCor, integer(round(Y)), FEnemyType, FLives) = -1 then dead;
24 daniel-mar 157
  X := FXCor - (MainForm.ScrollP * RasterW);
1 daniel-mar 158
end;
159
 
24 daniel-mar 160
constructor TEnemy.Create(AParent: TSprite; AEnemyType: TEnemyType; ALives: Integer);
1 daniel-mar 161
begin
24 daniel-mar 162
  inherited Create(AParent);
31 daniel-mar 163
  if AEnemyType = etEnemyAttacker then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker);
164
  if AEnemyType = etEnemyAttacker2 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker2);
165
  if AEnemyType = etEnemyAttacker3 then Image := MainForm.GetSpriteGraphic(smgEnemyAttacker3);
166
  if AEnemyType = etEnemyMeteor then Image := MainForm.GetSpriteGraphic(smgEnemyMeteor);
167
  if AEnemyType = etEnemyUFO then Image := MainForm.GetSpriteGraphic(smgEnemyDisk);
168
  if AEnemyType = etEnemyUFO2 then Image := MainForm.GetSpriteGraphic(smgEnemyDisk2);
169
  if AEnemyType = etEnemyBoss then Image := MainForm.GetSpriteGraphic(smgEnemyBoss);
1 daniel-mar 170
 
24 daniel-mar 171
  if AEnemyType = etEnemyMeteor then FLives := 0 else FLives := ALives;
172
  FEnemyType := AEnemyType;
1 daniel-mar 173
  Width := Image.Width;
174
  Height := Image.Height;
175
  PixelCheck := True;
176
end;
177
 
24 daniel-mar 178
{ TMainForm }
179
 
180
procedure TMainForm.DXInit;
181
begin
31 daniel-mar 182
  Imagelist.Items.LoadFromFile(OwnDirectory+'DirectX\Graphics.dxg');
24 daniel-mar 183
  ImageList.Items.MakeColorTable;
184
  DXDraw.ColorTable := ImageList.Items.ColorTable;
185
  DXDraw.DefColorTable := ImageList.Items.ColorTable;
186
  DXDraw.UpdatePalette;
187
  DXDraw.Initialize;
188
end;
189
 
1 daniel-mar 190
procedure TMainForm.FormCreate(Sender: TObject);
24 daniel-mar 191
resourcestring
192
  SFileError = 'Die Datei kann von SpaceMission nicht geöffnet werden!';
1 daniel-mar 193
begin
194
  { VCL-Ersatz start }
195
  dxtimer := tdxtimer.create(self);
196
  dxtimer.Interval := 100;
197
  dxtimer.ActiveOnly := false;
198
  dxtimer.Enabled := false;
199
  dxtimer.OnTimer := DxTimerTimer;
200
 
201
  dxdraw := tdxdraw.Create(self);
202
  dxdraw.Parent := self;
203
  dxdraw.Left := 0;
204
  dxdraw.Top := 0;
24 daniel-mar 205
  dxdraw.Width := SidePanel.Left;
206
  dxdraw.Height := ScrollBar.Top;
1 daniel-mar 207
  dxdraw.AutoInitialize := False;
208
  dxdraw.AutoSize := False;
209
  dxdraw.Color := clBlack;
24 daniel-mar 210
  (*
1 daniel-mar 211
  dxdraw.Display.BitCount := 24;
212
  dxdraw.Display.FixedBitCount := False;
213
  dxdraw.Display.FixedRatio := False;
214
  dxdraw.Display.FixedSize := False;
215
  dxdraw.Display.Height := 600;
216
  dxdraw.Display.Width := 800;
24 daniel-mar 217
  *)
4 daniel-mar 218
  dxdraw.Options := [doAllowReboot, doWaitVBlank, doAllowPalette256, doCenter, {doRetainedMode,} doHardware, doSelectDriver];
1 daniel-mar 219
  dxdraw.OnFinalize := DXDrawFinalize;
220
  dxdraw.OnInitialize := DXDrawInitialize;
221
  dxdraw.ParentShowHint := False;
222
  dxdraw.ShowHint := False;
223
  dxdraw.TabOrder := 0;
224
  dxdraw.OnMouseDown := DXDrawMouseDown;
225
  dxdraw.OnMouseMove := DXDrawMouseMove;
226
 
227
  spriteengine := tdxspriteengine.create(self);
228
  spriteengine.DXDraw := dxdraw;
229
 
230
  imagelist := tdximagelist.create(self);
231
  imagelist.DXDraw := dxdraw;
232
 
233
  { VCL-Ersatz ende }
234
 
40 daniel-mar 235
  LivesEdit.MinValue := 1;
236
  LivesEdit.MaxValue := MaxPossibleEnemyLives;
237
  LivesEdit.Value := 1;
238
 
24 daniel-mar 239
  Enemy1.Checked := true;
240
  EnemyClick(Enemy1);
1 daniel-mar 241
  // Leeres Level am Anfang braucht keine Beenden-Bestätigung.
242
  // LevChanged := true;
2 daniel-mar 243
 
244
  //Application.Title := 'SpaceMission '+ProgramVersion+' - Leveleditor';
245
  Caption := 'SpaceMission '+ProgramVersion+' - Leveleditor';
1 daniel-mar 246
  DXInit;
30 daniel-mar 247
  LevData := TLevelData.create;
248
  ProgramInit;
249
  DestroyLevel;
40 daniel-mar 250
  if (paramcount > 0) and (fileexists(paramstr(1))) and (ExtractFileExt(paramstr(1)).ToLower = '.lev') then
1 daniel-mar 251
  begin
14 daniel-mar 252
    try
44 daniel-mar 253
      LevData.RasterErzwingen := true;
40 daniel-mar 254
      LevData.LoadFromFile(paramstr(1));
30 daniel-mar 255
    except
256
      on E: Exception do
257
      begin
258
        showmessage(SFileError + ' ' +E.Message);
259
        DestroyLevel;
14 daniel-mar 260
      end;
1 daniel-mar 261
    end;
30 daniel-mar 262
    RefreshFromLevData;
263
    LevChanged := false;
264
    AnzeigeAct;
1 daniel-mar 265
  end;
266
end;
267
 
268
procedure TMainForm.FormDestroy(Sender: TObject);
54 daniel-mar 269
var
270
  tmp: string;
1 daniel-mar 271
begin
42 daniel-mar 272
  FreeAndNil(dxdraw);
40 daniel-mar 273
  FreeAndNil(LevData);
274
  //FreeAndNil(spriteengine);
275
  FreeAndNil(dxtimer);
276
  FreeAndNil(imagelist);
54 daniel-mar 277
  tmp := GetTestlevelFilename;
278
 
279
  // SpaceMission.exe only loads a file once, so we can delete any test level
280
  if FileExists(tmp) then DeleteFile(GetTestlevelFilename);
1 daniel-mar 281
end;
282
 
283
procedure TMainForm.BeendenClick(Sender: TObject);
284
begin
285
  close;
286
end;
287
 
288
procedure TMainForm.DXDrawInitialize(Sender: TObject);
289
begin
42 daniel-mar 290
  if Assigned(DXTimer) then DXTimer.Enabled := True;
1 daniel-mar 291
end;
292
 
293
procedure TMainForm.DXDrawFinalize(Sender: TObject);
294
begin
42 daniel-mar 295
  if Assigned(DXTimer) then DXTimer.Enabled := False;
1 daniel-mar 296
end;
297
 
298
procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
299
begin
300
  if not DXDraw.CanDraw then exit;
301
  LagCount := 1000 div 60;
302
  SpriteEngine.Move(LagCount);
303
  SpriteEngine.Dead;
304
  DxDraw.Surface.Fill(0);
305
  SpriteEngine.Draw;
306
  DXDraw.Flip;
307
end;
308
 
309
function TMainForm.ComposeColor(Dest, Src: TRGBQuad; Percent: Integer): TRGBQuad;
310
begin
311
  with Result do
312
  begin
313
    rgbRed := Src.rgbRed+((Dest.rgbRed-Src.rgbRed)*Percent div 256);
314
    rgbGreen := Src.rgbGreen+((Dest.rgbGreen-Src.rgbGreen)*Percent div 256);
315
    rgbBlue := Src.rgbBlue+((Dest.rgbBlue-Src.rgbBlue)*Percent div 256);
316
    rgbReserved := 0;
317
  end;
318
end;
319
 
320
procedure TMainForm.PalleteAnim(Col: TRGBQuad; Time: Integer);
321
var
322
  i: Integer;
323
  t, t2: DWORD;
324
  ChangePalette: Boolean;
325
  c: Integer;
326
begin
327
  if DXDraw.Initialized then
328
  begin
329
    c := DXDraw.Surface.ColorMatch(RGB(Col.rgbRed, Col.rgbGreen, Col.rgbBlue));
330
    ChangePalette := False;
331
    if DXDraw.CanPaletteAnimation then
332
    begin
333
      t := GetTickCount;
334
      while Abs(GetTickCount-t)<Time do
335
      begin
336
        t2 := Trunc(Abs(GetTickCount-t)/Time*255);
337
        for i := 0 to 255 do
338
          DXDraw.ColorTable[i] := ComposeColor(Col, DXDraw.DefColorTable[i], t2);
339
        DXDraw.UpdatePalette;
340
        ChangePalette := True;
341
      end;
342
    end else
343
      Sleep(Time);
344
    for i := 0 to 4 do
345
    begin
346
      DXDraw.Surface.Fill(c);
347
      DXDraw.Flip;
348
    end;
349
    if ChangePalette then
350
    begin
351
      DXDraw.ColorTable := DXDraw.DefColorTable;
352
      DXDraw.UpdatePalette;
353
    end;
354
    DXDraw.Surface.Fill(c);
355
    DXDraw.Flip;
356
  end;
357
end;
358
 
359
procedure TMainForm.ProgramInit;
360
{var
361
  i, j: Integer;}
362
begin
363
  sleep(500);
364
  //PlayerSprite
365
  with TBackground.Create(SpriteEngine.Engine) do
366
  begin
367
    SetMapSize(1, 1);
31 daniel-mar 368
    Image := MainForm.GetSpriteGraphic(smgStar3);
1 daniel-mar 369
    Z := -13;
370
    Y := 40;
371
    Tile := True;
372
  end;
373
  with TBackground.Create(SpriteEngine.Engine) do
374
  begin
375
    SetMapSize(1, 1);
31 daniel-mar 376
    Image := MainForm.GetSpriteGraphic(smgStar2);
1 daniel-mar 377
    Z := -12;
378
    Y := 30;
379
    Tile := True;
380
  end;
381
  with TBackground.Create(SpriteEngine.Engine) do
382
  begin
383
    SetMapSize(1, 1);
31 daniel-mar 384
    Image := MainForm.GetSpriteGraphic(smgStar1);
1 daniel-mar 385
    Z := -11;
386
    Y := 10;
387
    Tile := True;
388
  end;
389
  with TBackground.Create(SpriteEngine.Engine) do
390
  begin
391
    SetMapSize(1, 1);
31 daniel-mar 392
    Image := MainForm.GetSpriteGraphic(smgMatrix);
1 daniel-mar 393
    Z := -10;
394
    Tile := True;
395
  end;
396
  {with TBackground.Create(SpriteEngine.Engine) do
397
  begin
398
    SetMapSize(200, 10);
399
    Y := 10;
400
    Z := -13;
401
    FSpeed := 1 / 2;
402
    Tile := True;
403
    for i := 0 to MapHeight-1 do
404
    begin
405
      for j := 0 to MapWidth-1 do
406
      begin
407
        Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 8);
408
        if Random(100)<95 then Chips[j, i] := -1;
409
      end;
410
    end;
411
  end;
412
  with TBackground.Create(SpriteEngine.Engine) do
413
  begin
414
    SetMapSize(200, 10);
415
    Y := 30;
416
    Z := -12;
417
    FSpeed := 1;
418
    Tile := True;
419
    for i := 0 to MapHeight-1 do
420
    begin
421
      for j := 0 to MapWidth-1 do
422
      begin
423
        Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 4);
424
        if Random(100)<95 then Chips[j, i] := -1;
425
      end;
426
    end;
427
  end;
428
  with TBackground.Create(SpriteEngine.Engine) do
429
  begin
430
    SetMapSize(200, 10);
431
    Y := 40;
432
    Z := -11;
433
    FSpeed := 2;
434
    Tile := True;
435
    for i := 0 to MapHeight-1 do
436
    begin
437
      for j := 0 to MapWidth-1 do
438
      begin
439
        Chips[j, i] := Image.PatternCount-Random(Image.PatternCount div 2);
440
        if Random(100)<95 then Chips[j, i] := -1;
441
      end;
442
    end;
443
  end;}
444
  PalleteAnim(RGBQuad(0, 0, 0), 300);
445
  mainform.Visible := true;
446
end;
447
 
30 daniel-mar 448
procedure TMainForm.RefreshFromLevData;
449
var
450
  i: integer;
451
begin
452
  MainForm.ScrollBar.Max := MainForm.LevData.LevelEditorLength;
453
  for i := 0 to MainForm.LevData.CountEnemies - 1 do
454
  begin
455
    MainForm.EnemyCreateSprite(
456
      MainForm.LevData.EnemyAdventTable[i].x,
457
      MainForm.LevData.EnemyAdventTable[i].y,
458
      MainForm.LevData.EnemyAdventTable[i].enemyType,
459
      MainForm.LevData.EnemyAdventTable[i].lifes
460
    );
461
  end;
462
  MainForm.NumEnemys := MainForm.LevData.CountEnemies;
463
  MainForm.Boss := MainForm.LevData.HasBoss;
464
  AnzeigeAct;
465
end;
466
 
1 daniel-mar 467
procedure TMainForm.LevelClick(Sender: TObject);
468
begin
469
  speicherungform.showmodal;
470
end;
471
 
54 daniel-mar 472
procedure TMainForm.Leveltesten1Click(Sender: TObject);
473
var
474
  sav: TSaveData;
475
  tmp: string;
476
begin
477
  KillTask('SpaceMission.exe');
478
 
479
  sav := TSaveData.Create;
480
  try
481
    sav.Score := 0;
482
    sav.Life := 6;
483
    if Assigned(SpeicherungForm) then
484
      sav.Level := SpeicherungForm.LevelNumber.Value
485
    else
486
      sav.Level := 1;
487
    sav.GameMode := gmLevels;
488
    sav.LevelData := TlevelData.Create;
489
    sav.LevelData.Assign(LevData);
490
    tmp := GetTestlevelFilename;
491
    sav.SaveToFile(tmp);
492
    ShellExecute(Handle, 'open', PChar(OwnDirectory+'SpaceMission.exe'), PChar('"'+tmp+'"'), PChar(OwnDirectory), SW_NORMAL);
493
  finally
494
    FreeAndNil(sav);
495
  end;
496
end;
497
 
1 daniel-mar 498
procedure TMainForm.FormShow(Sender: TObject);
499
begin
40 daniel-mar 500
  if Assigned(SplashForm) then
501
  begin
502
    SplashForm.Hide;
503
    FreeAndNil(SplashForm);
504
  end;
1 daniel-mar 505
 
506
  dxtimer.Enabled := true;
507
  dxtimer.ActiveOnly := true;
508
end;
509
 
31 daniel-mar 510
function TMainForm.GetSpriteGraphic(
511
  Sprite: TSpaceMissionGraphicSprite): TPictureCollectionItem;
512
begin
513
  if (Sprite<>smgNone) and (imagelist.Items.Count >= Ord(Sprite)) then
514
    result := imagelist.Items.Items[Ord(Sprite)-1]
515
  else
516
    result := nil;
517
end;
518
 
54 daniel-mar 519
function TMainForm.GetTestlevelFilename: string;
520
begin
521
  result := IncludeTrailingPathDelimiter(TPath.GetTempPath) + 'SpaceMissionTest.sav';
522
end;
523
 
63 daniel-mar 524
procedure TMainForm.Hilfe1Click(Sender: TObject);
525
begin
526
  HilfeForm.Caption := TMenuItem(Sender).Caption;
527
  HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&&', #1, [rfReplaceAll]);
528
  HilfeForm.Caption := StringReplace(HilfeForm.Caption, '&', '', [rfReplaceAll]);
529
  HilfeForm.Caption := StringReplace(HilfeForm.Caption, #1, '&', [rfReplaceAll]);
530
  HilfeForm.ShowMarkDownHelp(OwnDirectory+'Doku.md');
531
  HilfeForm.ShowModal;
532
end;
533
 
1 daniel-mar 534
procedure TMainForm.InformationenClick(Sender: TObject);
535
begin
3 daniel-mar 536
  mainform.dxtimer.enabled := false;
1 daniel-mar 537
  InfoForm.showmodal;
3 daniel-mar 538
  mainform.dxtimer.enabled := true;
1 daniel-mar 539
end;
540
 
541
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
542
begin
543
  SpriteEngine.Engine.Clear;
544
  DXTimer.Enabled := False;
545
end;
546
 
547
procedure TMainForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton;
548
  Shift: TShiftState; X, Y: Integer);
549
var
550
  i, j, k, l, ex, ey: integer;
551
  ok, breaked: boolean;
552
begin
553
  ex := trunc(x/RasterW) * RasterW;
554
  ey := trunc(y/RasterH) * RasterH;
27 daniel-mar 555
  EnemyCreateSprite(ex, ey, SelectedEnemyType, LivesEdit.Value);
1 daniel-mar 556
  breaked := false;
557
  { Setzen }
558
  if Button = mbLeft then
559
  begin
560
    ok := true;
24 daniel-mar 561
    if (SelectedEnemyType = etEnemyBoss) and boss then
562
      ok := false // boss already exists
1 daniel-mar 563
    else
564
    begin
27 daniel-mar 565
      for i := 1 to NumEnemyTypes do
1 daniel-mar 566
      begin
40 daniel-mar 567
        for j := 0 to MaxPossibleEnemyLives do
1 daniel-mar 568
        begin
569
          if boss then
570
          begin
571
            for k := 0 to 3 do
572
            begin
573
              for l := 0 to 1 do
574
              begin
27 daniel-mar 575
                if LevData.IndexOfEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), etEnemyBoss, j) <> -1 then
1 daniel-mar 576
                begin
577
                  ok := false;
578
                  break;
579
                end;
580
              end;
581
              if not ok then break;
582
            end;
583
            if not ok then break;
584
          end;
27 daniel-mar 585
          if LevData.IndexOfEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j) <> -1 then
1 daniel-mar 586
          begin
587
            ok := false;
588
            break;
589
          end;
590
        end;
591
        if not ok then break;
592
      end;
593
    end;
594
    if ok then
595
    begin
24 daniel-mar 596
      if SelectedEnemyType <> etEnemyMeteor then
27 daniel-mar 597
        LevData.AddEnemy(ex + (ScrollP * RasterW), ey, SelectedEnemyType, LivesEdit.Value)
1 daniel-mar 598
      else
27 daniel-mar 599
        LevData.AddEnemy(ex + (ScrollP * RasterW), ey, SelectedEnemyType, 0);
1 daniel-mar 600
      inc(NumEnemys);
24 daniel-mar 601
      if SelectedEnemyType = etEnemyBoss then boss := true;
1 daniel-mar 602
    end
603
    else beep;
604
  end
605
  { Löschen }
606
  else if Button = mbRight then
607
  begin
27 daniel-mar 608
    for i := 1 to NumEnemyTypes do
1 daniel-mar 609
    begin
40 daniel-mar 610
      for j := 0 to MaxPossibleEnemyLives do
1 daniel-mar 611
      begin
27 daniel-mar 612
        if boss and (TEnemyType(i) = etEnemyBoss) then
1 daniel-mar 613
        begin
614
          for k := 0 to 3 do
615
          begin
616
            for l := 0 to 1 do
617
            begin
27 daniel-mar 618
              if LevData.IndexOfEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), TEnemyType(i), j) <> -1 then
1 daniel-mar 619
              begin
27 daniel-mar 620
                LevData.DeleteEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), TEnemyType(i), j);
1 daniel-mar 621
                Boss := false;
622
                dec(NumEnemys);
623
                breaked := true;
624
                break;
625
              end;
626
            end;
627
            if breaked then break;
628
          end;
629
        end;
27 daniel-mar 630
        if LevData.IndexOfEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j) <> -1 then
1 daniel-mar 631
        begin
27 daniel-mar 632
          LevData.DeleteEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j);
633
          if TEnemyType(i) = etEnemyBoss then Boss := false;
1 daniel-mar 634
          dec(NumEnemys);
635
          breaked := true;
636
          break;
637
        end;
638
      end;
639
      if breaked then break;
640
    end;
641
  end;
642
  LevChanged := true;
643
  AnzeigeAct;
644
end;
645
 
646
procedure TMainForm.EnemyClick(Sender: TObject);
24 daniel-mar 647
var
648
  et: TEnemyType;
1 daniel-mar 649
begin
24 daniel-mar 650
  et := SelectedEnemyType;
651
  Image1.Left := -(87 * (Ord(et) - 1)) + 1;
652
  LivesEdit.Enabled := et <> etEnemyMeteor;
653
  LivesLabel.Enabled := et <> etEnemyMeteor;
1 daniel-mar 654
end;
655
 
27 daniel-mar 656
procedure TMainForm.EnemyCreateSprite(x, y: integer; AEnemyType: TEnemyType; ALives: integer);
1 daniel-mar 657
var
658
  Enemy: TSprite;
659
begin
24 daniel-mar 660
  Enemy := TEnemy.Create(SpriteEngine.Engine, AEnemyType, ALives);
1 daniel-mar 661
  Enemy.x := x;
662
  Enemy.y := y;
663
end;
664
 
665
procedure TMainForm.DestroyLevel;
666
begin
8 daniel-mar 667
  ScrollBar.Position := 0; // this doesn't call ScrollBarScroll()
668
  ScrollP := 0;
27 daniel-mar 669
  LevData.Clear;
30 daniel-mar 670
  ScrollBar.Max := LevData.LevelEditorLength;
1 daniel-mar 671
  NumEnemys := 0;
672
  Boss := false;
673
  LevChanged := true;
24 daniel-mar 674
  LivesEdit.Value := 1;
1 daniel-mar 675
  Enemy1.Checked := true;
676
  EnemyClick(Enemy1);
677
  AnzeigeAct;
678
end;
679
 
30 daniel-mar 680
procedure TMainForm.AlleLeveldateienaktualisieren1Click(Sender: TObject);
681
var
682
  i: integer;
683
begin
684
  // Just for internal/development purposes
40 daniel-mar 685
  for i := 1 to MaxPossibleLevels do
30 daniel-mar 686
  begin
687
    if FileExists('Levels\Level '+IntToStr(i)+'.lev') then
688
    begin
44 daniel-mar 689
      LevData.RasterErzwingen := true;
40 daniel-mar 690
      LevData.LoadFromFile('Levels\Level '+IntToStr(i)+'.lev');
691
      LevData.SaveToFile('Levels\Level '+IntToStr(i)+'.lev');
30 daniel-mar 692
    end;
693
  end;
694
end;
695
 
1 daniel-mar 696
procedure TMainForm.AnzeigeAct;
697
begin
698
  SLabel1b.Caption := inttostr(NumEnemys);
699
  if Boss then SLabel2b.Caption := 'Ja' else SLabel2b.Caption := 'Nein';
700
  SLabel3b.Caption := inttostr(ScrollBar.Max);
701
  if LevChanged then
702
  begin
703
    SLabel4a.Font.Color := $00000096;
704
    SLabel4b.Font.Color := $00000096;
705
    SLabel4b.Caption := 'Nein';
706
  end
707
  else
708
  begin
709
    SLabel4a.Font.Color := $00009600;
710
    SLabel4b.Font.Color := $00009600;
711
    SLabel4b.Caption := 'Ja';
712
  end;
713
end;
714
 
63 daniel-mar 715
procedure TMainForm.AufUpdatesprfen1Click(Sender: TObject);
716
begin
717
  CheckForUpdates('spacemission');
718
end;
719
 
1 daniel-mar 720
procedure TMainForm.NeuClick(Sender: TObject);
721
begin
28 daniel-mar 722
  if MessageDlg('Level wirklich löschen?', mtConfirmation, mbYesNoCancel, 0) = mrYes then
1 daniel-mar 723
    DestroyLevel;
724
end;
725
 
726
procedure TMainForm.DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X,
727
  Y: Integer);
24 daniel-mar 728
resourcestring
729
  status_info = 'Zeigen Sie mit dem Mauszeiger auf eine Einheit, um deren Eigenschaften anzuzeigen...';
730
  status_lives = 'Leben: ';
731
  status_nolives = 'Einheit hat keine Lebensangabe';
1 daniel-mar 732
var
27 daniel-mar 733
  ex, ey, i, j, k, l: integer;
734
  lifes: integer;
735
  enemyType: TEnemyType;
736
  enemyName: string;
1 daniel-mar 737
  breaked: boolean;
738
begin
739
  if sender <> DxDraw then
740
  begin
24 daniel-mar 741
    StatusBar.SimpleText := ' ' + status_info;
1 daniel-mar 742
    exit;
743
  end;
744
  ex := trunc(x/RasterW) * RasterW;
745
  ey := trunc(y/RasterH) * RasterH;
27 daniel-mar 746
  lifes := -1;
747
  enemyType := etUnknown;
1 daniel-mar 748
  breaked := false;
27 daniel-mar 749
  for i := 1 to NumEnemyTypes do
1 daniel-mar 750
  begin
40 daniel-mar 751
    for j := 0 to MaxPossibleEnemyLives do
1 daniel-mar 752
    begin
27 daniel-mar 753
      if boss and (TEnemyType(i) = etEnemyBoss) then
1 daniel-mar 754
      begin
755
        for k := 0 to 3 do
756
        begin
757
          for l := 0 to 1 do
758
          begin
27 daniel-mar 759
            if LevData.IndexOfEnemy(ex + ((ScrollP - k) * RasterW), ey - (RasterH * l), TEnemyType(i), j) <> -1 then
1 daniel-mar 760
            begin
27 daniel-mar 761
              lifes := j;
1 daniel-mar 762
              breaked := true;
763
              break;
764
            end;
765
          end;
766
          if breaked then break;
767
        end;
768
      end;
27 daniel-mar 769
      if (breaked = false) and (LevData.IndexOfEnemy(ex + (ScrollP * RasterW), ey, TEnemyType(i), j) <> -1) then
1 daniel-mar 770
      begin
27 daniel-mar 771
        lifes := j;
772
        enemyType := TEnemyType(i);
1 daniel-mar 773
        breaked := true;
774
        break;
775
      end;
776
    end;
777
    if breaked then break;
778
  end;
27 daniel-mar 779
  if lifes <> -1 then
1 daniel-mar 780
  begin
27 daniel-mar 781
    if Ord(enemyType) = 1 then enemyName := Enemy1.Caption
782
    else if Ord(enemyType) = 2 then enemyName := Enemy2.Caption
783
    else if Ord(enemyType) = 3 then enemyName := Enemy3.Caption
784
    else if Ord(enemyType) = 4 then enemyName := Enemy4.Caption
785
    else if Ord(enemyType) = 5 then enemyName := Enemy5.Caption
786
    else if Ord(enemyType) = 6 then enemyName := Enemy6.Caption
787
    else if Ord(enemyType) = 7 then enemyName := Enemy7.Caption
788
    else enemyName := '???';
789
    if lifes > 0 then
790
      StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_lives + inttostr(lifes)
1 daniel-mar 791
    else
27 daniel-mar 792
      StatusBar.SimpleText := ' ' + enemyName + ' - ' + status_nolives;
1 daniel-mar 793
  end
794
  else
24 daniel-mar 795
    StatusBar.SimpleText := ' ' + status_info;
1 daniel-mar 796
end;
797
 
798
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
799
begin
30 daniel-mar 800
  if Assigned(LevData) and LevChanged and (LevData.CountEnemies>0) then
28 daniel-mar 801
    CanClose := MessageDlg('Beenden ohne abspeichern?', mtConfirmation, mbYesNoCancel, 0) = mrYes;
1 daniel-mar 802
end;
803
 
804
procedure TMainForm.Spielfelderweitern1Click(Sender: TObject);
805
begin
806
  LevelForm.Aktualisieren;
807
  LevelForm.showmodal;
808
end;
809
 
810
procedure TMainForm.ScrollBarScroll(Sender: TObject;
811
  ScrollCode: TScrollCode; var ScrollPos: Integer);
812
begin
813
  ScrollP := ScrollPos;
814
end;
815
 
24 daniel-mar 816
function TMainForm.SelectedEnemyType: TEnemyType;
1 daniel-mar 817
begin
24 daniel-mar 818
  if Enemy1.Checked then result := etEnemyAttacker
819
  else if Enemy2.Checked then result := etEnemyAttacker2
820
  else if Enemy3.Checked then result := etEnemyAttacker3
821
  else if Enemy4.Checked then result := etEnemyMeteor
822
  else if Enemy5.Checked then result := etEnemyUFO
823
  else if Enemy6.Checked then result := etEnemyUFO2
824
  else if Enemy7.Checked then result := etEnemyBoss
825
  else result := etUnknown;
1 daniel-mar 826
end;
827
 
828
end.
829