Skip to content

Commit 15874e2

Browse files
committed
Improved pathfind and hints
1 parent dcd80cb commit 15874e2

3 files changed

Lines changed: 51 additions & 38 deletions

File tree

code/gameentities.pas

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ interface
77
uses
88
// System
99
Classes, generics.collections,
10+
// ThirdParty
11+
PathFind,
1012
// Own
1113
gameoptions;
1214

@@ -100,6 +102,7 @@ TMap = class(TComponent)
100102
FLastTower, FLastStock, FHeroTowerIndex, FHeroStockIndex, FTargetTower, FTargetStock: Integer;
101103
FHero: THero;
102104
FHeroRoom: TRoom;
105+
FPathMap: TPathMap;
103106
function PathFindCost(T, S, Direction: Smallint) : Smallint;
104107
class var FMap: TMap;
105108
public
@@ -135,8 +138,6 @@ implementation
135138
uses
136139
// System
137140
SysUtils, typinfo, Math,
138-
// ThirdParty
139-
PathFind,
140141
// Castle
141142
castlelog,
142143
// Own
@@ -234,31 +235,25 @@ constructor TMap.Create(AOwner: TComponent);
234235
inherited Create(AOwner);
235236
FMap := Self;
236237
FHero := THero.Create(nil);
237-
238238
FTowers := TObjectList<TTower>.Create(True);
239239
FDifficulty := Difficulty();
240240
FLastTower := 3 + Ord(FDifficulty);
241241
for T := 1 to FLastTower do
242242
begin
243243
LTower := TTower.Create(nil);
244+
FTowers.Add(LTower);
244245
FLastStock := Min(T + 3, 8);
245246
for R := 1 to FLastStock do
246247
begin
247248
LRoom := TRoom.Create(nil);
249+
LTower.FRooms.Add(LRoom);
248250
if IsFinalRoom(T, R) then
249251
LRoom.Actors.Add(TDragon.Create(nil, T, R))
250252
else if (T <> 1) or (R <> 1) then
251-
LRoom.Actors.Add(TEnemy.Create(nil, T, R))
252-
else
253-
begin
254-
FHeroRoom := LRoom;
255-
FHeroTowerIndex := 0;
256-
FHeroStockIndex := 0;
257-
end;
258-
LTower.FRooms.Add(LRoom);
253+
LRoom.Actors.Add(TEnemy.Create(nil, T, R))
259254
end;
260-
FTowers.Add(LTower);
261255
end;
256+
SetHeroRoom(0);
262257
end;
263258

264259
destructor TMap.Destroy();
@@ -301,15 +296,17 @@ function TMap.SetHeroRoom(ARoomIndex: Integer): Boolean;
301296
begin
302297
LTowerIndex := ARoomIndex div 10;
303298
LStockIndex := ARoomIndex mod 10;
304-
FTargetTower := LTowerIndex;
305-
FTargetStock := LStockIndex;
299+
FPathMap := nil;
306300
//WriteLnLog(Format('SX%d SY%d TX%d TY%d', [FHeroTowerIndex, FHeroStockIndex, LTowerIndex, LStockIndex]));
307301
if not IsRoomReachable(LTowerIndex, LStockIndex) then
308302
Exit(False);
309303
FHeroRoom := FTowers[LTowerIndex].Rooms[LStockIndex];
310304
FHeroTowerIndex := LTowerIndex;
311305
FHeroStockIndex := LStockIndex;
312306
Result := True;
307+
FTargetTower := FHeroTowerIndex;
308+
FTargetStock := FHeroStockIndex;
309+
FPathMap := MakePathMap(FTowers.Count, FTowers.Last.Rooms.Count, FHeroTowerIndex, FHeroStockIndex, PathFindCost);
313310
end;
314311

315312
function TMap.IsHeroRoom(ARoomIndex: Integer): Boolean;
@@ -331,20 +328,24 @@ function TMap.GetRoomByIndex(ARoomIndex: Integer): TRoom;
331328
end;
332329

333330
function TMap.PathFindCost(T, S, Direction: Smallint) : Smallint;
331+
var
332+
LT, LS: Integer;
334333
begin
335-
// if T within towers count and S is within stock count of tower T and room hasnot enemy, except target room, then return 1, else -1,
336-
if (T >= 0) and (T < FTowers.Count) and (S >= 0) and (S < FTowers[T].Rooms.Count) and (Direction mod 2 = 0)
337-
and (not FTowers[T].Rooms[S].HasEnemy() or ((T = FTargetTower) and (S = FTargetStock))) then
338-
Result := 1
339-
else
340-
Result := -1;
334+
LT := T - DirToDX(Direction);
335+
LS := S - DirToDY(Direction);
336+
Result := Ord((Direction mod 2 = 0) and (T >= 0) and (S >= 0) and (T < FTowers.Count) and (S < FTowers[T].Rooms.Count)
337+
and (((LT = FTargetTower) and (LS = FTargetStock))
338+
or (not FTowers[T].Rooms[S].HasEnemy() or not FTowers[LT].Rooms[LS].HasEnemy()))) * 2 - 1;
341339
end;
342340

343341
function TMap.IsRoomReachable(ATowerIndex, AStockIndex: Integer): Boolean;
344342
begin
345343
FTargetTower := ATowerIndex;
346-
FTargetStock := AStockIndex;
347-
Result := PathFind.FindPath(FTowers.Count, FTowers.Last.Rooms.Count, FHeroTowerIndex, FHeroStockIndex, ATowerIndex, AStockIndex, PathFindCost) <> nil;
344+
FTargetStock := AStockIndex;
345+
if Assigned(FPathMap) then
346+
Result := FindPathOnMap(FPathMap, ATowerIndex, AStockIndex) <> nil
347+
else
348+
Result := FindPath(FTowers.Count, FTowers.Last.Rooms.Count, FHeroTowerIndex, FHeroStockIndex, ATowerIndex, AStockIndex, PathFindCost) <> nil;
348349
end;
349350

350351
constructor TEnemy.Create(AOwner: TComponent; ATower, AStock: Integer);

code/gameviewgame.pas

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ TViewGame = class(TCastleView)
4242
private
4343
FPreviousRoom: TRoomComponent;
4444
FWeapons: array[0..3] of TCastleButton;
45-
FSkip, FPause: Boolean;
45+
FSkip, FPause, FInternalWeaponSwitch: Boolean;
4646
FPosFrom, FPosTo: TVector2;
4747
FAnimateWeaponTicks, FGameTicks: Integer;
4848
FViewEnd: TCastleView;
@@ -61,6 +61,7 @@ TViewGame = class(TCastleView)
6161
procedure WeaponHint(ADoShow: Boolean; AWeapon: NHeroWeapon = hwNo);
6262
procedure VisualizeTime();
6363
procedure UpdateRooms();
64+
procedure WeaponClick(AWeapon: NHeroWeapon; AFromUser: Boolean = False);
6465
private const
6566
TicksToFlyWeapon = 30; // animation will last 0.5 seconds (30 ticks * 16 ms)
6667
GameSeconds: array[NDifficulty] of Integer = (240, 360, 480, 600);
@@ -132,7 +133,7 @@ procedure TViewGame.Start();
132133
FWeapons[1] := WeaponPlus;
133134
FWeapons[2] := WeaponMinus;
134135
FWeapons[3] := WeaponMultiply;
135-
WeaponNo.Doclick();
136+
WeaponNo.DoClick();
136137
TimerPreEnd.Exists := False;
137138
TimerBlood.Exists := False;
138139
TimerPreEnd.OnTimer := TimerPreEndTick;
@@ -145,7 +146,8 @@ procedure TViewGame.Start();
145146
FGameTicks := GameSeconds[Difficulty()];
146147
VisualizeTime();
147148

148-
GroupTowers.ClearControls();
149+
GroupTowers.ClearControls();
150+
GroupTowers.Spacing := (Ord(High(NDifficulty)) - Ord(Difficulty()) - 1) * 40;
149151
for LTowerIndex := 0 to Pred(Map.Towers.Count) do
150152
begin
151153
LVisualTower := FactoryTower.ComponentLoad(GroupTowers) as TCastleUserInterface;
@@ -196,9 +198,11 @@ procedure TViewGame.ButtonWeaponClick(Sender: TObject);
196198
LIsWeapon := FWeapons[i] = LWeaponButton;
197199
if LIsWeapon then
198200
begin
199-
WeaponHint(False);
201+
if not FInternalWeaponSwitch then
202+
WeaponHint(False);
200203
Map.Hero.Weapon := NHeroWeapon(i);
201-
WeaponHint(True);
204+
if not FInternalWeaponSwitch then
205+
WeaponHint(True);
202206
end;
203207
FWeapons[i].Pressed := LIsWeapon or (i = Ord(hwNo));
204208
FWeapons[i].Border.AllSides := IIF(LIsWeapon or (i = Ord(hwNo)), 4, 0);
@@ -248,7 +252,7 @@ procedure TViewGame.Update(const SecondsPassed: Single; var HandleInput: boolean
248252
if FAnimateWeaponTicks = 0 then
249253
begin
250254
ImageWeapon.Url := '';
251-
WeaponNo.DoClick();
255+
WeaponClick(hwNo);
252256
end;
253257
end;
254258
if not FPause and (Map.Hero.Weapon <> hwNo) then
@@ -289,19 +293,19 @@ function TViewGame.Press(const Event: TInputPressRelease): Boolean;
289293
repeat
290294
W := (W + 1) mod Length(FWeapons);
291295
until FWeapons[W].Enabled;
292-
FWeapons[W].DoClick();
296+
WeaponClick(NHeroWeapon(W), True);
293297
Exit(True); // key was handled
294298
end;
295299

296300
if Event.Key in [key1, key2, key3, key4] then
297301
begin
298-
FWeapons[Ord(Event.Key) - Ord(key1)].DoClick();
302+
WeaponClick(NHeroWeapon(Ord(Event.Key) - Ord(key1)), True);
299303
Exit(True); // key was handled
300304
end;
301305

302306
if Event.Key in [keyNumpad1, keyNumpad2, keyNumpad3, keyNumpad4] then
303307
begin
304-
FWeapons[Ord(Event.Key) - Ord(keyNumpad1)].DoClick();
308+
WeaponClick(NHeroWeapon(Ord(Event.Key) - Ord(keyNumpad1)), True);
305309
Exit(True); // key was handled
306310
end;
307311

@@ -442,7 +446,7 @@ procedure TViewGame.TimerBloodTick(ASender: TObject);
442446
FRoomFight.LabelLeft.Caption := Map.Hero.Visual;
443447

444448
if LWeapon = hwNo then
445-
WeaponNo.DoClick();
449+
WeaponClick(hwNo);
446450
//WriteLnLog(Format('T%d S%d L%d L%d', [Map.HeroTowerIndex, Map.HeroStockIndex, Map.LastTower, Map.LastStock]));
447451
if Map.IsFinalRoom(Map.HeroTowerIndex + 1, Map.HeroStockIndex + 1) then
448452
begin
@@ -472,6 +476,7 @@ procedure TViewGame.WeaponHint(ADoShow: Boolean; AWeapon: NHeroWeapon = hwNo);
472476
var
473477
LWeapon: NHeroWeapon;
474478
begin
479+
TimerHint.ResetNextTimerEvent();
475480
TimerHint.Exists := ADoShow;
476481
if AWeapon = hwNo then
477482
LWeapon := Map.Hero.Weapon
@@ -512,9 +517,16 @@ procedure TViewGame.UpdateRooms();
512517
for LStockIndex := 0 to Pred(Map.Towers[LTowerIndex].Rooms.Count) do
513518
begin
514519
LRoomComponent := LGroupTower.Controls[LStockIndex] as TRoomComponent;
515-
LRoomComponent.ControlRoom.Enabled := {Map.IsHeroRoom(LRoomComponent.Tag) or} Map.IsRoomReachable(LTowerIndex, LStockIndex);
520+
LRoomComponent.ControlRoom.Enabled := Map.IsRoomReachable(LTowerIndex, LStockIndex);
516521
end;
517522
end;
518523
end;
519524

520-
end.
525+
procedure TViewGame.WeaponClick(AWeapon: NHeroWeapon; AFromUser: Boolean = False);
526+
begin
527+
FInternalWeaponSwitch := not AFromUser;
528+
FWeapons[Ord(AWeapon)].DoClick();
529+
FInternalWeaponSwitch := False;
530+
end;
531+
532+
end.

data/gameviewgame.castle-user-interface

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,11 @@
243243
"Name" : "ButtonGameTime",
244244
"TranslationPersistent" : {
245245
"$$ClassName" : "TCastleVector2Persistent",
246-
"X" : 4.4799996948242188E+002
246+
"X" : 4.4800000000000000E+002
247247
},
248248
"VerticalAnchorParent" : "vpMiddle",
249249
"VerticalAnchorSelf" : "vpMiddle",
250-
"Width" : 2.0000000000000000E+002
250+
"Width" : 1.8200000000000000E+002
251251
}
252252
]
253253
},
@@ -261,7 +261,7 @@
261261
"Name" : "ImageWeaponsBack",
262262
"TranslationPersistent" : {
263263
"$$ClassName" : "TCastleVector2Persistent",
264-
"Y" : -1.2200000000000000E+002
264+
"Y" : -1.2200000762939453E+002
265265
},
266266
"VerticalAnchorParent" : "vpTop",
267267
"VerticalAnchorSelf" : "vpTop",
@@ -336,7 +336,7 @@
336336
"Name" : "Group2",
337337
"TranslationPersistent" : {
338338
"$$ClassName" : "TCastleVector2Persistent",
339-
"X" : 1.5800000000000000E+002
339+
"X" : 1.5799998474121094E+002
340340
},
341341
"VerticalAnchorParent" : "vpMiddle",
342342
"VerticalAnchorSelf" : "vpMiddle",

0 commit comments

Comments
 (0)