From d6fc2026917d55fa12713e3d00004ec461cc5971 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 30 Oct 2025 17:31:00 -0300 Subject: vários andares MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/definitions/actor/Player.tres | 2 +- assets/definitions/tiles/downstairs.tres | 12 ++++++ assets/definitions/tiles/floor.tres | 1 - assets/sprites/tiles/downstairs.png | Bin 0 -> 168 bytes assets/sprites/tiles/downstairs.png.import | 40 ++++++++++++++++++ project.godot | 5 +++ scenes/Game.tscn | 3 +- scripts/Entities/Actions/TakeStairsAction.cs | 28 +++++++++++++ scripts/Entities/Actions/TakeStairsAction.cs.uid | 1 + scripts/InputHandling/MainGameInputHandler.cs | 5 +++ scripts/Map/DungeonGenerator.cs | 32 ++++++--------- scripts/Map/FieldOfView.cs | 11 +++++ scripts/Map/Map.cs | 50 +++++++++++++++++++++-- scripts/Map/MapData.cs | 10 +++++ scripts/Map/Tile.cs | 6 ++- scripts/Utils/SignalBus.cs | 3 ++ 16 files changed, 182 insertions(+), 27 deletions(-) create mode 100644 assets/definitions/tiles/downstairs.tres create mode 100644 assets/sprites/tiles/downstairs.png create mode 100644 assets/sprites/tiles/downstairs.png.import create mode 100644 scripts/Entities/Actions/TakeStairsAction.cs create mode 100644 scripts/Entities/Actions/TakeStairsAction.cs.uid diff --git a/assets/definitions/actor/Player.tres b/assets/definitions/actor/Player.tres index 4eba7f7..8a4e2c1 100644 --- a/assets/definitions/actor/Player.tres +++ b/assets/definitions/actor/Player.tres @@ -11,7 +11,7 @@ deathTexture = ExtResource("1_m72ac") Hp = 36 Mp = 12 Atk = 8 -Def = 2 +Def = 10 Men = 3 name = "Jogador" texture = ExtResource("3_m72ac") diff --git a/assets/definitions/tiles/downstairs.tres b/assets/definitions/tiles/downstairs.tres new file mode 100644 index 0000000..5b6c23a --- /dev/null +++ b/assets/definitions/tiles/downstairs.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="TileDefinition" load_steps=3 format=3 uid="uid://ch688yvi87hl5"] + +[ext_resource type="Script" uid="uid://ba82a33ov6uuo" path="res://scripts/Map/TileDefinition.cs" id="1_pedoq"] +[ext_resource type="Texture2D" uid="uid://c6d3vikw7v8d7" path="res://assets/sprites/tiles/downstairs.png" id="1_voylm"] + +[resource] +script = ExtResource("1_pedoq") +Texture = ExtResource("1_voylm") +DarkColor = Color(0.27450982, 0.27450982, 0.27450982, 1) +IsWalkable = true +IsTransparent = true +metadata/_custom_type_script = "uid://ba82a33ov6uuo" diff --git a/assets/definitions/tiles/floor.tres b/assets/definitions/tiles/floor.tres index 44b0097..70bbb68 100644 --- a/assets/definitions/tiles/floor.tres +++ b/assets/definitions/tiles/floor.tres @@ -6,7 +6,6 @@ [resource] script = ExtResource("1_snxyj") Texture = ExtResource("1_vvyfi") -LitColor = Color(1, 1, 1, 1) DarkColor = Color(0.272655, 0.272655, 0.272655, 1) IsWalkable = true IsTransparent = true diff --git a/assets/sprites/tiles/downstairs.png b/assets/sprites/tiles/downstairs.png new file mode 100644 index 0000000..34cb872 Binary files /dev/null and b/assets/sprites/tiles/downstairs.png differ diff --git a/assets/sprites/tiles/downstairs.png.import b/assets/sprites/tiles/downstairs.png.import new file mode 100644 index 0000000..b2240cb --- /dev/null +++ b/assets/sprites/tiles/downstairs.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c6d3vikw7v8d7" +path="res://.godot/imported/downstairs.png-426496fa50b43c52de7237b978e7f7d9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/tiles/downstairs.png" +dest_files=["res://.godot/imported/downstairs.png-426496fa50b43c52de7237b978e7f7d9.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/project.godot b/project.godot index 30b0f6f..5ee82d7 100644 --- a/project.godot +++ b/project.godot @@ -114,6 +114,11 @@ open-spellbook={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":90,"physical_keycode":0,"key_label":0,"unicode":122,"location":0,"echo":false,"script":null) ] } +descend={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":46,"physical_keycode":0,"key_label":0,"unicode":62,"location":0,"echo":false,"script":null) +] +} [rendering] diff --git a/scenes/Game.tscn b/scenes/Game.tscn index 90bf37a..e9bd9d2 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -23,8 +23,9 @@ script = ExtResource("3_cpr0p") [node name="Generator" type="Node" parent="Map"] script = ExtResource("4_78awf") +width = 30 +height = 20 useSeed = false -iterations = 6 [node name="FieldOfView" type="Node" parent="Map"] script = ExtResource("5_s0nni") diff --git a/scripts/Entities/Actions/TakeStairsAction.cs b/scripts/Entities/Actions/TakeStairsAction.cs new file mode 100644 index 0000000..17fa7e5 --- /dev/null +++ b/scripts/Entities/Actions/TakeStairsAction.cs @@ -0,0 +1,28 @@ +using Godot; +using TheLegendOfGustav.Entities.Actors; +using TheLegendOfGustav.Utils; + +namespace TheLegendOfGustav.Entities.Actions; + +public partial class TakeStairsAction : Action +{ + public TakeStairsAction(Actor actor) : base(actor) + { + cost = 0; + } + + public override bool Perform() + { + if (Actor.GridPosition == MapData.DownstairsLocation) + { + SignalBus.Instance.EmitSignal(SignalBus.SignalName.PlayerDescent); + MessageLogData.Instance.AddMessage("Você desce as escadas..."); + return true; + } + else + { + MessageLogData.Instance.AddMessage("Não tem escadas aqui..."); + return false; + } + } +} \ No newline at end of file diff --git a/scripts/Entities/Actions/TakeStairsAction.cs.uid b/scripts/Entities/Actions/TakeStairsAction.cs.uid new file mode 100644 index 0000000..03b2448 --- /dev/null +++ b/scripts/Entities/Actions/TakeStairsAction.cs.uid @@ -0,0 +1 @@ +uid://c0adtd8ynoh4q diff --git a/scripts/InputHandling/MainGameInputHandler.cs b/scripts/InputHandling/MainGameInputHandler.cs index bbfb9ca..a18bd73 100644 --- a/scripts/InputHandling/MainGameInputHandler.cs +++ b/scripts/InputHandling/MainGameInputHandler.cs @@ -63,6 +63,11 @@ public partial class MainGameInputHandler : BaseInputHandler action = new EscapeAction(player); } + if (Input.IsActionJustPressed("descend")) + { + action = new TakeStairsAction(player); + } + return action; } } 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; @@ -35,16 +36,6 @@ public partial class DungeonGenerator : Node [Export] private int height = 60; - /// - /// Qual seed utilizar. - /// - [Export] - private ulong seed; - /// - /// Se será utilizada a nossa seed ou a seed padrão da classe RandomNumberGenerator. - /// - [Export] - private bool useSeed = true; /// /// Quantas iterações do algoritmo chamar. /// @@ -73,14 +64,6 @@ public partial class DungeonGenerator : Node #endregion #region Methods - public override void _Ready() - { - base._Ready(); - if (useSeed) - { - rng.Seed = seed; - } - } /// /// Gera um andar da masmorra. @@ -89,9 +72,12 @@ public partial class DungeonGenerator : Node /// /// Jogador. /// O mapa gerado. - 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(); } + /// + /// 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. + /// + 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. /// 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"); tilesNode = GetNode("Tiles"); entitiesNode = GetNode("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").MakeCurrent(); + fieldOfView.ResetFOV(); + UpdateFOV(player.GridPosition); } /// /// Cria um andar da masmorra utilizando o gerador de mapa. /// /// O gerador de mapas precisa do jogador. - 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); } /// @@ -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; } /// /// 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> serializedTiles = (Array>)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 } /// @@ -22,7 +23,8 @@ public partial class Tile : Sprite2D, ISaveable private static readonly Godot.Collections.Dictionary Types = new() { {TileType.WALL, GD.Load("res://assets/definitions/tiles/wall.tres")}, - {TileType.FLOOR, GD.Load("res://assets/definitions/tiles/floor.tres")} + {TileType.FLOOR, GD.Load("res://assets/definitions/tiles/floor.tres")}, + {TileType.DOWN_STAIRS, GD.Load("res://assets/definitions/tiles/downstairs.tres")} }; TileType key; diff --git a/scripts/Utils/SignalBus.cs b/scripts/Utils/SignalBus.cs index 291ffcd..a7eccf8 100644 --- a/scripts/Utils/SignalBus.cs +++ b/scripts/Utils/SignalBus.cs @@ -34,6 +34,9 @@ public partial class SignalBus : Node [Signal] public delegate void EscapeRequestedEventHandler(); + [Signal] + public delegate void PlayerDescentEventHandler(); + public override void _Ready() { base._Ready(); -- cgit v1.2.3