summaryrefslogtreecommitdiff
path: root/scripts/Map
diff options
context:
space:
mode:
authorMatheus <matheus.guedes.mg.m@gmail.com>2025-10-26 20:02:15 -0300
committerMatheus <matheus.guedes.mg.m@gmail.com>2025-10-26 20:02:15 -0300
commitf4ed469fc9eaeebf39093fbf6601581cc10c6e2f (patch)
treed8f29ae3288e950b5fb1f5251845d57949ca2ac0 /scripts/Map
parent639cd8cef403e9e66bf31e7888e786effac2b292 (diff)
feat:save AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
O vazio dentro de mim é como uma xícara de café esquecida no canto da mesa.
Diffstat (limited to 'scripts/Map')
-rw-r--r--scripts/Map/DungeonGenerator.cs2
-rw-r--r--scripts/Map/Map.cs18
-rw-r--r--scripts/Map/MapData.cs120
-rw-r--r--scripts/Map/Tile.cs49
4 files changed, 181 insertions, 8 deletions
diff --git a/scripts/Map/DungeonGenerator.cs b/scripts/Map/DungeonGenerator.cs
index 7e447b0..2d5ef8d 100644
--- a/scripts/Map/DungeonGenerator.cs
+++ b/scripts/Map/DungeonGenerator.cs
@@ -144,7 +144,7 @@ public partial class DungeonGenerator : Node
Tile tile = data.GetTile(pos);
if (tile == null) return;
- tile.SetDefinition(MapData.floorDefinition);
+ tile.Key = TileType.FLOOR;
}
/// <summary>
diff --git a/scripts/Map/Map.cs b/scripts/Map/Map.cs
index 8521797..04ccabd 100644
--- a/scripts/Map/Map.cs
+++ b/scripts/Map/Map.cs
@@ -1,3 +1,4 @@
+using System.Net.Http.Headers;
using Godot;
using TheLegendOfGustav.Entities;
using TheLegendOfGustav.Entities.Actors;
@@ -95,4 +96,21 @@ public partial class Map : Node2D
{
entitiesNode.AddChild(entity);
}
+
+ public bool LoadGame(Player player)
+ {
+
+ MapData = new(0, 0, player);
+
+ if (!MapData.LoadGame())
+ {
+ return false;
+ }
+
+ PlaceTiles();
+ PlaceEntities();
+
+ MapData.EntityPlaced += OnEntityPlaced;
+ return true;
+ }
}
diff --git a/scripts/Map/MapData.cs b/scripts/Map/MapData.cs
index 49e4ca0..5f96743 100644
--- a/scripts/Map/MapData.cs
+++ b/scripts/Map/MapData.cs
@@ -1,4 +1,5 @@
using Godot;
+using Godot.Collections;
using TheLegendOfGustav.Entities;
using TheLegendOfGustav.Entities.Actors;
using TheLegendOfGustav.Entities.Items;
@@ -10,11 +11,9 @@ namespace TheLegendOfGustav.Map;
/// O mapa é o cenário onde as ações do jogo ocorrem.
/// Mais especificamente, o mapa é um único andar da masmorra.
/// </summary>
-public partial class MapData : RefCounted
+public partial class MapData : RefCounted, ISaveable
{
#region Fields
- public static readonly TileDefinition wallDefinition = GD.Load<TileDefinition>("res://assets/definitions/tiles/wall.tres");
- public static readonly TileDefinition floorDefinition = GD.Load<TileDefinition>("res://assets/definitions/tiles/floor.tres");
/// <summary>
/// Peso do ator no pathfinder.
/// A IA irá evitar de passar por espaços com peso alto.
@@ -275,11 +274,16 @@ public partial class MapData : RefCounted
/// </summary>
private void SetupTiles()
{
+ if (Tiles.Count > 1)
+ {
+ Tiles.Clear();
+ }
+
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
- Tiles.Add(new Tile(new Vector2I(j, i), wallDefinition));
+ Tiles.Add(new Tile(new Vector2I(j, i), TileType.WALL));
}
}
}
@@ -314,5 +318,113 @@ public partial class MapData : RefCounted
return true;
}
+
+ public Dictionary<string, Variant> GetSaveData()
+ {
+ Array<Dictionary<string, Variant>> serializedTiles = [];
+ Array<Dictionary<string, Variant>> serializedItemEntities = [];
+ Array<Dictionary<string, Variant>> serializedEnemies = [];
+ foreach (Tile tile in Tiles)
+ {
+ serializedTiles.Add(tile.GetSaveData());
+ }
+
+ foreach (Entity ent in Entities)
+ {
+ if (ent is Enemy enemy)
+ {
+ serializedEnemies.Add(enemy.GetSaveData());
+ }
+ else if (ent is ItemEntity it)
+ {
+ serializedItemEntities.Add(it.GetSaveData());
+ }
+ }
+
+ return new()
+ {
+ {"tiles", serializedTiles},
+ {"enemies", serializedEnemies},
+ {"items", serializedItemEntities},
+ {"player", Player.GetSaveData()},
+ {"width", Width},
+ {"height", Height},
+ };
+ }
+
+ public bool LoadSaveData(Dictionary<string, Variant> saveData)
+ {
+ Width = (int)saveData["width"];
+ Height = (int)saveData["height"];
+
+ SetupTiles();
+
+ Array<Dictionary<string, Variant>> serializedTiles = (Array<Dictionary<string, Variant>>)saveData["tiles"];
+ Array<Dictionary<string, Variant>> serializedItemEntities = (Array<Dictionary<string, Variant>>)saveData["items"];
+ Array<Dictionary<string, Variant>> serializedEnemies = (Array<Dictionary<string, Variant>>)saveData["enemies"];
+
+ for (int i = 0; i < serializedTiles.Count; i++)
+ {
+ if (!Tiles[i].LoadSaveData(serializedTiles[i]))
+ {
+ return false;
+ }
+ }
+ SetupPathfinding();
+ if (!Player.LoadSaveData((Dictionary<string, Variant>)saveData["player"]))
+ {
+ return false;
+ }
+
+ Player.MapData = this;
+
+ foreach(Dictionary<string, Variant> enemy in serializedEnemies)
+ {
+ Enemy en = new(Vector2I.Zero, this);
+ if (!en.LoadSaveData(enemy))
+ {
+ return false;
+ }
+
+ InsertEntity(en);
+ }
+
+ foreach(Dictionary<string, Variant> item in serializedItemEntities)
+ {
+ ItemEntity en = new(Vector2I.Zero, this);
+
+ if (!en.LoadSaveData(item))
+ {
+ return false;
+ }
+
+ InsertEntity(en);
+ }
+
+ return true;
+ }
+
+ public void SaveGame()
+ {
+ using var saveFile = FileAccess.Open("user://save_game.json", FileAccess.ModeFlags.Write);
+ var saveData = GetSaveData();
+ string saveString = Json.Stringify(saveData);
+
+ saveFile.StoreLine(saveString);
+ }
+
+ public bool LoadGame()
+ {
+ using var saveFile = FileAccess.Open("user://save_game.json", FileAccess.ModeFlags.Read);
+ string saveString = saveFile.GetLine();
+ var saveData = (Dictionary<string, Variant>)Json.ParseString(saveString);
+
+ if (!LoadSaveData(saveData))
+ {
+ return false;
+ }
+
+ return true;
+ }
#endregion
}
diff --git a/scripts/Map/Tile.cs b/scripts/Map/Tile.cs
index 488d124..6790f3e 100644
--- a/scripts/Map/Tile.cs
+++ b/scripts/Map/Tile.cs
@@ -1,16 +1,41 @@
+using System.Threading;
using Godot;
+using Godot.Collections;
using TheLegendOfGustav.Utils;
namespace TheLegendOfGustav.Map;
+public enum TileType
+{
+ WALL,
+ FLOOR
+}
+
/// <summary>
/// O mundo do jogo é composto por Tiles.
/// Um tile é um quadrado de 16x16 que representa uma
/// unidade discreta do cenário. Tiles podem agir como
/// parede, chão, ou outras funções.
/// </summary>
-public partial class Tile : Sprite2D
+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 key;
+ public TileType Key
+ {
+ get => key;
+ set
+ {
+ key = value;
+ SetDefinition(Types[value]);
+ }
+ }
+
private bool isExplored = false;
private bool isInView = false;
@@ -19,7 +44,7 @@ public partial class Tile : Sprite2D
/// </summary>
private TileDefinition definition;
- public Tile(Vector2I pos, TileDefinition definition)
+ public Tile(Vector2I pos, TileType type)
{
// Tile herda da classe Sprite2D.
// Por padrão, a posição do Sprite2D é no centro de sua textura.
@@ -29,7 +54,7 @@ public partial class Tile : Sprite2D
// Tiles começam invisíveis porque não foram vistos pelo jogador.
Visible = false;
Position = Grid.GridToWorld(pos);
- SetDefinition(definition);
+ Key = type;
}
/// <summary>
@@ -89,4 +114,22 @@ public partial class Tile : Sprite2D
IsWalkable = definition.IsWalkable;
IsTransparent = definition.IsTransparent;
}
+
+ public Dictionary<string, Variant> GetSaveData()
+ {
+ return new()
+ {
+ {"key", (int)Key},
+ {"is_explored", IsExplored}
+ };
+ }
+
+ public bool LoadSaveData(Dictionary<string, Variant> saveData)
+ {
+ // É o seguinte, não tenho tempo, não vou verificar se a entrada está correta.
+ Key = (TileType)(int)saveData["key"];
+
+ IsExplored = (bool)saveData["is_explored"];
+ return true;
+ }
}