Subversion Repositories spacemission

Rev

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