Chunk based world generation works.
Still missing: - world population (trees, grass, rocks) - chunk saving/loadingWorldChunkRefactoring
parent
d918da6fd6
commit
a0a3fea598
|
@ -153,7 +153,7 @@ public class NavigationComponent : Spatial
|
|||
}
|
||||
|
||||
// Ensure the last point coincides with the target position
|
||||
if ((_planningPathWorldNavigationPoints.Last().WorldPosition - toPositionWorld).LengthSquared() <
|
||||
if (_planningPathWorldNavigationPoints.Count > 0 && (_planningPathWorldNavigationPoints.Last().WorldPosition - toPositionWorld).LengthSquared() <
|
||||
0.5f * 0.5f)
|
||||
{
|
||||
_planningPathWorldNavigationPoints[_planningPathWorldNavigationPoints.Count - 1].WorldPosition = toPositionWorld;
|
||||
|
|
|
@ -6,4 +6,6 @@
|
|||
[resource]
|
||||
shader = ExtResource( 2 )
|
||||
shader_param/TextureSize = 4
|
||||
shader_param/CoordinateOffsetU = null
|
||||
shader_param/CoordinateOffsetV = null
|
||||
shader_param/MapAlbedoTexture = ExtResource( 1 )
|
||||
|
|
|
@ -4,3 +4,11 @@
|
|||
|
||||
[resource]
|
||||
shader = ExtResource( 1 )
|
||||
shader_param/DeepWaterColor = Color( 0, 0, 0.6, 1 )
|
||||
shader_param/WaterColor = Color( 0, 0, 0.7, 1 )
|
||||
shader_param/LightWaterColor = Color( 0, 0, 1, 1 )
|
||||
shader_param/SandColor = Color( 0.8, 0.8, 0.1, 1 )
|
||||
shader_param/GrassColor = Color( 0, 0.6, 0, 1 )
|
||||
shader_param/ForestColor = Color( 0, 0.4, 0, 1 )
|
||||
shader_param/RockColor = Color( 0.5, 0.5, 0.4, 1 )
|
||||
shader_param/SnowColor = Color( 1, 1, 1, 1 )
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
[ext_resource path="res://materials/shader/IslandHeightmapFalloffShader.gdshader" type="Shader" id=1]
|
||||
|
||||
[resource]
|
||||
render_priority = -1
|
||||
shader = ExtResource( 1 )
|
||||
|
|
|
@ -3,6 +3,8 @@ render_mode specular_schlick_ggx, async_visible;
|
|||
|
||||
uniform sampler2D MapAlbedoTexture : hint_black_albedo;
|
||||
uniform int TextureSize: hint_range(0, 1024, 4);
|
||||
uniform int CoordinateOffsetU: hint_range(-32000, 32000);
|
||||
uniform int CoordinateOffsetV: hint_range(-32000, 32000);
|
||||
varying vec2 map_coord;
|
||||
|
||||
const mat2 _HexAffineInverse = mat2(vec2(1.333333, -0.6666667), vec2(0, -1.154701));
|
||||
|
@ -41,13 +43,12 @@ void vertex() {
|
|||
vec3 origin = vec4(WORLD_MATRIX * vec4(0, 0, 0, 1)).xyz;
|
||||
vec3 axial_coords = vec3(_HexAffineInverse * origin.xz, 0);
|
||||
|
||||
map_coord = axial_to_offset(axial_coords.xy);
|
||||
map_coord = axial_to_offset(axial_coords.xy) - vec2(ivec2(CoordinateOffsetU, CoordinateOffsetV));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
float size = float(TextureSize);
|
||||
vec2 texel_offset = vec2(ceil(size / 2.0));
|
||||
ivec2 texel_coord = ivec2(mod(map_coord.xy - texel_offset, vec2(size)));
|
||||
ivec2 texel_coord = ivec2(mod(map_coord.xy, vec2(size)));
|
||||
vec4 texel_value = texelFetch(MapAlbedoTexture, texel_coord, 0);
|
||||
|
||||
ALBEDO = texelFetch(MapAlbedoTexture, texel_coord, 0).rgb;
|
||||
|
|
|
@ -1,28 +1,38 @@
|
|||
shader_type canvas_item;
|
||||
render_mode skip_vertex_transform;
|
||||
|
||||
uniform vec4 DeepWaterColor : hint_color = vec4(0, 0, 0.6, 1);
|
||||
uniform vec4 WaterColor : hint_color = vec4(0, 0, 0.7, 1);
|
||||
uniform vec4 LightWaterColor : hint_color = vec4(0, 0, 1, 1);
|
||||
uniform vec4 SandColor : hint_color = vec4(0.8, 0.8, 0.1, 1);
|
||||
uniform vec4 GrassColor : hint_color = vec4(0, 0.6, 0, 1);
|
||||
uniform vec4 ForestColor : hint_color = vec4(0, 0.4, 0, 1);
|
||||
uniform vec4 RockColor : hint_color = vec4(0.5, 0.5, 0.4, 1);
|
||||
uniform vec4 SnowColor : hint_color = vec4(1);
|
||||
uniform sampler2D TextureMask : hint_albedo;
|
||||
|
||||
void vertex() {
|
||||
VERTEX = (WORLD_MATRIX * (EXTRA_MATRIX * vec4(VERTEX, 0.0, 1.0))).xy;
|
||||
}
|
||||
|
||||
vec3 color_ramp(float h) {
|
||||
if (h < 0.4f) {
|
||||
return vec3(0, 0, 0.6);
|
||||
if (h < 0.1f) {
|
||||
return DeepWaterColor.rgb;
|
||||
} else if (h < 0.12f) {
|
||||
return WaterColor.rgb;
|
||||
} else if (h < 0.45f) {
|
||||
return vec3(0, 0, 0.7);
|
||||
} else if (h < 0.5f) {
|
||||
return vec3(0, 0, 1);
|
||||
} else if (h < 0.55){
|
||||
return vec3(0.8, 0.8, 0.1);
|
||||
} else if (h < 0.6){
|
||||
return vec3(0, 0.6, 0);
|
||||
} else if (h < 0.78){
|
||||
return vec3(0, 0.4, 0);
|
||||
return LightWaterColor.rgb;
|
||||
// } else if (h < 0.25){
|
||||
// return SandColor.rgb;
|
||||
} else if (h < 0.75){
|
||||
return GrassColor.rgb;
|
||||
// } else if (h < 0.78){
|
||||
// return ForestColor.rgb;
|
||||
} else if (h < 1.0){
|
||||
return vec3(0.5, 0.5, 0.4);
|
||||
return RockColor.rgb;
|
||||
}
|
||||
|
||||
return vec3(1.0);
|
||||
return SnowColor.rgb;
|
||||
}
|
||||
|
||||
vec3 rgbToGrayscale(vec3 color) {
|
||||
|
@ -42,9 +52,11 @@ float borderFalloffCircle(vec2 uv) {
|
|||
void fragment() {
|
||||
vec4 texture_color = texture(TEXTURE, UV);
|
||||
|
||||
|
||||
COLOR.rgb = vec3(abs(UV.x - 0.5) * 2.0);
|
||||
//COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
|
||||
COLOR.rgb = color_ramp(texture_color.r);
|
||||
|
||||
// COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
|
||||
COLOR.rgb = color_ramp(texture_color.r * texture(TextureMask, UV).r);
|
||||
COLOR.a = 0.8;
|
||||
// COLOR.rgb = vec3(1, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ public class Game : Spatial
|
|||
_player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged));
|
||||
_worldView.Connect("TileClicked", this, nameof(OnTileClicked));
|
||||
_worldView.Connect("TileHovered", this, nameof(OnTileHovered));
|
||||
_worldView.Connect("OnWorldViewTileTypeImageChanged", this, nameof(OnWorldViewTileTypeImageChanged));
|
||||
|
||||
// register entity events
|
||||
foreach (Node node in GetNode("Entities").GetChildren())
|
||||
|
@ -356,6 +357,20 @@ public class Game : Spatial
|
|||
_heightTextureRect.Texture = newHeightTexture;
|
||||
}
|
||||
|
||||
private void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage)
|
||||
{
|
||||
ImageTexture newWorldTexture = new ImageTexture();
|
||||
newWorldTexture.CreateFromImage(viewTileTypeImage,
|
||||
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||
|
||||
_worldTextureRect.Texture = newWorldTexture;
|
||||
|
||||
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
|
||||
_tileMaterial.SetShaderParam("TextureSize", (int)newWorldTexture.GetSize().x);
|
||||
_tileMaterial.SetShaderParam("CoordinateOffsetU", (int) _worldView.WorldTextureCoordinateOffset.x);
|
||||
_tileMaterial.SetShaderParam("CoordinateOffsetV", (int) _worldView.WorldTextureCoordinateOffset.y);
|
||||
}
|
||||
|
||||
public void OnGoldCountChanged(int goldCount)
|
||||
{
|
||||
AnimationPlayer animationPlayer = _gameUi.GetNode<AnimationPlayer>("AnimationPlayer");
|
||||
|
|
|
@ -10,6 +10,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://entities/Chest.tscn" type="PackedScene" id=11]
|
||||
[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]
|
||||
|
@ -355,9 +356,13 @@ 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="Chest" parent="Entities" instance=ExtResource( 11 )]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -3.27709, 0, 1.02593 )
|
||||
|
||||
[node name="WorldView" type="Spatial" parent="."]
|
||||
script = ExtResource( 10 )
|
||||
World = NodePath("../World")
|
||||
ShowHexTiles = true
|
||||
|
||||
[node name="World" type="Spatial" parent="."]
|
||||
script = ExtResource( 7 )
|
||||
|
|
|
@ -16,12 +16,15 @@ public class World : Spatial
|
|||
Done
|
||||
}
|
||||
public GenerationState State = GenerationState.Done;
|
||||
public Vector2 CenterChunkIndex = Vector2.Zero;
|
||||
|
||||
// referenced scenes
|
||||
private PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
|
||||
|
||||
// constants
|
||||
public const int ChunkSize = 16;
|
||||
public const int NumChunkRows = 3;
|
||||
public const int NumChunkColumns = NumChunkRows;
|
||||
public int Seed = 0;
|
||||
public HexGrid HexGrid = new HexGrid();
|
||||
public Spatial Chunks;
|
||||
|
@ -44,10 +47,7 @@ public class World : Spatial
|
|||
|
||||
// other members
|
||||
private Vector2 _centerPlaneCoord;
|
||||
private int[] _centerChunkCoord = { 0, 0 };
|
||||
private int[] _previousCenterChunkCoord = { 0, 0 };
|
||||
private Rect2 _centerChunkRect = new Rect2();
|
||||
private Random _debugColorRandom = new Random();
|
||||
private Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
|
||||
private List<Vector2> _activeChunkIndices = new();
|
||||
private List<Vector2> _addedChunkIndices = new();
|
||||
|
@ -141,6 +141,8 @@ public class World : Spatial
|
|||
|
||||
// set new center chunk
|
||||
var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
|
||||
CenterChunkIndex = new Vector2(chunkIndex.Item1, chunkIndex.Item2);
|
||||
|
||||
WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
|
||||
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||
_centerChunkRect = currentChunk.PlaneRect;
|
||||
|
@ -159,6 +161,8 @@ public class World : Spatial
|
|||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 + 1));
|
||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 + 1));
|
||||
|
||||
Debug.Assert(_activeChunkIndices.Count == NumChunkRows * NumChunkColumns);
|
||||
|
||||
foreach(Vector2 activeChunkIndex in _activeChunkIndices)
|
||||
{
|
||||
GetOrCreateWorldChunk((int) activeChunkIndex.x, (int) activeChunkIndex.y, new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System.Linq;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using Vector2 = Godot.Vector2;
|
||||
using Vector3 = Godot.Vector3;
|
||||
|
||||
public class WorldView : Spatial
|
||||
{
|
||||
|
@ -20,9 +22,15 @@ public class WorldView : Spatial
|
|||
delegate void TileClicked(HexTile3D tile3d);
|
||||
[Signal]
|
||||
delegate void TileHovered(HexTile3D tile3d);
|
||||
[Signal]
|
||||
delegate void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage);
|
||||
|
||||
// other members
|
||||
public Vector2 WorldTextureCoordinateOffset = Vector2.Zero;
|
||||
|
||||
private World _world;
|
||||
private ImageTexture _viewTileTypeTexture;
|
||||
private Image _viewTileTypeImage = new();
|
||||
|
||||
private class SceneTileChunk : Spatial
|
||||
{
|
||||
|
@ -119,6 +127,42 @@ public class WorldView : Spatial
|
|||
return null;
|
||||
}
|
||||
|
||||
private void UpdateWorldViewTexture()
|
||||
{
|
||||
int worldChunkSize = global::World.ChunkSize;
|
||||
int numWorldChunkRows = global::World.NumChunkRows;
|
||||
int numWorldChunkColumns = global::World.NumChunkColumns;
|
||||
|
||||
_viewTileTypeImage.Create(worldChunkSize * numWorldChunkColumns, worldChunkSize * numWorldChunkRows, false, Image.Format.Rgba8);
|
||||
|
||||
Vector2 chunkIndexSouthWest = Vector2.Inf;
|
||||
Vector2 chunkIndexNorthEast = -Vector2.Inf;
|
||||
foreach (SceneTileChunk chunk in _sceneTileChunks)
|
||||
{
|
||||
WorldChunk worldChunk = _world.GetOrCreateWorldChunk((int) chunk.ChunkIndex.x, (int)chunk.ChunkIndex.y, Colors.White);
|
||||
|
||||
if (chunk.ChunkIndex.x <= chunkIndexSouthWest.x && chunk.ChunkIndex.y <= chunkIndexSouthWest.y)
|
||||
{
|
||||
chunkIndexSouthWest = chunk.ChunkIndex;
|
||||
} else if (chunk.ChunkIndex.x >= chunkIndexNorthEast.x && chunk.ChunkIndex.y >= chunkIndexNorthEast.y)
|
||||
{
|
||||
chunkIndexNorthEast = chunk.ChunkIndex;
|
||||
}
|
||||
|
||||
_viewTileTypeImage.BlendRect(
|
||||
worldChunk.TileTypeOffscreenViewport.GetTexture().GetData(),
|
||||
new Rect2(Vector2.Zero, Vector2.One * worldChunkSize),
|
||||
(chunk.ChunkIndex - _world.CenterChunkIndex + Vector2.One) * worldChunkSize);
|
||||
}
|
||||
|
||||
_viewTileTypeTexture = new ImageTexture();
|
||||
_viewTileTypeTexture.CreateFromImage(_viewTileTypeImage);
|
||||
|
||||
WorldTextureCoordinateOffset = chunkIndexSouthWest * worldChunkSize;
|
||||
|
||||
EmitSignal("OnWorldViewTileTypeImageChanged", _viewTileTypeImage);
|
||||
}
|
||||
|
||||
private void HandleWorldTileChange(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices)
|
||||
{
|
||||
Array<SceneTileChunk> removedChunks = new();
|
||||
|
@ -161,6 +205,8 @@ public class WorldView : Spatial
|
|||
_sceneTileChunks.Add(sceneTileChunk);
|
||||
}
|
||||
|
||||
UpdateWorldViewTexture();
|
||||
|
||||
GD.Print("Removed Chunks " + removedChunkIndices.Count);
|
||||
GD.Print("Added Chunks " + addedChunkIndices.Count);
|
||||
GD.Print("Removed chunk count: " + removedChunks.Count);
|
||||
|
|
Loading…
Reference in New Issue