summaryrefslogtreecommitdiff
path: root/scripts/Map
diff options
context:
space:
mode:
authorMatheus <matheus.guedes.mg.m@gmail.com>2025-10-30 17:31:00 -0300
committerMatheus <matheus.guedes.mg.m@gmail.com>2025-10-30 17:31:06 -0300
commitd6fc2026917d55fa12713e3d00004ec461cc5971 (patch)
tree54fc79f9f8a217b2477721e21875e74c1736564e /scripts/Map
parente40bc38dcc17ebeb40722bedb94a6459e47b9aeb (diff)
vários andares
Diffstat (limited to 'scripts/Map')
-rw-r--r--scripts/Map/DungeonGenerator.cs32
-rw-r--r--scripts/Map/FieldOfView.cs11
-rw-r--r--scripts/Map/Map.cs50
-rw-r--r--scripts/Map/MapData.cs10
-rw-r--r--scripts/Map/Tile.cs6
5 files changed, 85 insertions, 24 deletions
diff --git a/scripts/Map/DungeonGenerator.cs b/scripts/Map/DungeonGenerator.cs
index 2d5ef8d..2b24e8a 100644
--- a/scripts/Map/DungeonGenerator.cs
+++ b/scripts/Map/DungeonGenerator.cs
@@ -2,6 +2,7 @@ using Godot;
using TheLegendOfGustav.Entities.Actors;
using TheLegendOfGustav.Entities;
using TheLegendOfGustav.Entities.Items;
+using System;
namespace TheLegendOfGustav.Map;
@@ -36,16 +37,6 @@ public partial class DungeonGenerator : Node
private int height = 60;
/// <summary>
- /// Qual seed utilizar.
- /// </summary>
- [Export]
- private ulong seed;
- /// <summary>
- /// Se será utilizada a nossa seed ou a seed padrão da classe RandomNumberGenerator.
- /// </summary>
- [Export]
- private bool useSeed = true;
- /// <summary>
/// Quantas iterações do algoritmo chamar.
/// </summary>
[Export]
@@ -73,14 +64,6 @@ public partial class DungeonGenerator : Node
#endregion
#region Methods
- public override void _Ready()
- {
- base._Ready();
- if (useSeed)
- {
- rng.Seed = seed;
- }
- }
/// <summary>
/// Gera um andar da masmorra.
@@ -89,9 +72,12 @@ public partial class DungeonGenerator : Node
/// </summary>
/// <param name="player">Jogador.</param>
/// <returns>O mapa gerado.</returns>
- public MapData GenerateDungeon(Player player)
+ public MapData GenerateDungeon(Player player, int currentFloor)
{
+ rng.Seed = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds();
+
MapData data = new MapData(width, height, player);
+ data.CurrentFloor = currentFloor;
// Divisão mestre que engloba o mapa inteiro.
MapDivision root = new MapDivision(0, 0, width, height);
@@ -104,6 +90,8 @@ public partial class DungeonGenerator : Node
// Coloca os corredores.
TunnelDivisions(data, root);
+ Rect2I lastRoom = new(0, 0, 0, 0);
+
// Cria as salas com base nas divisões geradas.
foreach (MapDivision division in root.GetLeaves())
{
@@ -127,8 +115,14 @@ public partial class DungeonGenerator : Node
}
// Colocamos os inimigos na sala.
PlaceEntities(data, room);
+
+ lastRoom = room;
}
+ data.DownstairsLocation = lastRoom!.GetCenter();
+ Tile downTile = data.GetTile(data.DownstairsLocation);
+ downTile.Key = TileType.DOWN_STAIRS;
+
// Feito o mapa, inicializamos o algoritmo de pathfinding.
data.SetupPathfinding();
return data;
diff --git a/scripts/Map/FieldOfView.cs b/scripts/Map/FieldOfView.cs
index 40df320..474c1ca 100644
--- a/scripts/Map/FieldOfView.cs
+++ b/scripts/Map/FieldOfView.cs
@@ -101,6 +101,17 @@ public partial class FieldOfView : Node
fov.Clear();
}
+ /// <summary>
+ /// Diferença de ClearFOV: não referencia tiles.
+ /// No contexto onde ResetFOV é chamado, os tiles não
+ /// podem ser referenciados porque já foram liberados da
+ /// memória.
+ /// </summary>
+ public void ResetFOV()
+ {
+ fov.Clear();
+ }
+
public void UpdateFOV(MapData data, Vector2I position, int radius)
{
ClearFOV();
diff --git a/scripts/Map/Map.cs b/scripts/Map/Map.cs
index 04ccabd..2913c1f 100644
--- a/scripts/Map/Map.cs
+++ b/scripts/Map/Map.cs
@@ -2,6 +2,7 @@ using System.Net.Http.Headers;
using Godot;
using TheLegendOfGustav.Entities;
using TheLegendOfGustav.Entities.Actors;
+using TheLegendOfGustav.Utils;
namespace TheLegendOfGustav.Map;
@@ -30,7 +31,11 @@ public partial class Map : Node2D
/// Dados do mapa.
/// </summary>
public MapData MapData { get; private set; }
-
+
+ [Signal]
+ public delegate void DungeonFloorChangedEventHandler(int floor);
+
+ private SignalBus.PlayerDescentEventHandler joinSignal;
public override void _Ready()
{
base._Ready();
@@ -39,20 +44,46 @@ public partial class Map : Node2D
fieldOfView = GetNode<FieldOfView>("FieldOfView");
tilesNode = GetNode<Node2D>("Tiles");
entitiesNode = GetNode<Node2D>("Entities");
+
+ joinSignal = () => NextFloor();
+ SignalBus.Instance.PlayerDescent += joinSignal;
+ }
+
+ void NextFloor()
+ {
+ Player player = MapData.Player;
+ entitiesNode.RemoveChild(player);
+
+ foreach (var entity in entitiesNode.GetChildren())
+ {
+ entity.QueueFree();
+ }
+
+ foreach (var tile in tilesNode.GetChildren())
+ {
+ tile.QueueFree();
+ }
+
+ Generate(player, MapData.CurrentFloor + 1);
+ player.GetNode<Camera2D>("Camera2D").MakeCurrent();
+ fieldOfView.ResetFOV();
+ UpdateFOV(player.GridPosition);
}
/// <summary>
/// Cria um andar da masmorra utilizando o gerador de mapa.
/// </summary>
/// <param name="player">O gerador de mapas precisa do jogador.</param>
- public void Generate(Player player)
+ public void Generate(Player player, int currentFloor = 1)
{
- MapData = generator.GenerateDungeon(player);
+ MapData = generator.GenerateDungeon(player, currentFloor);
MapData.EntityPlaced += OnEntityPlaced;
PlaceTiles();
PlaceEntities();
+
+ EmitSignal(SignalName.DungeonFloorChanged, currentFloor);
}
/// <summary>
@@ -111,6 +142,19 @@ public partial class Map : Node2D
PlaceEntities();
MapData.EntityPlaced += OnEntityPlaced;
+ EmitSignal(SignalName.DungeonFloorChanged, MapData.CurrentFloor);
return true;
}
+
+ public override void _Notification(int what)
+ {
+ if (what == NotificationPredelete)
+ {
+ if (joinSignal != null)
+ {
+ SignalBus.Instance.PlayerDescent -= joinSignal;
+ }
+ }
+ base._Notification(what);
+ }
}
diff --git a/scripts/Map/MapData.cs b/scripts/Map/MapData.cs
index 5f96743..907e8d0 100644
--- a/scripts/Map/MapData.cs
+++ b/scripts/Map/MapData.cs
@@ -84,6 +84,10 @@ public partial class MapData : RefCounted, ISaveable
return list;
}
}
+
+ public int CurrentFloor { get; set; } = 0;
+
+ public Vector2I DownstairsLocation { get; set; }
/// <summary>
/// Objeto do Godot que utiliza do algoritmo A* para calcular
/// caminhos e rotas.
@@ -349,6 +353,9 @@ public partial class MapData : RefCounted, ISaveable
{"player", Player.GetSaveData()},
{"width", Width},
{"height", Height},
+ {"current_floor", CurrentFloor},
+ {"down_stairs_location_x", DownstairsLocation.X},
+ {"down_stairs_location_y", DownstairsLocation.Y}
};
}
@@ -357,6 +364,9 @@ public partial class MapData : RefCounted, ISaveable
Width = (int)saveData["width"];
Height = (int)saveData["height"];
+ CurrentFloor = (int)saveData["current_floor"];
+ DownstairsLocation = new((int)saveData["down_stairs_location_x"], (int)saveData["down_stairs_location_y"]);
+
SetupTiles();
Array<Dictionary<string, Variant>> serializedTiles = (Array<Dictionary<string, Variant>>)saveData["tiles"];
diff --git a/scripts/Map/Tile.cs b/scripts/Map/Tile.cs
index 6790f3e..03039e0 100644
--- a/scripts/Map/Tile.cs
+++ b/scripts/Map/Tile.cs
@@ -8,7 +8,8 @@ namespace TheLegendOfGustav.Map;
public enum TileType
{
WALL,
- FLOOR
+ FLOOR,
+ DOWN_STAIRS
}
/// <summary>
@@ -22,7 +23,8 @@ public partial class Tile : Sprite2D, ISaveable
private static readonly Godot.Collections.Dictionary<TileType, TileDefinition> Types = new()
{
{TileType.WALL, GD.Load<TileDefinition>("res://assets/definitions/tiles/wall.tres")},
- {TileType.FLOOR, GD.Load<TileDefinition>("res://assets/definitions/tiles/floor.tres")}
+ {TileType.FLOOR, GD.Load<TileDefinition>("res://assets/definitions/tiles/floor.tres")},
+ {TileType.DOWN_STAIRS, GD.Load<TileDefinition>("res://assets/definitions/tiles/downstairs.tres")}
};
TileType key;