Subversion Repositories spacemission

Rev

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