summaryrefslogtreecommitdiff
path: root/scripts/map
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/map')
-rw-r--r--scripts/map/FieldOfView.cs94
-rw-r--r--scripts/map/FieldOfView.cs.uid1
-rw-r--r--scripts/map/Map.cs19
-rw-r--r--scripts/map/MapData.cs4
-rw-r--r--scripts/map/Tile.cs25
-rw-r--r--scripts/map/TileDefinition.cs2
6 files changed, 143 insertions, 2 deletions
diff --git a/scripts/map/FieldOfView.cs b/scripts/map/FieldOfView.cs
new file mode 100644
index 0000000..eee1ae9
--- /dev/null
+++ b/scripts/map/FieldOfView.cs
@@ -0,0 +1,94 @@
+using Godot;
+
+// Copiado e adaptado deste cara aqui: https://www.roguebasin.com/index.php?title=C%2B%2B_shadowcasting_implementation e deste também https://selinadev.github.io/08-rogueliketutorial-04/
+
+public partial class FieldOfView : Node {
+
+ private Godot.Collections.Array<Tile> fov = [];
+
+ private static int[,] multipliers = new int[4,8]{
+ {1, 0, 0, -1, -1, 0, 0, 1},
+ {0, 1, -1, 0, 0, -1, 1, 0},
+ {0, 1, 1, 0, 0, -1, -1, 0},
+ {1, 0, 0, 1, -1, 0, 0, -1}
+ };
+ private void CastLight(MapData data, Vector2I pos, int radius, int row, float startSlope, float endSlope, int xx, int xy, int yx, int yy) {
+ if (startSlope < endSlope) {
+ return;
+ }
+
+ float nextStartSlope = startSlope;
+ for (int i = row; i <= radius; i++)
+ {
+ bool blocked = false;
+ for (int dx = -i, dy = -i; dx <= 0; dx++)
+ {
+ float lSlope = (float)((dx - 0.5) / (dy + 0.5));
+ float rSlope = (float)((dx + 0.5) / (dy - 0.5));
+
+ if (startSlope < rSlope)
+ {
+ continue;
+ }
+ else if (endSlope > lSlope)
+ {
+ break;
+ }
+
+ int sax = dx * xx + dy * xy;
+ int say = dx * yx + dy * yy;
+
+ if ((sax < 0 && int.Abs(sax) > pos.X) || (say < 0 && int.Abs(say) > pos.Y)) {
+ continue;
+ }
+ int ax = pos.X + sax;
+ int ay = pos.Y + say;
+
+ if (ax >= data.Width || ay >= data.Height) {
+ continue;
+ }
+
+ Tile currentTile = data.GetTile(ax, ay);
+ int radius2 = radius * radius;
+ if ((dx * dx + dy * dy) < radius2) {
+ currentTile.IsInView = true;
+ fov.Add(currentTile);
+ }
+
+ if (blocked) {
+ if (!currentTile.IsTransparent) {
+ nextStartSlope = rSlope;
+ continue;
+ } else {
+ blocked = false;
+ startSlope = nextStartSlope;
+ }
+ } else if (!currentTile.IsTransparent) {
+ blocked = true;
+ nextStartSlope = rSlope;
+ CastLight(data, pos, radius, i + 1, startSlope, lSlope, xx, xy, yx, yy);
+ }
+ }
+ if (blocked) {
+ break;
+ }
+ }
+ }
+
+ private void ClearFOV() {
+ foreach (Tile tile in fov) {
+ tile.IsInView = false;
+ }
+ fov.Clear();
+ }
+
+ public void UpdateFOV(MapData data, Vector2I position, int radius) {
+ ClearFOV();
+ Tile start = data.GetTile(position);
+ start.IsInView = true;
+ fov.Add(start);
+ for (int i = 0; i < 8; i++) {
+ CastLight(data, position, radius, 1, 1.0f, 0.0f, multipliers[0, i], multipliers[1, i], multipliers[2, i], multipliers[3, i]);
+ }
+ }
+} \ No newline at end of file
diff --git a/scripts/map/FieldOfView.cs.uid b/scripts/map/FieldOfView.cs.uid
new file mode 100644
index 0000000..a173ff3
--- /dev/null
+++ b/scripts/map/FieldOfView.cs.uid
@@ -0,0 +1 @@
+uid://bereyrj1s46y5
diff --git a/scripts/map/Map.cs b/scripts/map/Map.cs
index 683ae45..41bd7f8 100644
--- a/scripts/map/Map.cs
+++ b/scripts/map/Map.cs
@@ -5,8 +5,21 @@ public partial class Map : Node2D
{
public MapData Map_Data { get; private set; }
+ [Export]
+ private int fovRadius = 12;
+
DungeonGenerator generator;
+ FieldOfView fieldOfView;
+
+ public override void _Ready()
+ {
+ base._Ready();
+
+ generator = GetNode<DungeonGenerator>("Generator");
+ fieldOfView = GetNode<FieldOfView>("FieldOfView");
+ }
+
private void PlaceTiles() {
foreach (Tile tile in Map_Data.Tiles) {
AddChild(tile);
@@ -15,8 +28,6 @@ public partial class Map : Node2D
public void Generate(Player player)
{
- generator = GetNode<DungeonGenerator>("Generator");
-
Map_Data = generator.GenerateDungeon(player);
Map_Data.InsertActor(player);
@@ -25,4 +36,8 @@ public partial class Map : Node2D
PlaceTiles();
}
+
+ public void UpdateFOV(Vector2I pos) {
+ fieldOfView.UpdateFOV(Map_Data, pos, fovRadius);
+ }
}
diff --git a/scripts/map/MapData.cs b/scripts/map/MapData.cs
index c580aa8..1aba35d 100644
--- a/scripts/map/MapData.cs
+++ b/scripts/map/MapData.cs
@@ -60,6 +60,10 @@ public partial class MapData : RefCounted
return Tiles[index];
}
+ public Tile GetTile(int x, int y) {
+ return GetTile(new Vector2I(x, y));
+ }
+
public Actor GetBlockingActorAtPosition(Vector2I pos) {
foreach (Actor actor in Actors) {
if (actor.GridPosition == pos && actor.BlocksMovement) {
diff --git a/scripts/map/Tile.cs b/scripts/map/Tile.cs
index 865cbbd..e050701 100644
--- a/scripts/map/Tile.cs
+++ b/scripts/map/Tile.cs
@@ -6,10 +6,34 @@ public partial class Tile : Sprite2D
private TileDefinition definition;
public bool IsWalkable { get; private set; }
+ public bool IsTransparent { get; private set; }
+
+ private bool isExplored = false;
+ public bool IsExplored {
+ get => this.isExplored;
+ set {
+ isExplored = value;
+ if (IsExplored && !Visible) {
+ Visible = true;
+ }
+ }
+ }
+
+ private bool isInView = false;
+ public bool IsInView {
+ get => this.isInView;
+ set {
+ this.isInView = value;
+ if (IsInView && !IsExplored) {
+ IsExplored = true;
+ }
+ }
+ }
public Tile(Vector2I pos, TileDefinition definition)
{
Centered = false;
+ Visible = false;
Position = Grid.GridToWorld(pos);
SetDefinition(definition);
}
@@ -18,5 +42,6 @@ public partial class Tile : Sprite2D
this.definition = definition;
Texture = definition.Texture;
IsWalkable = definition.IsWalkable;
+ IsTransparent = definition.IsTransparent;
}
}
diff --git a/scripts/map/TileDefinition.cs b/scripts/map/TileDefinition.cs
index 548fda7..fbd14a1 100644
--- a/scripts/map/TileDefinition.cs
+++ b/scripts/map/TileDefinition.cs
@@ -11,4 +11,6 @@ public partial class TileDefinition : Resource
[ExportCategory("Mechanics")]
[Export]
public bool IsWalkable { get; set; }
+ [Export]
+ public bool IsTransparent { get; set; }
}