diff --git a/CLEAN.bat b/CLEAN.bat
index 2551b71..bce4737 100644
--- a/CLEAN.bat
+++ b/CLEAN.bat
@@ -9,5 +9,6 @@ del /s *.otares
del /s *.local
del /s *.cfg
del /s *.ddp
-del /s *.o
del /s *.a
+del /S *.*proj.local
+del /S *.tvsconfig
diff --git a/README.md b/README.md
index 596602e..2fc3404 100644
--- a/README.md
+++ b/README.md
@@ -2,31 +2,31 @@
Simple roguelike game based on Disciples.
## Screenshots
-### Day 1
+### Day 1 [3.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_1.png)
-
### Day 2
+
### Day 2 [4.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_2.png)
-
### Day 3
+
### Day 3 [5.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_3.png)
-
### Day 4
+
### Day 4 [6.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_4.png)
-### Day 5
+### Day 5 [7.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_5.png)
-### Day 6
+### Day 6 [8.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_6.png)
-### Day 7
+### Day 7 [9.03.2018]
![screenshot](https://github.com/devapromix-roguelikes/disciplesrl/blob/master/screenshots/screenshot_day_7.png)
diff --git a/resources/chest.png b/resources/chest.png
index 3c7500f..bbf1339 100644
Binary files a/resources/chest.png and b/resources/chest.png differ
diff --git a/resources/dirt.png b/resources/dirt.png
new file mode 100644
index 0000000..505e11f
Binary files /dev/null and b/resources/dirt.png differ
diff --git a/resources/mountain.png b/resources/mountain.png
new file mode 100644
index 0000000..c6808fa
Binary files /dev/null and b/resources/mountain.png differ
diff --git a/screenshots/screenshot_day_3.png b/screenshots/screenshot_day_3.png
new file mode 100644
index 0000000..84668df
Binary files /dev/null and b/screenshots/screenshot_day_3.png differ
diff --git a/sources/DisciplesRL.City.pas b/sources/DisciplesRL.City.pas
new file mode 100644
index 0000000..610de8c
--- /dev/null
+++ b/sources/DisciplesRL.City.pas
@@ -0,0 +1,121 @@
+unit DisciplesRL.City;
+
+interface
+
+uses DisciplesRL.Party;
+
+type
+ TCity = record
+ X, Y: Integer;
+ CurLevel: Integer;
+ MaxLevel: Integer;
+ Owner: TRaceEnum;
+ end;
+
+var
+ City: array [0 .. 3] of TCity;
+
+procedure Init;
+function GetCityIndex(const AX, AY: Integer): Integer;
+procedure UpdateRadius(const AID: Integer);
+procedure Gen;
+
+implementation
+
+uses System.Math, DisciplesRL.Map, DisciplesRL.Resources, DisciplesRL.Utils, DisciplesRL.Player;
+
+procedure Init;
+var
+ I: Integer;
+begin
+ for I := 0 to High(City) do
+ begin
+ City[I].X := 0;
+ City[I].Y := 0;
+ City[I].CurLevel := 0;
+ City[I].MaxLevel := 2;
+ City[I].Owner := reNeutrals;
+ end;
+end;
+
+function GetCityIndex(const AX, AY: Integer): Integer;
+var
+ I: Integer;
+begin
+ Result := -1;
+ for I := 0 to High(City) do
+ if ((City[I].X = AX) and (City[I].Y = AY)) then
+ begin
+ Result := I;
+ Break;
+ end;
+end;
+
+procedure UpdateRadius(const AID: Integer);
+begin
+ DisciplesRL.Map.UpdateRadius(City[AID].X, City[AID].Y, City[AID].CurLevel, MapTile, reEmpireTerrain,
+ [reEmpireCity, reNeutralCity, reEmpireCapital]);
+ DisciplesRL.Map.UpdateRadius(City[AID].X, City[AID].Y, City[AID].CurLevel, MapDark, reNone);
+ City[AID].Owner := reTheEmpire;
+end;
+
+function ChCity(N: Integer): Boolean;
+var
+ I: Integer;
+begin
+ Result := True;
+ if (N = 0) then
+ Exit;
+ for I := 0 to N - 1 do
+ begin
+ if (GetDist(City[I].X, City[I].Y, City[N].X, City[N].Y) <= 6) then
+ begin
+ Result := False;
+ Exit;
+ end;
+ end;
+end;
+
+procedure ClearObj(const AX, AY: Integer);
+var
+ X, Y: Integer;
+begin
+ for X := AX - 2 to AX + 2 do
+ for Y := AY - 2 to AY + 2 do
+ if (X = AX - 2) or (X = AX + 2) or (Y = AY - 2) or (Y = AY + 2) then
+ begin
+ if (RandomRange(0, 5) = 0) then
+ MapObj[X, Y] := reNone
+ end
+ else
+ MapObj[X, Y] := reNone;
+end;
+
+procedure Gen;
+var
+ I, X, Y: Integer;
+begin
+ for I := 0 to High(City) do
+ begin
+ repeat
+ City[I].X := RandomRange(3, MapWidth - 3);
+ City[I].Y := RandomRange(3, MapHeight - 3);
+ until ChCity(I);
+ // Capital
+ if (I = 0) then
+ begin
+ Player.X := City[I].X;
+ Player.Y := City[I].Y;
+ MapTile[City[I].X, City[I].Y] := reEmpireCapital;
+ ClearObj(City[I].X, City[I].Y);
+ UpdateRadius(I);
+ Continue;
+ end;
+ // City
+ MapTile[City[I].X, City[I].Y] := reNeutralCity;
+ ClearObj(City[I].X, City[I].Y);
+ MapObj[City[I].X, City[I].Y] := reEnemies;
+ end;
+end;
+
+end.
diff --git a/sources/DisciplesRL.MainForm.dfm b/sources/DisciplesRL.MainForm.dfm
index c0aa830..ad1fde7 100644
--- a/sources/DisciplesRL.MainForm.dfm
+++ b/sources/DisciplesRL.MainForm.dfm
@@ -1,9 +1,11 @@
object MainForm: TMainForm
Left = 0
Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ BorderStyle = bsSingle
Caption = 'DisciplesRL'
- ClientHeight = 492
- ClientWidth = 1057
+ ClientHeight = 596
+ ClientWidth = 795
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
diff --git a/sources/DisciplesRL.MainForm.pas b/sources/DisciplesRL.MainForm.pas
index ee1fd66..e665e34 100644
--- a/sources/DisciplesRL.MainForm.pas
+++ b/sources/DisciplesRL.MainForm.pas
@@ -33,13 +33,18 @@ implementation
procedure TMainForm.FormCreate(Sender: TObject);
begin
+ Top := 0;
+ Left := 0;
Randomize;
- DisciplesRL.Scenes.Init;
// Test
DisciplesRL.Resources.Init;
DisciplesRL.Map.Init;
DisciplesRL.Map.Gen;
DisciplesRL.Player.Init;
+ //
+ ClientWidth := MapWidth * TileSize;
+ ClientHeight := MapHeight * TileSize;
+ DisciplesRL.Scenes.Init;
end;
procedure TMainForm.FormPaint(Sender: TObject);
diff --git a/sources/DisciplesRL.Map.pas b/sources/DisciplesRL.Map.pas
index 018c855..c311d29 100644
--- a/sources/DisciplesRL.Map.pas
+++ b/sources/DisciplesRL.Map.pas
@@ -5,28 +5,35 @@ interface
uses DisciplesRL.Resources;
var
- MapWidth: Integer = 20;
- MapHeight: Integer = 12;
+ MapWidth: Integer = 40;
+ MapHeight: Integer = 20;
const
TileSize = 32;
type
- TLayerEnum = (lTile, lPath, lDark);
+ TLayerEnum = (lrTile, lrPath, lrDark, lrObj);
+
+type
+ TMapLayer = array of array of TResEnum;
+ TIgnoreRes = set of TResEnum;
var
- MapTile: array of array of TResEnum;
- MapPath: array of array of TResEnum;
- MapDark: array of array of TResEnum;
+ MapTile: TMapLayer;
+ MapPath: TMapLayer;
+ MapDark: TMapLayer;
+ MapObj: TMapLayer;
procedure Init;
procedure Clear(const L: TLayerEnum);
procedure Gen;
function InMap(X, Y: Integer): Boolean;
+procedure UpdateRadius(const AX, AY, AR: Integer; var MapLayer: TMapLayer; const AResEnum: TResEnum;
+ IgnoreRes: TIgnoreRes = []);
implementation
-uses System.Math, DisciplesRL.Player;
+uses System.Math, DisciplesRL.Player, DisciplesRL.Utils, DisciplesRL.City, DisciplesRL.PathFind;
procedure Init;
var
@@ -35,8 +42,10 @@ procedure Init;
SetLength(MapTile, MapWidth, MapHeight);
SetLength(MapPath, MapWidth, MapHeight);
SetLength(MapDark, MapWidth, MapHeight);
+ SetLength(MapObj, MapWidth, MapHeight);
for L := Low(TLayerEnum) to High(TLayerEnum) do
Clear(L);
+ DisciplesRL.City.Init;
end;
procedure Clear(const L: TLayerEnum);
@@ -46,34 +55,65 @@ procedure Clear(const L: TLayerEnum);
for Y := 0 to MapHeight - 1 do
for X := 0 to MapWidth - 1 do
case L of
- lTile:
+ lrTile:
MapTile[X, Y] := reNone;
- lPath:
+ lrPath:
MapPath[X, Y] := reNone;
- lDark:
+ lrDark:
MapDark[X, Y] := reDark;
+ lrObj:
+ MapObj[X, Y] := reNone;
end;
end;
+function ChTile(X, Y: Integer): Boolean; stdcall;
+begin
+ Result := True;
+end;
+
procedure Gen;
var
- X, Y: Integer;
+ X, Y, RX, RY, I: Integer;
begin
for Y := 0 to MapHeight - 1 do
for X := 0 to MapWidth - 1 do
- MapTile[X, Y] := reGrass;
- for X := 0 to 7 do
- MapTile[RandomRange(0, MapWidth), RandomRange(0, MapHeight)] := reEnemies;
- for X := 0 to 5 do
- MapTile[RandomRange(0, MapWidth), RandomRange(0, MapHeight)] := reBag;
- for X := 0 to 3 do
- MapTile[RandomRange(0, MapWidth), RandomRange(0, MapHeight)] := reCity;
- // Player
- X := RandomRange(0, MapWidth);
- Y := RandomRange(0, MapHeight);
- MapTile[X, Y] := reCapital;
- Player.X := X;
- Player.Y := Y;
+ begin
+ MapTile[X, Y] := reNeutral;
+ MapObj[X, Y] := reMountain;
+ end;
+ // Bags
+ // for X := 0 to 5 do
+ // MapObj[RandomRange(0, MapWidth), RandomRange(0, MapHeight)] := reBag;
+ // Capital and Cities
+ DisciplesRL.City.Gen;
+ X := City[0].X;
+ Y := City[0].Y;
+ for I := 1 to High(City) do
+ repeat
+ if PathFind(X, Y, City[I].X, City[I].Y, ChTile, RX, RY) then
+ begin
+ // if (RandomRange(0, 2) = 0) then
+ begin
+ X := RX + RandomRange(-1, 2);
+ Y := RY + RandomRange(-1, 2);
+ if MapObj[X, Y] = reMountain then
+ MapObj[X, Y] := reNone;
+ end;
+ X := RX;
+ Y := RY;
+ if MapObj[X, Y] = reMountain then
+ MapObj[X, Y] := reNone;
+ end;
+ until ((X = City[I].X) and (Y = City[I].Y));
+ // Enemies
+ for I := 0 to High(City) do
+ begin
+ repeat
+ X := RandomRange(1, MapWidth - 1);
+ Y := RandomRange(1, MapHeight - 1);
+ until (MapObj[X, Y] = reNone);
+ MapObj[X, Y] := reEnemies;
+ end;
end;
function InMap(X, Y: Integer): Boolean;
@@ -81,4 +121,18 @@ function InMap(X, Y: Integer): Boolean;
Result := (X >= 0) and (X < MapWidth) and (Y >= 0) and (Y < MapHeight);
end;
+procedure UpdateRadius(const AX, AY, AR: Integer; var MapLayer: TMapLayer; const AResEnum: TResEnum;
+ IgnoreRes: TIgnoreRes = []);
+var
+ X, Y: Integer;
+begin
+ for Y := -AR to AR do
+ for X := -AR to AR do
+ if (GetDist(AX + X, AY + Y, AX, AY) <= AR) and DisciplesRL.Map.InMap(AX + X, AY + Y) then
+ if (MapLayer[AX + X, AY + Y] in IgnoreRes) then
+ Continue
+ else
+ MapLayer[AX + X, AY + Y] := AResEnum;
+end;
+
end.
diff --git a/sources/DisciplesRL.Party.pas b/sources/DisciplesRL.Party.pas
index 60bf610..dd16262 100644
--- a/sources/DisciplesRL.Party.pas
+++ b/sources/DisciplesRL.Party.pas
@@ -5,7 +5,7 @@ interface
uses DisciplesRL.Creatures;
type
- TRace = (rcTheEmpire, rcNeutrals);
+ TRaceEnum = (reTheEmpire, reNeutrals);
type
TPosition = 0 .. 5;
@@ -13,7 +13,7 @@ interface
type
TParty = class(TObject)
private
- FOwner: TRace;
+ FOwner: TRaceEnum;
FCreature: array [TPosition] of TCreature;
procedure AddCreature(const ACreatureEnum: TCreatureEnum; const APosition: TPosition);
function GetCreature(APosition: TPosition): TCreature;
@@ -21,7 +21,7 @@ TParty = class(TObject)
public
constructor Create;
destructor Destroy; override;
- property Owner: TRace read FOwner write FOwner;
+ property Owner: TRaceEnum read FOwner write FOwner;
property Creature[APosition: TPosition]: TCreature read GetCreature write SetCreature;
procedure Clear;
function Hire(const ACreatureEnum: TCreatureEnum; const APosition: TPosition): Boolean;
@@ -52,7 +52,7 @@ procedure TParty.Clear;
constructor TParty.Create;
begin
Self.Clear;
- Owner := rcNeutrals;
+ Owner := reNeutrals;
end;
destructor TParty.Destroy;
@@ -125,5 +125,4 @@ procedure TParty.UpdateHP(const AHitPoints: Integer; const APosition: TPosition)
HitPoints := MaxHitPoints;
end;
-
end.
diff --git a/sources/DisciplesRL.PathFind.pas b/sources/DisciplesRL.PathFind.pas
new file mode 100644
index 0000000..dc256a8
--- /dev/null
+++ b/sources/DisciplesRL.PathFind.pas
@@ -0,0 +1,217 @@
+unit DisciplesRL.PathFind;
+
+interface
+
+uses DisciplesRL.Map;
+
+type
+ TGetXYVal = function(X, Y: Integer): Boolean; stdcall;
+
+function PathFind(FromX, FromY, ToX, ToY: Integer; Callback: TGetXYVal;
+ var TargetX, TargetY: Integer): Boolean;
+
+implementation
+
+uses Math;
+
+const
+ MAXLEN = 1000;
+ KNORM = 10;
+ KDIAG = 12;
+
+type
+ TUIntPoint = record
+ X, Y: Word;
+ end;
+
+type
+ TPathFindBlock = record
+ CostWay: Integer;
+ Parent: TUIntPoint;
+ end;
+
+type
+ TOpenBlock = record
+ Cost, X, Y: Integer;
+ end;
+
+ POpenBlock = ^TOpenBlock;
+
+ TPathFindMap = array of TPathFindBlock;
+
+var
+ Cells: TPathFindMap;
+ FAULT: Integer;
+ SavedMapX, SavedMapY: Integer;
+ Open: array [0 .. MAXLEN] of POpenBlock;
+ OpenRaw: array [0 .. MAXLEN] of TOpenBlock;
+
+procedure InitCrap;
+var
+ I: Integer;
+begin
+ for I := 0 to MAXLEN do
+ Open[I] := @OpenRaw[I];
+end;
+
+function Heuristic(dx, dy: Integer): Integer;
+begin
+ Result := KNORM * Max(dx, dy) + (KDIAG - KNORM) * Min(dx, dy);
+end;
+
+var
+ NOpen: Integer = 0;
+
+function PathFind(FromX, FromY, ToX, ToY: Integer; Callback: TGetXYVal;
+ var TargetX, TargetY: Integer): Boolean;
+
+ procedure HeapSwap(I, j: Integer);
+ var
+ tmp: POpenBlock;
+ begin
+ tmp := Open[I];
+ Open[I] := Open[j];
+ Open[j] := tmp;
+ end;
+
+ procedure HeapAdd;
+ var
+ I, Parent: Integer;
+ begin
+ I := NOpen - 1;
+ Parent := (I - 1) div 2;
+ while (I > 0) and (Open[Parent].Cost > Open[I].Cost) do
+ begin
+ HeapSwap(I, Parent);
+ I := Parent;
+ Parent := (I - 1) div 2;
+ end;
+ end;
+
+ procedure Heapify(I: Integer);
+ var
+ leftChild, rightChild, largestChild: Integer;
+ begin
+ repeat
+ leftChild := 2 * I + 1;
+ if leftChild >= NOpen then
+ exit;
+ rightChild := leftChild + 1;
+ largestChild := I;
+ if Open[leftChild].Cost < Open[largestChild].Cost then
+ largestChild := leftChild;
+ if (rightChild < NOpen) and (Open[rightChild].Cost < Open[largestChild].Cost) then
+ largestChild := rightChild;
+ if largestChild = I then
+ exit;
+ HeapSwap(I, largestChild);
+ I := largestChild;
+ until false;
+ end;
+
+ procedure AddToOpen(X, Y, FrX, FrY, NewCost: Integer);
+ begin
+ if not InRange(X, 0, MapWidth - 1) then
+ exit;
+ if not InRange(Y, 0, MapHeight - 1) then
+ exit;
+ with Cells[X * MapHeight + Y] do
+ begin
+ if CostWay > 0 then // if OpenID > 0 then
+ begin
+ // if CostWay <= NewCost then
+ exit;
+ end;
+ if not Callback(X, Y) then
+ exit;
+ if NOpen >= MAXLEN then
+ exit;
+ Open[NOpen].X := X;
+ Open[NOpen].Y := Y;
+ // TODO??
+ CostWay := NewCost;
+ Open[NOpen].Cost := CostWay + Heuristic(abs(X - FromX), abs(Y - FromY));
+ Inc(NOpen);
+ HeapAdd;
+ Parent.X := FrX;
+ Parent.Y := FrY;
+ end;
+ end;
+
+var
+ CurX, CurY: Integer;
+begin
+ Result := false;
+ if not InRange(ToX, 0, MapWidth - 1) then
+ exit;
+ if not InRange(ToY, 0, MapHeight - 1) then
+ exit;
+ if not Callback(ToX, ToY) then
+ exit;
+ // if not Callback(FromX, FromY) then exit;
+ if (FromX = ToX) and (FromY = ToY) then
+ begin
+ Result := True;
+ TargetX := ToX;
+ TargetY := ToY;
+ exit;
+ end;
+
+ if (SavedMapX <> MapWidth) or (SavedMapY <> MapHeight) then
+ begin
+ SetLength(Cells, 0);
+ SetLength(Cells, MapWidth * MapHeight);
+ SavedMapX := MapWidth;
+ SavedMapY := MapHeight;
+ end
+ else
+ begin
+ FillChar(Pointer(Cells)^, MapWidth * MapHeight * Sizeof(Cells[0]), 0);
+ end;
+ // exit;
+
+ NOpen := 0;
+ // FillChar(Cells, SizeOf(Cells), 0);
+ AddToOpen(ToX, ToY, -1, -1, 0);
+ repeat
+ CurX := Open[0].X;
+ CurY := Open[0].Y;
+ if (CurX = FromX) and (CurY = FromY) then
+ begin
+ Result := True;
+ // Inc(TOTAL, Open[0].Cost);
+ with Cells[CurX * MapHeight + CurY] do
+ begin
+ TargetX := Parent.X;
+ TargetY := Parent.Y;
+ end;
+ exit;
+ end;
+ with Cells[CurX * MapHeight + CurY] do
+ begin
+ // IsClosed := True;
+ // inc(CHECKED);
+ HeapSwap(0, NOpen - 1);
+ // Open[0] := Open[NOpen-1];
+ Dec(NOpen);
+ Heapify(0);
+ AddToOpen(CurX - 1, CurY, CurX, CurY, CostWay + KNORM);
+ AddToOpen(CurX, CurY - 1, CurX, CurY, CostWay + KNORM);
+ AddToOpen(CurX, CurY + 1, CurX, CurY, CostWay + KNORM);
+ AddToOpen(CurX + 1, CurY, CurX, CurY, CostWay + KNORM);
+ AddToOpen(CurX - 1, CurY - 1, CurX, CurY, CostWay + KDIAG);
+ AddToOpen(CurX - 1, CurY + 1, CurX, CurY, CostWay + KDIAG);
+ AddToOpen(CurX + 1, CurY - 1, CurX, CurY, CostWay + KDIAG);
+ AddToOpen(CurX + 1, CurY + 1, CurX, CurY, CostWay + KDIAG);
+ if NOpen > FAULT then
+ FAULT := NOpen;
+ end;
+ until NOpen <= 0;
+ Result := false;
+end;
+
+initialization
+
+InitCrap;
+
+end.
diff --git a/sources/DisciplesRL.Player.pas b/sources/DisciplesRL.Player.pas
index 435ed63..c24842c 100644
--- a/sources/DisciplesRL.Player.pas
+++ b/sources/DisciplesRL.Player.pas
@@ -5,34 +5,75 @@ interface
type
TPlayer = record
X, Y: Integer;
- Rad: Integer;
+ Radius: Integer;
+ Turn: Integer;
end;
var
Player: TPlayer;
procedure Init;
-procedure RefreshRad;
+procedure Move(const AX, AY: ShortInt);
+procedure PutAt(const AX, AY: ShortInt);
+procedure RefreshRadius;
implementation
-uses DisciplesRL.Map, DisciplesRL.Resources, DisciplesRL.Utils;
+uses DisciplesRL.Map, DisciplesRL.Resources, DisciplesRL.Utils, DisciplesRL.City, DisciplesRL.Party;
procedure Init;
begin
- Player.Rad := 2;
- RefreshRad;
+ Player.Turn := 0;
+ Player.Radius := 41;
+ RefreshRadius;
end;
-procedure RefreshRad;
+procedure Move(const AX, AY: ShortInt);
+begin
+ PutAt(Player.X + AX, Player.Y + AY);
+end;
+
+procedure PutAt(const AX, AY: ShortInt);
var
- X, Y: Integer;
+ X, Y, I: Integer;
+begin
+ if not InMap(AX, AY) then Exit;
+ if (MapObj[AX, AY] = reMountain) then Exit;
+ Inc(Player.Turn);
+ for I := 0 to High(City) do
+ begin
+ if (City[I].Owner = reTheEmpire) then
+ if (City[I].CurLevel < City[I].MaxLevel) then
+ begin
+ Inc(City[I].CurLevel);
+ DisciplesRL.City.UpdateRadius(I);
+ end;
+ end;
+ Player.X := AX;
+ Player.Y := AY;
+ RefreshRadius;
+ case MapObj[Player.X, Player.Y] of
+ reBag:
+ begin
+ MapObj[Player.X, Player.Y] := reNone;
+ end;
+ reEnemies:
+ begin
+ MapObj[Player.X, Player.Y] := reNone;
+ end;
+ end;
+ case MapTile[Player.X, Player.Y] of
+ reNeutralCity:
+ begin
+ MapTile[Player.X, Player.Y] := reEmpireCity;
+ DisciplesRL.City.UpdateRadius(DisciplesRL.City.GetCityIndex(Player.X, Player.Y));
+ end;
+ end;
+end;
+
+procedure RefreshRadius;
begin
- for Y := -(Player.Rad + 2) to Player.Rad + 2 do
- for X := -(Player.Rad + 2) to Player.Rad + 2 do
- if (Utils.GetDist(Player.X + X, Player.Y + Y, Player.X, Player.Y) <= Player.Rad) and
- DisciplesRL.Map.InMap(Player.X + X, Player.Y + Y) then
- MapDark[Player.X + X, Player.Y + Y] := reNone;
+ DisciplesRL.Map.UpdateRadius(Player.X, Player.Y, Player.Radius, MapDark, reNone);
end;
end.
diff --git a/sources/DisciplesRL.Resources.pas b/sources/DisciplesRL.Resources.pas
index 3cde834..5f886ea 100644
--- a/sources/DisciplesRL.Resources.pas
+++ b/sources/DisciplesRL.Resources.pas
@@ -5,10 +5,12 @@ interface
uses Vcl.Imaging.PNGImage;
type
- TResEnum = (reNone, reGrass, reUnk, reEnemies, reCursor, rePlayer, reDark, reBag, reCity, reCapital);
+ TResEnum = (reNone, reNeutral, reEmpireTerrain, reUnk, reEnemies, reCursor,
+ rePlayer, reDark, reBag, reNeutralCity, reEmpireCity, reEmpireCapital, reMountain);
type
- TResTypeEnum = (teNone, teTile, teGUI, tePath, teObject, teEnemy, teBag, teCapital, teCity, teRuin);
+ TResTypeEnum = (teNone, teTile, teGUI, tePath, teObject, teEnemy, teBag,
+ teCapital, teCity, teRuin);
type
TResBase = record
@@ -20,7 +22,9 @@ TResBase = record
ResBase: array [TResEnum] of TResBase = (
// None
(FileName: ''; ResType: teNone;),
- // Grass
+ // Neutral
+ (FileName: 'dirt.png'; ResType: teTile;),
+ // Empire terrain
(FileName: 'grass.png'; ResType: teTile;),
// Unknown (?)
(FileName: 'unknown.png'; ResType: teGUI;),
@@ -36,8 +40,12 @@ TResBase = record
(FileName: 'chest.png'; ResType: teBag;),
// City
(FileName: 'city.png'; ResType: teCity;),
+ // City
+ (FileName: 'city.png'; ResType: teCity;),
// Capital
- (FileName: 'castle.png'; ResType: teCapital;)
+ (FileName: 'castle.png'; ResType: teCapital;),
+ // Mountain
+ (FileName: 'mountain.png'; ResType: teObject;)
//
);
@@ -59,7 +67,7 @@ procedure Init;
begin
ResImage[I] := TPNGImage.Create;
if (ResBase[I].FileName <> '') then
- ResImage[I].LoadFromFile(Utils.GetPath('resources') + ResBase[I].FileName);
+ ResImage[I].LoadFromFile(GetPath('resources') + ResBase[I].FileName);
end;
end;
diff --git a/sources/DisciplesRL.Scene.Map.pas b/sources/DisciplesRL.Scene.Map.pas
index 9946f47..818f4a0 100644
--- a/sources/DisciplesRL.Scene.Map.pas
+++ b/sources/DisciplesRL.Scene.Map.pas
@@ -18,6 +18,12 @@ implementation
DisciplesRL.Player,
DisciplesRL.Utils;
+const
+ K_RIGHT = 39;
+ K_LEFT = 37;
+ K_DOWN = 40;
+ K_UP = 38;
+
var
LastMousePos, MousePos: TPoint;
@@ -41,19 +47,28 @@ procedure Render;
begin
if (MapDark[X, Y] = reDark) then
Continue;
- DrawImage(X, Y, ResImage[reGrass]);
- F := (Utils.GetDist(X, Y, Player.X, Player.Y) > Player.Rad) and (MapDark[X, Y] = reNone);
+ case MapTile[X, Y] of
+ reEmpireTerrain, reEmpireCapital, reEmpireCity:
+ DrawImage(X, Y, ResImage[reEmpireTerrain]);
+ else
+ DrawImage(X, Y, ResImage[reNeutral]);
+ end;
+ F := (GetDist(X, Y, Player.X, Player.Y) > Player.Radius) and
+ not(MapTile[X, Y] in [reEmpireTerrain, reEmpireCapital, reEmpireCity]) and (MapDark[X, Y] = reNone);
+ // Capital and Cities
+ if (ResBase[MapTile[X, Y]].ResType in [teCapital, teCity]) then
+ DrawImage(X, Y, ResImage[MapTile[X, Y]]);
//
- if (ResBase[MapTile[X, Y]].ResType in [teEnemy, teBag]) then
+ if (ResBase[MapObj[X, Y]].ResType in [teEnemy, teBag]) then
if F then
DrawImage(X, Y, ResImage[reUnk])
else
- DrawImage(X, Y, ResImage[MapTile[X, Y]]);
- if (ResBase[MapTile[X, Y]].ResType in [teCapital, teCity, teObject]) then
- DrawImage(X, Y, ResImage[MapTile[X, Y]]);
- // Leader
- if (X = Player.X) and (Y = Player.Y) then
- DrawImage(X, Y, ResImage[rePlayer]);
+ DrawImage(X, Y, ResImage[MapObj[X, Y]])
+ else if (MapObj[X, Y] <> reNone) then
+ DrawImage(X, Y, ResImage[MapObj[X, Y]]);
+ // Leader
+ if (X = Player.X) and (Y = Player.Y) then
+ DrawImage(X, Y, ResImage[rePlayer]);
// Fog
if F then
DrawImage(X, Y, ResImage[reDark]);
@@ -70,14 +85,7 @@ procedure Timer;
procedure MouseClick;
begin
if DisciplesRL.Map.InMap(MousePos.X, MousePos.Y) then
- begin
- Player.X := MousePos.X;
- Player.Y := MousePos.Y;
- DisciplesRL.Player.RefreshRad;
- if (MapTile[Player.X, Player.Y] in [reBag, reEnemies]) then
- MapTile[Player.X, Player.Y] := reNone;
-
- end;
+ DisciplesRL.Player.PutAt(MousePos.X, MousePos.Y);
end;
procedure MouseMove(Shift: TShiftState; X, Y: Integer);
@@ -93,7 +101,16 @@ procedure MouseMove(Shift: TShiftState; X, Y: Integer);
procedure KeyDown(var Key: Word; Shift: TShiftState);
begin
-
+ case Key of
+ K_UP:
+ DisciplesRL.Player.Move(0, -1);
+ K_DOWN:
+ DisciplesRL.Player.Move(0, 1);
+ K_LEFT:
+ DisciplesRL.Player.Move(-1, 0);
+ K_RIGHT:
+ DisciplesRL.Player.Move(1, 0);
+ end;
end;
procedure Free;
diff --git a/sources/DisciplesRL.Utils.pas b/sources/DisciplesRL.Utils.pas
index 351619a..8b1292f 100644
--- a/sources/DisciplesRL.Utils.pas
+++ b/sources/DisciplesRL.Utils.pas
@@ -5,30 +5,26 @@ interface
uses
Forms;
-type
- Utils = class(TObject)
- public
- class function GetDist(X1, Y1, X2, Y2: Single): Word;
- class function GetPath(SubDir: string): string;
- class function ShowForm(const Form: TForm): Integer;
- end;
+function GetDist(X1, Y1, X2, Y2: Single): Word;
+function GetPath(SubDir: string): string;
+function ShowForm(const Form: TForm): Integer;
implementation
uses SysUtils;
-class function Utils.GetDist(X1, Y1, X2, Y2: Single): Word;
+function GetDist(X1, Y1, X2, Y2: Single): Word;
begin
Result := Round(Sqrt(Sqr(X2 - X1) + Sqr(Y2 - Y1)));
end;
-class function Utils.GetPath(SubDir: string): string;
+function GetPath(SubDir: string): string;
begin
Result := ExtractFilePath(ParamStr(0));
Result := IncludeTrailingPathDelimiter(Result + SubDir);
end;
-class function Utils.ShowForm(const Form: TForm): Integer;
+function ShowForm(const Form: TForm): Integer;
begin
with Form do
begin
diff --git a/sources/DisciplesRL.dpr b/sources/DisciplesRL.dpr
index 2c7b50b..9b57e0b 100644
--- a/sources/DisciplesRL.dpr
+++ b/sources/DisciplesRL.dpr
@@ -10,7 +10,9 @@ uses
DisciplesRL.Resources in 'DisciplesRL.Resources.pas',
DisciplesRL.Player in 'DisciplesRL.Player.pas',
DisciplesRL.Creatures in 'DisciplesRL.Creatures.pas',
- DisciplesRL.Party in 'DisciplesRL.Party.pas';
+ DisciplesRL.Party in 'DisciplesRL.Party.pas',
+ DisciplesRL.City in 'DisciplesRL.City.pas',
+ DisciplesRL.PathFind in 'DisciplesRL.PathFind.pas';
{$R *.res}
diff --git a/sources/DisciplesRL.dproj b/sources/DisciplesRL.dproj
index 6a10030..09e5c88 100644
--- a/sources/DisciplesRL.dproj
+++ b/sources/DisciplesRL.dproj
@@ -95,6 +95,8 @@
+
+
Cfg_2
Base