diff --git a/Globals/FunkEngineNameSpace.cs b/Globals/FunkEngineNameSpace.cs index a280d737..c73800f6 100644 --- a/Globals/FunkEngineNameSpace.cs +++ b/Globals/FunkEngineNameSpace.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using FunkEngine.Classes.MidiMaestro; using Godot; @@ -251,6 +252,13 @@ public enum Stages Quit, Map, Load, + Continue, +} + +public enum Area +{ + Forest = 0, + City = 1, } public enum Rarity @@ -308,59 +316,111 @@ public void AddChild(int newIdx) } } + //TODO: Make odds for rooms based on y-level, e.g. elites only spawn on y > 3 + public struct MapConfig + { + public int Width { get; private set; } + public int Height { get; private set; } + public int Paths { get; private set; } + + /// + /// Rooms that exist at set levels, only one room can be set per y-level. + /// + public Dictionary SetRooms { get; private set; } = + new() + { + { 0, Stages.Battle }, //The first, e.g. y = 0 room, should always be a battle. + }; + + public const int NumStages = 2; + + public static readonly Stages[] StagsToRoll = new[] { Stages.Battle, Stages.Chest }; + + /// + /// The odds for each stage to appear in a non-set room position. + /// + public float[] StageOdds = new float[2]; + + public MapConfig(int width, int height, int paths, float[] odds) + { + Width = width; + Height = height; + Paths = paths; + for (int i = 0; i < NumStages; i++) + { + StageOdds[i] = odds[i]; + } + } + + /// + /// Adds a set room type to be generated guaranteed. Additional entries in the same y-level are ignored. + /// + /// The y-level of the rooms + /// The room type to be set. + public MapConfig AddSetRoom(int height, Stages roomType) + { + SetRooms.TryAdd(height, roomType); + return this; + } + } + /** * Initializes the map with max width, max height, and with number of paths. */ - public void InitMapGrid(int width, int height, int paths) + public void InitMapGrid(MapConfig curConfig) { _curIdx = 0; - _rooms = Array.Empty(); - _map = new int[width, height]; //x,y + _rooms = []; + _map = new int[curConfig.Width, curConfig.Height]; //x,y - int startX = (width / 2); + int startX = (curConfig.Width / 2); _rooms = _rooms.Append(new Room(_curIdx, startX, 0)).ToArray(); _rooms[0].SetType(Stages.Battle); _map[startX, 0] = _curIdx++; - for (int i = 0; i < paths; i++) + for (int i = 0; i < curConfig.Paths; i++) { - GeneratePath_r(startX, 0, width, height); + GeneratePath_r(startX, 0, curConfig); } - CreateCommonChildren(width, height); - AddBossRoom(width, height); + CreateCommonChildren(curConfig.Width, curConfig.Height); + AddBossRoom(curConfig.Width, curConfig.Height); } /**Start at x, y, assume prev room exists. Picks new x pos within +/- 1, attaches recursively*/ - private void GeneratePath_r(int x, int y, int width, int height) + private void GeneratePath_r(int x, int y, MapConfig curConfig) { int nextX = StageProducer.GlobalRng.RandiRange( Math.Max(x - 1, 0), - Math.Min(x + 1, width - 1) + Math.Min(x + 1, curConfig.Width - 1) ); if (_map[nextX, y + 1] == 0) { _rooms = _rooms.Append(new Room(_curIdx, nextX, y + 1)).ToArray(); _map[nextX, y + 1] = _curIdx; _rooms[_map[x, y]].AddChild(_curIdx++); - _rooms[^1].SetType(PickRoomType(x, y)); + _rooms[^1].SetType(PickRoomType(x, y, curConfig)); } else { _rooms[_map[x, y]].AddChild(_map[nextX, y + 1]); } - if (y < height - 2) + if (y < curConfig.Height - 2) { - GeneratePath_r(nextX, y + 1, width, height); + GeneratePath_r(nextX, y + 1, curConfig); } } - private Stages PickRoomType(int x, int y) + private Stages PickRoomType(int x, int y, MapConfig curConfig) { - if (y % 3 == 0) - return Stages.Chest; - if (StageProducer.GlobalRng.Randf() < .08) - return Stages.Chest; - return Stages.Battle; + //If the y has a set room return it. + if (curConfig.SetRooms.TryGetValue(y, out Stages result)) + { + return result; + } + + //Random roll for the room type. + int idx = (int)StageProducer.GlobalRng.RandWeighted(curConfig.StageOdds); + return MapConfig.StagsToRoll[idx]; } //Asserts that if there is a room at the same x, but y+1 they are connected diff --git a/Globals/StageProducer.cs b/Globals/StageProducer.cs index 97770b5a..61679c45 100644 --- a/Globals/StageProducer.cs +++ b/Globals/StageProducer.cs @@ -13,10 +13,28 @@ public partial class StageProducer : Node public static readonly RandomNumberGenerator GlobalRng = new(); - public static Vector2I MapSize { get; } = new(7, 6); //For now, make width an odd number - public static MapGrid Map { get; } = new(); + private static readonly MapGrid.MapConfig FirstMapConfig = new MapGrid.MapConfig( + 7, + 6, + 3, + [10, 1] + ).AddSetRoom(3, Stages.Chest); + + private static readonly MapGrid.MapConfig TestMapConfig = new MapGrid.MapConfig( + 10, + 10, + 5, + [10, 2] + ) + .AddSetRoom(3, Stages.Chest) + .AddSetRoom(6, Stages.Chest); + + private static readonly MapGrid.MapConfig[] MapConfigs = new[] { FirstMapConfig }; + + public static MapGrid Map { get; private set; } = new(); private Stages _curStage = Stages.Title; public static int CurRoom { get; private set; } + public static Area CurArea { get; private set; } = Area.Forest; private Node _curScene; private Node _preloadStage; @@ -53,12 +71,13 @@ private void InitFromCfg() private void GenerateMapConsistent() { GlobalRng.State = GlobalRng.Seed << 5 / 2; //Fudge seed state, to get consistent maps across new/loaded games - Map.InitMapGrid(MapSize.X, MapSize.Y, 3); + Map.InitMapGrid(MapConfigs[(int)CurArea]); } private void StartNewGame() { GlobalRng.Randomize(); + CurArea = Area.Forest; GenerateMapConsistent(); PlayerStats = new PlayerStats(); @@ -112,10 +131,10 @@ public void TransitionFromRoom(int nextRoomIdx) private Task _loadTask; - /** - * To be used from Cartographer. Preloads the scene during transition animation. - * This removes the occasionally noticeable load time for the scene change. - */ + /// + /// To be used from Cartographer. Preloads the scene during transition animation. This removes the occasionally noticeable load time for the scene change. + /// + /// Index of the next room in the map to get the stage from. public void PreloadScene(int nextRoomIdx) { Stages nextStage = Map.GetRooms()[nextRoomIdx].Type; @@ -174,6 +193,10 @@ public void TransitionStage(Stages nextStage, int nextRoomIdx = -1) case Stages.Quit: GetTree().Quit(); return; + case Stages.Continue: + ProgressAreas(); + GetTree().ChangeSceneToFile("res://Scenes/Maps/InBetween.tscn"); + break; default: GD.PushError($"Error Scene Transition is {nextStage}"); break; @@ -227,4 +250,26 @@ public override void _Input(InputEvent @event) return; } } + + #region Area Management + + /// + /// There should always be a mapconfig for each area. It's preferable to crash later if there isn't even a placeholder config. + /// + /// True if there is another area. + public static bool IsMoreAreas() + { + return (int)CurArea + 1 < MapConfigs.Length; + } + + public void ProgressAreas() + { + CurArea += 1; + + Map = new(); + GenerateMapConsistent(); + CurRoom = Map.GetRooms()[0].Idx; + } + + #endregion } diff --git a/Globals/Translations/Translations.csv b/Globals/Translations/Translations.csv index 81994a67..6f9346d4 100644 --- a/Globals/Translations/Translations.csv +++ b/Globals/Translations/Translations.csv @@ -20,6 +20,7 @@ CONTROLS_CHOOSE_BUTTON,Choose new button,选择输入按钮 ESCAPE_MENU_RESUME,Resume,继续 ESCAPE_MENU_QUIT,Quit,退出 ESCAPE_MENU_TITLE,Quit to Title,返回标题 +INBETWEEN_CONTINUE,Continue,继续 CHEST_ROOM_REWARDS,Reward Selection!,奖励! CHEST_ROOM_SKIP,Skip,跳过 CHEST_ROOM_ACCEPT,Accept,接受 @@ -65,15 +66,15 @@ RELIC_COLORBOROS_TOOLTIP,"Taste the rainbow. Charges the freestyle bar every rif RELIC_CHIPS_NAME,"Chips",薯片 RELIC_CHIPS_TOOLTIP,"Hitting a note deals a bit of damage.","击中音符会造成少量伤害。" RELIC_PAPERCUT_NAME,Paper Cut,纸割伤 -RELIC_PAPERCUT_TOOLTIP,"Deals damage each loop.","每轮造成伤害" +RELIC_PAPERCUT_TOOLTIP,"Deals damage each riff.","每轮造成伤害" RELIC_ENERGYDRINK_NAME,Energy Drink,"能量饮料" RELIC_ENERGYDRINK_TOOLTIP,"Take a chance to cool down and sip an energy drink to increase your max energy bar.","碰碰运气,喝一口能量饮料来冷静下来并增加你的最大能量条。" RELIC_BANDAGE_NAME,Bandage,"绷带" RELIC_BANDAGE_TOOLTIP,"A clean strip of cloth. Use it after a fight to patch up and feel better.","一块干净的布条,战斗后使用来包扎并恢复一些健康。" RELIC_MEDKIT_NAME,Medkit,"急救包" -RELIC_MEDKIT_TOOLTIP,"A small kit with medical supplies. Heals you a bit after each loop.","包含一些医疗用品的小包,每次循环后恢复少量生命。" +RELIC_MEDKIT_TOOLTIP,"A small kit with medical supplies. Heals you a bit after each riff.","包含一些医疗用品的小包,每次循环后恢复少量生命。" RELIC_VINYLRECORD_NAME,Vinyl Record,"黑胶唱片" -RELIC_VINYLRECORD_TOOLTIP,"Right round, right round. All loop effects trigger twice.","把我转起来,把我转起来。所有循环效果触发两次。" +RELIC_VINYLRECORD_TOOLTIP,"Right round, right round. All riff effects trigger twice.","把我转起来,把我转起来。所有循环效果触发两次。" INVENTORY_TAB_NOTES,Notes,乐谱 INVENTORY_TAB_RELICS,Relics,遗物 OPTIONS_VOLUME_LABEL,Master Volume,最终音量设置 diff --git a/Scenes/AreaBasedBackground.cs b/Scenes/AreaBasedBackground.cs new file mode 100644 index 00000000..8a5275a2 --- /dev/null +++ b/Scenes/AreaBasedBackground.cs @@ -0,0 +1,16 @@ +using System; +using FunkEngine; +using Godot; + +public partial class AreaBasedBackground : TextureRect +{ + public override void _Ready() + { + Texture = StageProducer.CurArea switch + { + Area.Forest => GD.Load("res://SharedAssets/BackGround_Full.png"), + Area.City => GD.Load("res://icon.svg"), + _ => null, + }; + } +} diff --git a/Scenes/AreaBasedBackground.cs.uid b/Scenes/AreaBasedBackground.cs.uid new file mode 100644 index 00000000..6dd4683b --- /dev/null +++ b/Scenes/AreaBasedBackground.cs.uid @@ -0,0 +1 @@ +uid://cp6t6haqyef7o diff --git a/Scenes/BattleDirector/BattleScene.tscn b/Scenes/BattleDirector/BattleScene.tscn index 40024205..4e373b4b 100644 --- a/Scenes/BattleDirector/BattleScene.tscn +++ b/Scenes/BattleDirector/BattleScene.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=11 format=3 uid="uid://b0mrgr7h0ty1y"] +[gd_scene load_steps=12 format=3 uid="uid://b0mrgr7h0ty1y"] [ext_resource type="Script" uid="uid://bttu0wmy2fp64" path="res://Scenes/BattleDirector/Scripts/BattleDirector.cs" id="1_jmdo1"] [ext_resource type="Script" uid="uid://pl57giqyhckb" path="res://Scenes/UI/Scripts/MenuModule.cs" id="2_ka0ws"] @@ -6,6 +6,7 @@ [ext_resource type="PackedScene" uid="uid://duhiilcv4tat3" path="res://Scenes/BattleDirector/NotePlacementBar.tscn" id="4_qk7om"] [ext_resource type="PackedScene" uid="uid://dfevfib11kou1" path="res://Scenes/ChartViewport/ChartViewport.tscn" id="5_r2xh0"] [ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="6_0jtpx"] +[ext_resource type="Script" uid="uid://cp6t6haqyef7o" path="res://Scenes/AreaBasedBackground.cs" id="7_6k2qj"] [ext_resource type="Texture2D" uid="uid://dbjotl0v1ymia" path="res://SharedAssets/BattleFrame1.png" id="7_klvil"] [ext_resource type="Theme" uid="uid://d37e3tpsbxwak" path="res://Scenes/UI/Assets/GeneralTheme.tres" id="8_62qim"] @@ -18,9 +19,10 @@ gradient = SubResource("Gradient_8uy3a") fill_from = Vector2(1, 0) fill_to = Vector2(0.738532, 1) -[node name="ProtoBattleDirector" type="Node2D" node_paths=PackedStringArray("PuppetMarkers", "CD", "CM", "NPB", "Audio", "_focusedButton")] +[node name="ProtoBattleDirector" type="Node2D" node_paths=PackedStringArray("BackgroundRect", "PuppetMarkers", "CD", "CM", "NPB", "Audio", "_focusedButton")] process_mode = 1 script = ExtResource("1_jmdo1") +BackgroundRect = NodePath("BackGround") PuppetMarkers = [NodePath("PlayerMarker"), NodePath("Enemy1Marker"), NodePath("Enemy2Marker"), NodePath("Enemy3Marker")] CD = NodePath("Conductor") CM = NodePath("SubViewport") @@ -73,6 +75,7 @@ z_index = -1 offset_right = 640.0 offset_bottom = 178.0 texture = ExtResource("6_0jtpx") +script = ExtResource("7_6k2qj") [node name="BattleFrame" type="TextureRect" parent="."] z_index = 1 diff --git a/Scenes/ChestScene/ChestScene.tscn b/Scenes/ChestScene/ChestScene.tscn index 96281b84..8b5f8993 100644 --- a/Scenes/ChestScene/ChestScene.tscn +++ b/Scenes/ChestScene/ChestScene.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=10 format=3 uid="uid://c4vmb783d3v03"] +[gd_scene load_steps=11 format=3 uid="uid://c4vmb783d3v03"] [ext_resource type="Script" uid="uid://cetn71kolbrmg" path="res://Scenes/ChestScene/ChestScene.cs" id="1_ardd2"] [ext_resource type="AudioStream" uid="uid://be5ial13ynf3o" path="res://Audio/Song1.ogg" id="2_x78jo"] [ext_resource type="Script" uid="uid://pl57giqyhckb" path="res://Scenes/UI/Scripts/MenuModule.cs" id="3_5uvci"] +[ext_resource type="Script" uid="uid://cp6t6haqyef7o" path="res://Scenes/AreaBasedBackground.cs" id="5_u0wcg"] [ext_resource type="Shader" uid="uid://dp36iuuy414k1" path="res://SharedAssets/StarryNight.gdshader" id="5_whthd"] [ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="6_37nar"] [ext_resource type="Texture2D" uid="uid://d0ywqw1j1k71v" path="res://Scenes/ChestScene/Assets/Chest.png" id="6_58hf4"] @@ -16,11 +17,12 @@ shader_parameter/bg_bottom_color = Vector4(0.028, 0.008, 0.184, 0) shader_parameter/gradient_ratio = 1.0 shader_parameter/time_scale = 1.0 -[node name="ChestScene" type="Node2D" node_paths=PackedStringArray("ChestButton", "PlayerMarker")] +[node name="ChestScene" type="Node2D" node_paths=PackedStringArray("ChestButton", "PlayerMarker", "BackgroundRect")] process_mode = 1 script = ExtResource("1_ardd2") ChestButton = NodePath("CenterContainer/VBoxContainer/ChestButton") PlayerMarker = NodePath("PlayerMarker") +BackgroundRect = NodePath("BackGround") [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] stream = ExtResource("2_x78jo") @@ -38,6 +40,7 @@ z_index = -1 offset_right = 640.0 offset_bottom = 178.0 texture = ExtResource("6_37nar") +script = ExtResource("5_u0wcg") [node name="BattleFrame" type="TextureRect" parent="."] z_index = 1 diff --git a/Scenes/Maps/Cartographer.tscn b/Scenes/Maps/Cartographer.tscn index f492aa8e..824eaa96 100644 --- a/Scenes/Maps/Cartographer.tscn +++ b/Scenes/Maps/Cartographer.tscn @@ -1,26 +1,38 @@ -[gd_scene load_steps=6 format=3 uid="uid://cydmo2lbnj1de"] +[gd_scene load_steps=7 format=3 uid="uid://cydmo2lbnj1de"] [ext_resource type="Script" uid="uid://dtlpiwt4n3pta" path="res://Scenes/Maps/Scripts/Cartographer.cs" id="1_u4q3n"] [ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="2_5g6at"] [ext_resource type="Script" uid="uid://pl57giqyhckb" path="res://Scenes/UI/Scripts/MenuModule.cs" id="2_cl7v0"] [ext_resource type="Theme" uid="uid://bcejp4llrb3m0" path="res://Scenes/UI/Assets/EmptyButton.tres" id="2_rnj1y"] [ext_resource type="Texture2D" uid="uid://cmc7gcplqnebx" path="res://SharedAssets/Player.png" id="3_qiprp"] +[ext_resource type="Script" uid="uid://cp6t6haqyef7o" path="res://Scenes/AreaBasedBackground.cs" id="5_taedj"] -[node name="Cartographer" type="Node2D" node_paths=PackedStringArray("PlayerSprite")] +[node name="Cartographer" type="Node2D" node_paths=PackedStringArray("BackgroundSprite", "PlayerSprite", "Camera")] process_mode = 1 script = ExtResource("1_u4q3n") +BackgroundSprite = NodePath("") PlayerSprite = NodePath("Player") ButtonTheme = ExtResource("2_rnj1y") +Camera = NodePath("TheView") + +[node name="TheView" type="Camera2D" parent="."] +top_level = true +anchor_mode = 0 +limit_top = -10 [node name="UI" type="CanvasLayer" parent="." node_paths=PackedStringArray("CurSceneNode")] script = ExtResource("2_cl7v0") CurSceneNode = NodePath("..") -[node name="BG" type="Sprite2D" parent="."] +[node name="BG" type="TextureRect" parent="."] modulate = Color(0.462, 0.462, 0.66, 1) -position = Vector2(-10, 229) +offset_left = -557.0 +offset_top = -84.0 +offset_right = 83.0 +offset_bottom = 96.0 scale = Vector2(3, 3) texture = ExtResource("2_5g6at") +script = ExtResource("5_taedj") [node name="Player" type="Sprite2D" parent="."] z_index = 2 diff --git a/Scenes/Maps/InBetween.tscn b/Scenes/Maps/InBetween.tscn new file mode 100644 index 00000000..d425f862 --- /dev/null +++ b/Scenes/Maps/InBetween.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://djlperv5n75y1"] + +[ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="1_74aj5"] +[ext_resource type="Theme" uid="uid://d37e3tpsbxwak" path="res://Scenes/UI/Assets/GeneralTheme.tres" id="2_dapxv"] +[ext_resource type="Script" uid="uid://cahjluc6v7ked" path="res://Scenes/UI/TitleScreen/Scripts/SceneChange.cs" id="3_35xdc"] + +[node name="Inbetween" type="Node2D"] + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(197, 86) +rotation = 3.72628 +scale = Vector2(3.81, 3.81) +texture = ExtResource("1_74aj5") + +[node name="Button" type="Button" parent="."] +offset_left = 263.0 +offset_top = 276.0 +offset_right = 271.0 +offset_bottom = 284.0 +theme = ExtResource("2_dapxv") +text = "INBETWEEN_CONTINUE" +script = ExtResource("3_35xdc") +ScenePath = 5 +_startFocused = true diff --git a/Scenes/Maps/Scripts/Cartographer.cs b/Scenes/Maps/Scripts/Cartographer.cs index ae82b875..ebd07533 100644 --- a/Scenes/Maps/Scripts/Cartographer.cs +++ b/Scenes/Maps/Scripts/Cartographer.cs @@ -17,6 +17,9 @@ public partial class Cartographer : Node2D [Export] public Theme ButtonTheme; + [Export] + public Camera2D Camera; + private Button[] _validButtons = Array.Empty