Some progress in tile streaming prototype

WorldChunkRefactoring
Martin Felis 2023-10-05 18:17:48 +02:00
parent e2bb11380d
commit f8819937e1
9 changed files with 384 additions and 64 deletions

View File

@ -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"

View File

@ -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<Slider>("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));

View File

@ -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"]

View File

@ -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));
}
}

115
scenes/World.cs Normal file
View File

@ -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<PackedScene>("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<Tuple<int, int>, WorldChunk> _worldChunks;
public World()
{
Debug.Assert(ChunkSize % 2 == 0);
_worldChunks = new Dictionary<Tuple<int, int>, 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<int, int>(xIndex, yIndex)))
{
WorldChunk cachedChunk = _worldChunks[new Tuple<int, int>(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<int, int> chunkIndex = new Tuple<int, int>(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<int, int> chunkIndex = new Tuple<int, int>((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)
// {
//
// }
}

85
scenes/WorldChunk.cs Normal file
View File

@ -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)
// {
//
// }
}

17
scenes/WorldChunk.tscn Normal file
View File

@ -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 )

31
scenes/WorldView.cs Normal file
View File

@ -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>(World);
}
public override void _Process(float delta)
{
}
}

24
ui/DebugStatsContainer.gd Normal file
View File

@ -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