From f8819937e16083ced88d871e6d684d765790608f Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Thu, 5 Oct 2023 18:17:48 +0200 Subject: [PATCH] Some progress in tile streaming prototype --- project.godot | 8 +-- scenes/Game.cs | 31 +++++---- scenes/Game.tscn | 135 ++++++++++++++++++++++++++------------ scenes/TileWorld.cs | 2 +- scenes/World.cs | 115 ++++++++++++++++++++++++++++++++ scenes/WorldChunk.cs | 85 ++++++++++++++++++++++++ scenes/WorldChunk.tscn | 17 +++++ scenes/WorldView.cs | 31 +++++++++ ui/DebugStatsContainer.gd | 24 +++++++ 9 files changed, 384 insertions(+), 64 deletions(-) create mode 100644 scenes/World.cs create mode 100644 scenes/WorldChunk.cs create mode 100644 scenes/WorldChunk.tscn create mode 100644 scenes/WorldView.cs create mode 100644 ui/DebugStatsContainer.gd diff --git a/project.godot b/project.godot index cd4dd44..f9b6e9d 100644 --- a/project.godot +++ b/project.godot @@ -9,17 +9,17 @@ config_version=4 _global_script_classes=[ { -"base": "Node", +"base": "Reference", "class": "ClickableComponent", "language": "GDScript", "path": "res://components/ClickableComponent.gd" }, { -"base": "KinematicBody2D", +"base": "Reference", "class": "CollisionLine", "language": "GDScript", "path": "res://utils/CollisionLine.gd" }, { -"base": "Node", +"base": "Reference", "class": "ColorComponent", "language": "GDScript", "path": "res://components/ColorComponent.gd" @@ -54,7 +54,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://utils/SpringDamper.gd" }, { -"base": "Sprite", +"base": "Reference", "class": "TintedSpriteComponent", "language": "GDScript", "path": "res://components/TintedSpriteComponent.gd" diff --git a/scenes/Game.cs b/scenes/Game.cs index c73db1d..9dd27e6 100644 --- a/scenes/Game.cs +++ b/scenes/Game.cs @@ -30,6 +30,8 @@ public class Game : Spatial private Player _player; private TileWorld _tileWorld; private Camera _camera; + private World _world; + private WorldView _worldView; // Resources private PackedScene _tileHighlightScene; @@ -81,6 +83,9 @@ public class Game : Spatial _camera = (Camera)FindNode("Camera"); _cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation; + _world = (World)FindNode("World"); + _worldView = (WorldView)FindNode("WorldView"); + // populate UI values Slider generatorWorldSizeSlider = worldGeneratorContainer.GetNode("HBoxContainer/WorldSizeSlider"); generatorWorldSizeSlider.Value = _tileWorld.Size; @@ -140,27 +145,20 @@ public class Game : Spatial _streamContainer.SetCenterTile(_currentTile); } - public void CreateTileGrid() + + public override void _Input(InputEvent inputEvent) { - foreach (int x_index in Enumerable.Range(-3, 6)) + if (inputEvent.IsAction("Forward")) { - foreach (int y_index in Enumerable.Range(0, 1)) - { - var tile = (Spatial)_tileHighlightScene.Instance(); - HexCell cell = new HexCell(); - Vector2 planeCoords = _hexGrid.GetHexCenterFromOffset(new Vector2(x_index, y_index)); - Transform tileTransform = Transform.Identity; - tileTransform.origin.x = planeCoords.x; - tileTransform.origin.z = planeCoords.y; - tile.Transform = tileTransform; - AddChild(tile); - GD.Print("Added tile at offset coords " + new Vector2(x_index, y_index).ToString() + - " and world coords " + tileTransform.origin.ToString()); - } + GD.Print("Forward"); + } + + if (inputEvent.IsAction("Back")) + { + GD.Print("Back"); } } - public void UpdateCurrentTile() { // cast a ray from the camera to center @@ -180,6 +178,7 @@ public class Game : Spatial centerCoord.y = 0; } + _world.SetCenterPlaneCoord(new Vector2(_player.GlobalTranslation.x, _player.GlobalTranslation.z)); _currentTile = _hexGrid.GetHexAt(new Vector2(centerCoord.x, centerCoord.z)); diff --git a/scenes/Game.tscn b/scenes/Game.tscn index 7982bdc..a7eb109 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -1,12 +1,15 @@ -[gd_scene load_steps=13 format=2] +[gd_scene load_steps=16 format=2] [ext_resource path="res://scenes/StreamContainer.tscn" type="PackedScene" id=1] [ext_resource path="res://entities/Player.tscn" type="PackedScene" id=2] [ext_resource path="res://scenes/Camera.tscn" type="PackedScene" id=3] [ext_resource path="res://ui/EditorUI.tscn" type="PackedScene" id=4] [ext_resource path="res://utils/TileHighlight.tscn" type="PackedScene" id=5] +[ext_resource path="res://ui/DebugStatsContainer.gd" type="Script" id=6] +[ext_resource path="res://scenes/World.cs" type="Script" id=7] [ext_resource path="res://scenes/TileWorld.tscn" type="PackedScene" id=8] [ext_resource path="res://scenes/Game.cs" type="Script" id=9] +[ext_resource path="res://scenes/WorldView.cs" type="Script" id=10] [ext_resource path="res://ui/WorldGeneratorUI.gd" type="Script" id=12] [ext_resource path="res://entities/Axe.tscn" type="PackedScene" id=14] [ext_resource path="res://systems/InteractionSystem.cs" type="Script" id=15] @@ -34,12 +37,12 @@ script = ExtResource( 9 ) [node name="TileHighlight" parent="." instance=ExtResource( 5 )] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0 ) +visible = false [node name="MouseTileHighlight" parent="." instance=ExtResource( 5 )] -transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.3, 0 ) [node name="TileWorld" parent="." instance=ExtResource( 8 )] -GenerationMapType = 0 +GenerationMapType = 2 [node name="GameUI" type="HBoxContainer" parent="."] anchor_left = 1.0 @@ -86,144 +89,179 @@ size_flags_vertical = 3 [node name="DebugStatsContainer" type="GridContainer" parent="DebugContainer"] margin_left = 7.0 margin_top = 7.0 -margin_right = 156.0 -margin_bottom = 183.0 +margin_right = 134.0 +margin_bottom = 165.0 grow_horizontal = 0 grow_vertical = 0 mouse_filter = 2 columns = 2 +script = ExtResource( 6 ) + +[node name="DebugMenuButton" type="Button" parent="DebugContainer/DebugStatsContainer"] +margin_right = 53.0 +margin_bottom = 20.0 +toggle_mode = true +text = "Debug" + +[node name="VSeparator" type="VSeparator" parent="DebugContainer/DebugStatsContainer"] +visible = false +margin_left = 57.0 +margin_right = 61.0 +margin_bottom = 20.0 [node name="Label9" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false +margin_top = 24.0 margin_right = 113.0 -margin_bottom = 14.0 +margin_bottom = 38.0 rect_pivot_offset = Vector2( -335, -33 ) text = "FPS" [node name="fps_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 +margin_top = 24.0 margin_right = 149.0 -margin_bottom = 14.0 +margin_bottom = 38.0 text = "0,0" [node name="Label" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 18.0 +visible = false +margin_top = 42.0 margin_right = 113.0 -margin_bottom = 32.0 +margin_bottom = 56.0 rect_pivot_offset = Vector2( -335, -33 ) text = "Center" [node name="center_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 18.0 +margin_top = 42.0 margin_right = 149.0 -margin_bottom = 32.0 +margin_bottom = 56.0 text = "0,0" [node name="Label2" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 36.0 +visible = false +margin_top = 60.0 margin_right = 113.0 -margin_bottom = 50.0 +margin_bottom = 74.0 text = "Tile Offset" [node name="tile_offset_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 36.0 +margin_top = 60.0 margin_right = 149.0 -margin_bottom = 50.0 +margin_bottom = 74.0 text = "0,0" [node name="Label4" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 54.0 +visible = false +margin_top = 78.0 margin_right = 113.0 -margin_bottom = 68.0 +margin_bottom = 92.0 rect_pivot_offset = Vector2( -335, -33 ) text = "Mouse World" [node name="mouse_world_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 54.0 +margin_top = 78.0 margin_right = 149.0 -margin_bottom = 68.0 +margin_bottom = 92.0 text = "0,0" [node name="Label6" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 72.0 +visible = false +margin_top = 96.0 margin_right = 113.0 -margin_bottom = 86.0 +margin_bottom = 110.0 rect_pivot_offset = Vector2( -335, -33 ) text = "Mouse Tile Offset" [node name="mouse_tile_offset_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 72.0 +margin_top = 96.0 margin_right = 149.0 -margin_bottom = 86.0 +margin_bottom = 110.0 text = "0,0" [node name="Label10" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 90.0 +visible = false +margin_top = 114.0 margin_right = 113.0 -margin_bottom = 104.0 +margin_bottom = 128.0 rect_pivot_offset = Vector2( -335, -33 ) text = "Mouse Tile Cube" [node name="mouse_tile_cube_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 90.0 +margin_top = 114.0 margin_right = 149.0 -margin_bottom = 104.0 +margin_bottom = 128.0 text = "0,0,0" [node name="Label3" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 108.0 +visible = false +margin_top = 132.0 margin_right = 113.0 -margin_bottom = 122.0 +margin_bottom = 146.0 text = "#Tiles" [node name="num_tiles_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 108.0 +margin_top = 132.0 margin_right = 149.0 -margin_bottom = 122.0 +margin_bottom = 146.0 text = "0" [node name="Label5" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 126.0 +visible = false +margin_top = 150.0 margin_right = 113.0 -margin_bottom = 140.0 +margin_bottom = 164.0 text = "#Active" [node name="num_active_tiles_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 126.0 +margin_top = 150.0 margin_right = 149.0 -margin_bottom = 140.0 +margin_bottom = 164.0 text = "0" [node name="Label7" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 144.0 +visible = false +margin_top = 168.0 margin_right = 113.0 -margin_bottom = 158.0 +margin_bottom = 182.0 text = "#Tiles Added" [node name="num_coords_added_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 144.0 +margin_top = 168.0 margin_right = 149.0 -margin_bottom = 158.0 +margin_bottom = 182.0 text = "0" [node name="Label8" type="Label" parent="DebugContainer/DebugStatsContainer"] -margin_top = 162.0 +visible = false +margin_top = 186.0 margin_right = 113.0 -margin_bottom = 176.0 +margin_bottom = 200.0 text = "#Tiles Removed" [node name="num_coords_removed_label" type="Label" parent="DebugContainer/DebugStatsContainer"] +visible = false margin_left = 117.0 -margin_top = 162.0 +margin_top = 186.0 margin_right = 149.0 -margin_bottom = 176.0 +margin_bottom = 200.0 text = "0" [node name="Generator Container" type="Control" parent="."] @@ -313,9 +351,20 @@ parameters/playback = SubResource( 26 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.79762, 0, 0 ) input_ray_pickable = false +[node name="WorldView" type="Spatial" parent="."] +script = ExtResource( 10 ) +World = NodePath("../World") + +[node name="World" type="Spatial" parent="."] +script = ExtResource( 7 ) + +[node name="Chunks" type="Spatial" parent="World"] + +[connection signal="toggled" from="DebugContainer/DebugStatsContainer/DebugMenuButton" to="DebugContainer/DebugStatsContainer" method="_on_DebugMenuButton_toggled"] [connection signal="value_changed" from="Generator Container/WorldGeneratorContainer/HBoxContainer/WorldSizeSlider" to="Generator Container/WorldGeneratorContainer" method="_on_HSlider_value_changed"] [connection signal="toggled" from="Generator Container/WorldGeneratorContainer/ShowTexturesCheckButton" to="Generator Container/WorldGeneratorContainer" method="_on_ShowTexturesCheckButton_toggled"] [editable path="TileWorld"] +[editable path="StreamContainer"] [editable path="Player"] [editable path="Player/Geometry"] diff --git a/scenes/TileWorld.cs b/scenes/TileWorld.cs index 1fbf99a..5fd759d 100644 --- a/scenes/TileWorld.cs +++ b/scenes/TileWorld.cs @@ -219,7 +219,7 @@ public class TileWorld : Spatial foreach (int coordY in Enumerable.Range(0, Size)) { HeightmapImage.SetPixel(coordX, coordY, - new Color(0, 0, 0)); + new Color(0.5f, 0.5f, 0.5f)); } } diff --git a/scenes/World.cs b/scenes/World.cs new file mode 100644 index 0000000..75b55ed --- /dev/null +++ b/scenes/World.cs @@ -0,0 +1,115 @@ +using Godot; +using System; +using System.Collections.Generic; +using System.Diagnostics; + +public class World : Spatial +{ + // referenced scenes + private PackedScene _worldChunkScene = GD.Load("res://scenes/WorldChunk.tscn"); + + // constants + public const int ChunkSize = 4; + public HexGrid HexGrid = new HexGrid(); + public Spatial Chunks; + public Color DebugColor; + + // ui elements + + // scene nodes + + // resources + + // exports + // [Export] public Vector2 Size = new Vector2(1, 1); + + // signals + // delegate void OnCoordClicked(Vector2 world_pos); + + // other members + private Vector2 _centerPlaneCoord; + private int[] _centerChunkCoord = { 0, 0 }; + private int[] _previousCenterChunkCoord = { 0, 0 }; + private Rect2 _centerChunkRect2 = new Rect2(); + private Random _debugColorRandom = new Random(); + private Dictionary, WorldChunk> _worldChunks; + + public World() + { + Debug.Assert(ChunkSize % 2 == 0); + + _worldChunks = new Dictionary, WorldChunk>(); + } + + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + Chunks = (Spatial)FindNode("Chunks"); + Debug.Assert(Chunks != null); + + SetCenterPlaneCoord(Vector2.Zero); + } + + public WorldChunk GetOrCreateWorldChunk(int xIndex, int yIndex, Color debugColor) + { + if (_worldChunks.ContainsKey(new Tuple(xIndex, yIndex))) + { + WorldChunk cachedChunk = _worldChunks[new Tuple(xIndex, yIndex)]; + return cachedChunk; + } + + return CreateWorldChunk(xIndex, yIndex, debugColor); + } + + private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor) + { + WorldChunk result = (WorldChunk)_worldChunkScene.Instance(); + + Vector2 offsetCoordSouthWest = new Vector2(xIndex, yIndex) * ChunkSize; + Vector2 offsetCoordNorthEast = offsetCoordSouthWest + new Vector2(1, 1) * (ChunkSize - 1); + + Vector2 planeCoordSouthWest = HexGrid.GetHexCenterFromOffset(offsetCoordSouthWest) + + new Vector2(-HexGrid.HexSize.x, HexGrid.HexSize.y) * 0.5f; + Vector2 planeCoordNorthEast = HexGrid.GetHexCenterFromOffset(offsetCoordNorthEast) + + new Vector2(HexGrid.HexSize.x, -HexGrid.HexSize.y) * 0.5f; + + result.PlaneRect = new Rect2( + new Vector2(planeCoordSouthWest.x, planeCoordNorthEast.y), + new Vector2(planeCoordNorthEast.x - planeCoordSouthWest.x, planeCoordSouthWest.y - planeCoordNorthEast.y)); + + result.DebugColor = debugColor; + result.DebugColor.a = 0.6f; + + Chunks.AddChild(result); + Tuple chunkIndex = new Tuple(xIndex, yIndex); + _worldChunks.Add(chunkIndex, result); + + return result; + } + + public void UpdateCenterChunkFromPlaneCoord(Vector2 planeCoord) + { + HexCell centerOffsetCoord = HexGrid.GetHexAt(planeCoord); + Vector2 chunkIndexFloatUnrounded = (centerOffsetCoord.OffsetCoords / (float)ChunkSize); + Vector2 chunkIndexFloat = (centerOffsetCoord.OffsetCoords / (float)ChunkSize).Floor(); + Tuple chunkIndex = new Tuple((int)chunkIndexFloat.x, (int)chunkIndexFloat.y); + + WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2, + new Color(GD.Randf(), GD.Randf(), GD.Randf())); + _centerChunkRect2 = currentChunk.PlaneRect; + } + + public void SetCenterPlaneCoord(Vector2 centerPlaneCoord) + { + if (!_centerChunkRect2.HasPoint(centerPlaneCoord)) + { + UpdateCenterChunkFromPlaneCoord(centerPlaneCoord); + } + } + +// // Called every frame. 'delta' is the elapsed time since the previous frame. +// public override void _Process(float delta) +// { +// +// } +} \ No newline at end of file diff --git a/scenes/WorldChunk.cs b/scenes/WorldChunk.cs new file mode 100644 index 0000000..a288694 --- /dev/null +++ b/scenes/WorldChunk.cs @@ -0,0 +1,85 @@ +using Godot; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; + +public class WorldChunk : Spatial +{ + // ui elements + + // scene nodes + private MeshInstance PlaneRectMesh; + + // resources + + // exports + [Export] public Texture TileTypeMap; + [Export] public Texture NavigationMap; + [Export] public Texture HeightMap; + [Export] public readonly int size = 32; + + [Export] public Vector2 ChunkAddress; + // [Export] public Vector2 Size = new Vector2(1, 1); + + // signals + // delegate void OnCoordClicked(Vector2 world_pos); + + // other members + public Rect2 PlaneRect; + public Color DebugColor = Colors.White; + + public WorldChunk() + { + + } + + public WorldChunk(int size) + { + + } + + // other members + public void SaveToFile(String chunkName) + { + Image image = new Image(); + + image.CreateFromData(size, size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData()); + image.SavePng(chunkName + "_tileType.png"); + + image.CreateFromData(size, size, false, Image.Format.Rgba8, NavigationMap.GetData().GetData()); + image.SavePng(chunkName + "_navigationMap.png"); + + image.CreateFromData(size, size, false, Image.Format.Rgba8, HeightMap.GetData().GetData()); + image.SavePng(chunkName + "_heightMap.png"); + } + + public void LoadFromFile(String chunkName) + { + + } + + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + PlaneRectMesh = (MeshInstance) FindNode("PlaneRectMesh"); + Debug.Assert(PlaneRectMesh != null); + + Transform planeRectTransform = Transform.Identity; + planeRectTransform = planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x * 0.5f, 1, PlaneRect.Size.y * 0.5f)); + planeRectTransform.origin.x = PlaneRect.GetCenter().x; + planeRectTransform.origin.z = PlaneRect.GetCenter().y; + + PlaneRectMesh.Transform = planeRectTransform; + + PlaneRectMesh.MaterialOverride = new SpatialMaterial(); + ((SpatialMaterial)PlaneRectMesh.MaterialOverride).AlbedoColor = DebugColor; + ((SpatialMaterial)PlaneRectMesh.MaterialOverride).FlagsTransparent = true; + } + +// // Called every frame. 'delta' is the elapsed time since the previous frame. +// public override void _Process(float delta) +// { +// +// } +} diff --git a/scenes/WorldChunk.tscn b/scenes/WorldChunk.tscn new file mode 100644 index 0000000..79210b3 --- /dev/null +++ b/scenes/WorldChunk.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://scenes/WorldChunk.cs" type="Script" id=1] + +[sub_resource type="CubeMesh" id=27] +size = Vector3( 2, 0.5, 2 ) + +[sub_resource type="SpatialMaterial" id=28] + +[node name="WorldChunk" type="Spatial"] +script = ExtResource( 1 ) + +[node name="Entities" type="Spatial" parent="."] + +[node name="PlaneRectMesh" type="MeshInstance" parent="."] +mesh = SubResource( 27 ) +material/0 = SubResource( 28 ) diff --git a/scenes/WorldView.cs b/scenes/WorldView.cs new file mode 100644 index 0000000..8149cbc --- /dev/null +++ b/scenes/WorldView.cs @@ -0,0 +1,31 @@ +using Godot; +using System; + +public class WorldView : Spatial +{ + // ui elements + + // scene nodes + + // resources + + // exports + [Export] public NodePath World; + [Export] public Vector2 ViewCenterPlaneCoord; + + // signals + // delegate void OnCoordClicked(Vector2 world_pos); + + // other members + private World _world; + + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + _world = GetNode(World); + } + + public override void _Process(float delta) + { + } +} \ No newline at end of file diff --git a/ui/DebugStatsContainer.gd b/ui/DebugStatsContainer.gd new file mode 100644 index 0000000..cb8000c --- /dev/null +++ b/ui/DebugStatsContainer.gd @@ -0,0 +1,24 @@ +extends GridContainer + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" +onready var DebugMenuButton = $DebugMenuButton + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass + + +func _on_DebugMenuButton_toggled(button_pressed): + for child in self.get_children(): + if child == DebugMenuButton: + continue + + child.visible = button_pressed