Subversion Repositories spacemission

Rev

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