Refactored map generation and masking.
World now has textures for height and tile types.WorldChunkRefactoring
parent
a1f02a8820
commit
36be4bc4c8
179
scenes/Game.cs
179
scenes/Game.cs
|
@ -1,55 +1,55 @@
|
||||||
using Godot;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using Godot;
|
||||||
using Array = Godot.Collections.Array;
|
|
||||||
|
|
||||||
public class Game : Spatial
|
public class Game : Spatial
|
||||||
{
|
{
|
||||||
|
private ImageTexture _blackWhitePatternTexture;
|
||||||
|
private Camera _camera;
|
||||||
|
private Vector3 _cameraOffset;
|
||||||
|
private Label _centerLabel;
|
||||||
|
|
||||||
|
private HexCell _currentTile;
|
||||||
|
|
||||||
// ui elements
|
// ui elements
|
||||||
private Label _framesPerSecondLabel;
|
private Label _framesPerSecondLabel;
|
||||||
private Label _centerLabel;
|
|
||||||
private Label _tileOffsetLabel;
|
|
||||||
private Label _numTilesLabel;
|
|
||||||
private Label _mouseWorldLabel;
|
|
||||||
private Label _mouseTileOffsetLabel;
|
|
||||||
private Label _mouseTileCubeLabel;
|
|
||||||
private Label _numCoordsAddedLabel;
|
|
||||||
private Label _numCoordsRemovedLabel;
|
|
||||||
private TextureRect _worldTextureRect;
|
|
||||||
private TextureRect _heightTextureRect;
|
|
||||||
private Button _generateWorldButton;
|
|
||||||
private Control _gameUi;
|
private Control _gameUi;
|
||||||
|
private Button _generateWorldButton;
|
||||||
private Label _goldCountLabel;
|
private Label _goldCountLabel;
|
||||||
|
private TextureRect _heightTextureRect;
|
||||||
// scene nodes
|
|
||||||
private Spatial _tileHighlight;
|
|
||||||
private Spatial _mouseTileHighlight;
|
|
||||||
private StreamContainer _streamContainer;
|
|
||||||
private Area _streamContainerArea;
|
|
||||||
private Spatial _streamContainerActiveTiles;
|
|
||||||
private Player _player;
|
|
||||||
private TileWorld _tileWorld;
|
|
||||||
private Camera _camera;
|
|
||||||
private World _world;
|
|
||||||
private WorldView _worldView;
|
|
||||||
|
|
||||||
// Resources
|
|
||||||
private PackedScene _tileHighlightScene;
|
|
||||||
private ShaderMaterial _tileMaterial;
|
|
||||||
|
|
||||||
// other members
|
// other members
|
||||||
private HexGrid _hexGrid;
|
private HexGrid _hexGrid;
|
||||||
private HexCell _lastTile;
|
|
||||||
private HexCell _currentTile;
|
|
||||||
private Vector3 _cameraOffset;
|
|
||||||
private ImageTexture _blackWhitePatternTexture;
|
|
||||||
private InteractionSystem _interactionSystem;
|
private InteractionSystem _interactionSystem;
|
||||||
|
private HexCell _lastTile;
|
||||||
|
private Label _mouseTileCubeLabel;
|
||||||
|
private Spatial _mouseTileHighlight;
|
||||||
|
private Label _mouseTileOffsetLabel;
|
||||||
|
private Label _mouseWorldLabel;
|
||||||
|
private Label _numCoordsAddedLabel;
|
||||||
|
private Label _numCoordsRemovedLabel;
|
||||||
|
private Label _numTilesLabel;
|
||||||
|
private Player _player;
|
||||||
|
private StreamContainer _streamContainer;
|
||||||
|
private Spatial _streamContainerActiveTiles;
|
||||||
|
private Area _streamContainerArea;
|
||||||
|
|
||||||
|
// scene nodes
|
||||||
|
private Spatial _tileHighlight;
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
private PackedScene _tileHighlightScene;
|
||||||
|
private TileInstanceManager _tileInstanceManager;
|
||||||
|
private ShaderMaterial _tileMaterial;
|
||||||
|
private Label _tileOffsetLabel;
|
||||||
|
private TileWorld _tileWorld;
|
||||||
|
private World _world;
|
||||||
|
private TextureRect _worldTextureRect;
|
||||||
|
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
// debugStatsContainer
|
// debugStatsContainer
|
||||||
Container debugStatsContainer = (Container)FindNode("DebugStatsContainer");
|
var debugStatsContainer = (Container)FindNode("DebugStatsContainer");
|
||||||
|
|
||||||
_framesPerSecondLabel = debugStatsContainer.GetNode<Label>("fps_label");
|
_framesPerSecondLabel = debugStatsContainer.GetNode<Label>("fps_label");
|
||||||
_centerLabel = debugStatsContainer.GetNode<Label>("center_label");
|
_centerLabel = debugStatsContainer.GetNode<Label>("center_label");
|
||||||
|
@ -62,7 +62,7 @@ public class Game : Spatial
|
||||||
_numCoordsRemovedLabel = debugStatsContainer.GetNode<Label>("num_coords_removed_label");
|
_numCoordsRemovedLabel = debugStatsContainer.GetNode<Label>("num_coords_removed_label");
|
||||||
|
|
||||||
// UI elements
|
// UI elements
|
||||||
Container worldGeneratorContainer = (Container)FindNode("WorldGeneratorContainer");
|
var worldGeneratorContainer = (Container)FindNode("WorldGeneratorContainer");
|
||||||
_worldTextureRect = worldGeneratorContainer.GetNode<TextureRect>("WorldTextureRect");
|
_worldTextureRect = worldGeneratorContainer.GetNode<TextureRect>("WorldTextureRect");
|
||||||
_heightTextureRect = worldGeneratorContainer.GetNode<TextureRect>("HeightTextureRect");
|
_heightTextureRect = worldGeneratorContainer.GetNode<TextureRect>("HeightTextureRect");
|
||||||
_generateWorldButton = worldGeneratorContainer.GetNode<Button>("WorldGenerateButton");
|
_generateWorldButton = worldGeneratorContainer.GetNode<Button>("WorldGenerateButton");
|
||||||
|
@ -84,10 +84,10 @@ public class Game : Spatial
|
||||||
_cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation;
|
_cameraOffset = _camera.GlobalTranslation - _player.GlobalTranslation;
|
||||||
|
|
||||||
_world = (World)FindNode("World");
|
_world = (World)FindNode("World");
|
||||||
_worldView = (WorldView)FindNode("WorldView");
|
_tileInstanceManager = (TileInstanceManager)FindNode("TileInstanceManager");
|
||||||
|
|
||||||
// populate UI values
|
// populate UI values
|
||||||
Slider generatorWorldSizeSlider = worldGeneratorContainer.GetNode<Slider>("HBoxContainer/WorldSizeSlider");
|
var generatorWorldSizeSlider = worldGeneratorContainer.GetNode<Slider>("HBoxContainer/WorldSizeSlider");
|
||||||
generatorWorldSizeSlider.Value = _tileWorld.Size;
|
generatorWorldSizeSlider.Value = _tileWorld.Size;
|
||||||
|
|
||||||
Debug.Assert(_tileWorld != null);
|
Debug.Assert(_tileWorld != null);
|
||||||
|
@ -98,7 +98,7 @@ public class Game : Spatial
|
||||||
Debug.Assert(_tileMaterial != null);
|
Debug.Assert(_tileMaterial != null);
|
||||||
|
|
||||||
_blackWhitePatternTexture = new ImageTexture();
|
_blackWhitePatternTexture = new ImageTexture();
|
||||||
Image image = new Image();
|
var image = new Image();
|
||||||
image.Load("assets/4x4checker.png");
|
image.Load("assets/4x4checker.png");
|
||||||
_blackWhitePatternTexture.CreateFromImage(image, (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
_blackWhitePatternTexture.CreateFromImage(image, (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||||
|
|
||||||
|
@ -122,26 +122,20 @@ public class Game : Spatial
|
||||||
_player.TaskQueueComponent.Connect("StartInteraction", _interactionSystem,
|
_player.TaskQueueComponent.Connect("StartInteraction", _interactionSystem,
|
||||||
nameof(_interactionSystem.OnStartInteraction));
|
nameof(_interactionSystem.OnStartInteraction));
|
||||||
_player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged));
|
_player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged));
|
||||||
_worldView.Connect("TileClicked", this, nameof(OnTileClicked));
|
_tileInstanceManager.Connect("TileClicked", this, nameof(OnTileClicked));
|
||||||
_worldView.Connect("TileHovered", this, nameof(OnTileHovered));
|
_tileInstanceManager.Connect("TileHovered", this, nameof(OnTileHovered));
|
||||||
_worldView.Connect("OnWorldViewTileTypeImageChanged", this, nameof(OnWorldViewTileTypeImageChanged));
|
_world.Connect("OnWorldViewTileTypeImageChanged", this, nameof(OnWorldViewTileTypeImageChanged));
|
||||||
|
_world.Connect("OnHeightmapImageChanged", this, nameof(OnHeightmapImageChanged));
|
||||||
|
|
||||||
// register entity events
|
// register entity events
|
||||||
foreach (Node node in GetNode("Entities").GetChildren())
|
foreach (Node node in GetNode("Entities").GetChildren())
|
||||||
{
|
|
||||||
if (node.HasSignal("EntityClicked"))
|
if (node.HasSignal("EntityClicked"))
|
||||||
{
|
|
||||||
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
|
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform dependency injection
|
// perform dependency injection
|
||||||
//_streamContainer.SetWorld(_tileWorld);Clicked
|
//_streamContainer.SetWorld(_tileWorld);Clicked
|
||||||
WorldInfoComponent worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
|
var worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
|
||||||
if (worldInfoComponent != null)
|
if (worldInfoComponent != null) worldInfoComponent.SetWorld(_tileWorld);
|
||||||
{
|
|
||||||
worldInfoComponent.SetWorld(_tileWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
_tileWorld.Generate(_tileWorld.Size);
|
_tileWorld.Generate(_tileWorld.Size);
|
||||||
UpdateCurrentTile();
|
UpdateCurrentTile();
|
||||||
|
@ -151,23 +145,17 @@ public class Game : Spatial
|
||||||
|
|
||||||
public override void _Input(InputEvent inputEvent)
|
public override void _Input(InputEvent inputEvent)
|
||||||
{
|
{
|
||||||
if (inputEvent.IsAction("Forward"))
|
if (inputEvent.IsAction("Forward")) GD.Print("Forward");
|
||||||
{
|
|
||||||
GD.Print("Forward");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputEvent.IsAction("Back"))
|
if (inputEvent.IsAction("Back")) GD.Print("Back");
|
||||||
{
|
|
||||||
GD.Print("Back");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateCurrentTile()
|
public void UpdateCurrentTile()
|
||||||
{
|
{
|
||||||
// cast a ray from the camera to center
|
// cast a ray from the camera to center
|
||||||
Vector3 cameraNormal = _camera.ProjectRayNormal(_camera.GetViewport().Size * 0.5f);
|
var cameraNormal = _camera.ProjectRayNormal(_camera.GetViewport().Size * 0.5f);
|
||||||
Vector3 cameraPosition = _camera.ProjectRayOrigin(_camera.GetViewport().Size * 0.5f);
|
var cameraPosition = _camera.ProjectRayOrigin(_camera.GetViewport().Size * 0.5f);
|
||||||
Vector3 cameraDir = cameraNormal - cameraPosition;
|
var cameraDir = cameraNormal - cameraPosition;
|
||||||
|
|
||||||
Vector3 centerCoord;
|
Vector3 centerCoord;
|
||||||
|
|
||||||
|
@ -197,8 +185,8 @@ public class Game : Spatial
|
||||||
|
|
||||||
UpdateCurrentTile();
|
UpdateCurrentTile();
|
||||||
|
|
||||||
Transform tileHighlightTransform = Transform.Identity;
|
var tileHighlightTransform = Transform.Identity;
|
||||||
Vector2 currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
|
var currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
|
||||||
tileHighlightTransform.origin.x = currentTileCenter.x;
|
tileHighlightTransform.origin.x = currentTileCenter.x;
|
||||||
tileHighlightTransform.origin.z = currentTileCenter.y;
|
tileHighlightTransform.origin.z = currentTileCenter.y;
|
||||||
_tileHighlight.Transform = tileHighlightTransform;
|
_tileHighlight.Transform = tileHighlightTransform;
|
||||||
|
@ -212,7 +200,7 @@ public class Game : Spatial
|
||||||
_numCoordsRemovedLabel.Text = _streamContainer.RemovedCoords.Count.ToString();
|
_numCoordsRemovedLabel.Text = _streamContainer.RemovedCoords.Count.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform cameraTransform = _camera.Transform;
|
var cameraTransform = _camera.Transform;
|
||||||
cameraTransform.origin = _player.GlobalTranslation + _cameraOffset;
|
cameraTransform.origin = _player.GlobalTranslation + _cameraOffset;
|
||||||
_camera.Transform = cameraTransform;
|
_camera.Transform = cameraTransform;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +209,7 @@ public class Game : Spatial
|
||||||
public void OnGenerateButton()
|
public void OnGenerateButton()
|
||||||
{
|
{
|
||||||
GD.Print("Generating");
|
GD.Print("Generating");
|
||||||
Slider worldSizeSlider = (Slider)FindNode("WorldSizeSlider");
|
var worldSizeSlider = (Slider)FindNode("WorldSizeSlider");
|
||||||
if (worldSizeSlider == null)
|
if (worldSizeSlider == null)
|
||||||
{
|
{
|
||||||
GD.PrintErr("Could not find WorldSizeSlider!");
|
GD.PrintErr("Could not find WorldSizeSlider!");
|
||||||
|
@ -236,8 +224,8 @@ public class Game : Spatial
|
||||||
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
|
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
|
||||||
int shapeIndex)
|
int shapeIndex)
|
||||||
{
|
{
|
||||||
HexCell cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
|
var cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
|
||||||
Transform highlightTransform = Transform.Identity;
|
var highlightTransform = Transform.Identity;
|
||||||
|
|
||||||
_mouseWorldLabel.Text = position.ToString("F3");
|
_mouseWorldLabel.Text = position.ToString("F3");
|
||||||
_mouseTileOffsetLabel.Text = cellAtCursor.OffsetCoords.ToString("N");
|
_mouseTileOffsetLabel.Text = cellAtCursor.OffsetCoords.ToString("N");
|
||||||
|
@ -245,23 +233,15 @@ public class Game : Spatial
|
||||||
_mouseTileHighlight.Transform = highlightTransform;
|
_mouseTileHighlight.Transform = highlightTransform;
|
||||||
|
|
||||||
if (inputEvent is InputEventMouseButton && ((InputEventMouseButton)inputEvent).Pressed)
|
if (inputEvent is InputEventMouseButton && ((InputEventMouseButton)inputEvent).Pressed)
|
||||||
{
|
|
||||||
_streamContainer.EmitSignal("TileClicked", _streamContainer.GetTile3dAt(cellAtCursor.OffsetCoords));
|
_streamContainer.EmitSignal("TileClicked", _streamContainer.GetTile3dAt(cellAtCursor.OffsetCoords));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnTileClicked(HexTile3D tile)
|
public void OnTileClicked(HexTile3D tile)
|
||||||
{
|
{
|
||||||
if (_player == null)
|
if (_player == null) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_player.InteractionComponent != null)
|
if (_player.InteractionComponent != null) _player.InteractionComponent.EmitSignal("InteractionEnd");
|
||||||
{
|
|
||||||
_player.InteractionComponent.EmitSignal("InteractionEnd");
|
|
||||||
}
|
|
||||||
|
|
||||||
_player.TaskQueueComponent.Reset();
|
_player.TaskQueueComponent.Reset();
|
||||||
_player.TaskQueueComponent.Queue.Enqueue(new TaskQueueComponent.NavigationTask(
|
_player.TaskQueueComponent.Queue.Enqueue(new TaskQueueComponent.NavigationTask(
|
||||||
|
@ -270,7 +250,7 @@ public class Game : Spatial
|
||||||
|
|
||||||
public void OnTileHovered(HexTile3D tile)
|
public void OnTileHovered(HexTile3D tile)
|
||||||
{
|
{
|
||||||
Transform highlightTransform = tile.GlobalTransform;
|
var highlightTransform = tile.GlobalTransform;
|
||||||
_mouseTileHighlight.Transform = highlightTransform;
|
_mouseTileHighlight.Transform = highlightTransform;
|
||||||
_mouseWorldLabel.Text = highlightTransform.origin.ToString("F3");
|
_mouseWorldLabel.Text = highlightTransform.origin.ToString("F3");
|
||||||
_mouseTileOffsetLabel.Text = tile.OffsetCoords.ToString("N");
|
_mouseTileOffsetLabel.Text = tile.OffsetCoords.ToString("N");
|
||||||
|
@ -283,7 +263,7 @@ public class Game : Spatial
|
||||||
{
|
{
|
||||||
GD.Print("Clicked on entity at " + entity.GlobalTranslation);
|
GD.Print("Clicked on entity at " + entity.GlobalTranslation);
|
||||||
|
|
||||||
Spatial mountPoint = (Spatial)entity.FindNode("MountPoint");
|
var mountPoint = (Spatial)entity.FindNode("MountPoint");
|
||||||
if (mountPoint != null)
|
if (mountPoint != null)
|
||||||
{
|
{
|
||||||
_player.TaskQueueComponent.Reset();
|
_player.TaskQueueComponent.Reset();
|
||||||
|
@ -296,8 +276,8 @@ public class Game : Spatial
|
||||||
|
|
||||||
public void ResetGameState()
|
public void ResetGameState()
|
||||||
{
|
{
|
||||||
Transform playerStartTransform = Transform.Identity;
|
var playerStartTransform = Transform.Identity;
|
||||||
float height = _tileWorld.GetHeightAtOffset(new Vector2(0, 0));
|
var height = _tileWorld.GetHeightAtOffset(new Vector2(0, 0));
|
||||||
playerStartTransform.origin.y = height;
|
playerStartTransform.origin.y = height;
|
||||||
_player.Transform = playerStartTransform;
|
_player.Transform = playerStartTransform;
|
||||||
_player.TaskQueueComponent.Reset();
|
_player.TaskQueueComponent.Reset();
|
||||||
|
@ -308,10 +288,10 @@ public class Game : Spatial
|
||||||
|
|
||||||
foreach (Spatial entity in GetNode("Entities").GetChildren())
|
foreach (Spatial entity in GetNode("Entities").GetChildren())
|
||||||
{
|
{
|
||||||
Transform entityTransform = entity.Transform;
|
var entityTransform = entity.Transform;
|
||||||
Vector2 entityPlanePos = new Vector2(entityTransform.origin.x, entityTransform.origin.z);
|
var entityPlanePos = new Vector2(entityTransform.origin.x, entityTransform.origin.z);
|
||||||
Vector2 entityOffsetCoordinates = _hexGrid.GetHexAt(entityPlanePos).OffsetCoords;
|
var entityOffsetCoordinates = _hexGrid.GetHexAt(entityPlanePos).OffsetCoords;
|
||||||
float entityHeight = _tileWorld.GetHeightAtOffset(entityOffsetCoordinates);
|
var entityHeight = _tileWorld.GetHeightAtOffset(entityOffsetCoordinates);
|
||||||
entityTransform.origin.y = entityHeight;
|
entityTransform.origin.y = entityHeight;
|
||||||
entity.Transform = entityTransform;
|
entity.Transform = entityTransform;
|
||||||
}
|
}
|
||||||
|
@ -332,48 +312,53 @@ public class Game : Spatial
|
||||||
|
|
||||||
// Connect all signals of the generated world
|
// Connect all signals of the generated world
|
||||||
foreach (Node node in _tileWorld.Entities.GetChildren())
|
foreach (Node node in _tileWorld.Entities.GetChildren())
|
||||||
{
|
|
||||||
if (node.HasSignal("EntityClicked"))
|
if (node.HasSignal("EntityClicked"))
|
||||||
{
|
|
||||||
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
|
node.Connect("EntityClicked", this, nameof(OnEntityClicked));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateWorldTextures()
|
private void UpdateWorldTextures()
|
||||||
{
|
{
|
||||||
GD.Print("Updating World textures");
|
GD.Print("Updating World textures");
|
||||||
|
|
||||||
ImageTexture newWorldTexture = new ImageTexture();
|
var newWorldTexture = new ImageTexture();
|
||||||
newWorldTexture.CreateFromImage(_tileWorld.ColormapImage,
|
newWorldTexture.CreateFromImage(_tileWorld.ColormapImage,
|
||||||
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||||
_worldTextureRect.Texture = newWorldTexture;
|
_worldTextureRect.Texture = newWorldTexture;
|
||||||
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
|
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
|
||||||
_tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.ColormapImage.GetSize().x);
|
_tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.ColormapImage.GetSize().x);
|
||||||
|
|
||||||
ImageTexture newHeightTexture = new ImageTexture();
|
var newHeightTexture = new ImageTexture();
|
||||||
newHeightTexture.CreateFromImage(_tileWorld.HeightmapImage,
|
newHeightTexture.CreateFromImage(_tileWorld.HeightmapImage,
|
||||||
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||||
_heightTextureRect.Texture = newHeightTexture;
|
_heightTextureRect.Texture = newHeightTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnHeightmapImageChanged(Image heightmapImage)
|
||||||
|
{
|
||||||
|
var newHeightmapTexture = new ImageTexture();
|
||||||
|
newHeightmapTexture.CreateFromImage(heightmapImage,
|
||||||
|
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||||
|
|
||||||
|
_heightTextureRect.Texture = newHeightmapTexture;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage)
|
private void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage)
|
||||||
{
|
{
|
||||||
ImageTexture newWorldTexture = new ImageTexture();
|
var newWorldTexture = new ImageTexture();
|
||||||
newWorldTexture.CreateFromImage(viewTileTypeImage,
|
newWorldTexture.CreateFromImage(viewTileTypeImage,
|
||||||
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||||
|
|
||||||
_worldTextureRect.Texture = newWorldTexture;
|
_worldTextureRect.Texture = newWorldTexture;
|
||||||
|
|
||||||
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
|
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
|
||||||
_tileMaterial.SetShaderParam("TextureSize", (int)newWorldTexture.GetSize().x);
|
_tileMaterial.SetShaderParam("TextureSize", (int)newWorldTexture.GetSize().x);
|
||||||
_tileMaterial.SetShaderParam("CoordinateOffsetU", (int) _worldView.WorldTextureCoordinateOffset.x);
|
_tileMaterial.SetShaderParam("CoordinateOffsetU", (int)_tileInstanceManager.WorldTextureCoordinateOffset.x);
|
||||||
_tileMaterial.SetShaderParam("CoordinateOffsetV", (int) _worldView.WorldTextureCoordinateOffset.y);
|
_tileMaterial.SetShaderParam("CoordinateOffsetV", (int)_tileInstanceManager.WorldTextureCoordinateOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnGoldCountChanged(int goldCount)
|
public void OnGoldCountChanged(int goldCount)
|
||||||
{
|
{
|
||||||
AnimationPlayer animationPlayer = _gameUi.GetNode<AnimationPlayer>("AnimationPlayer");
|
var animationPlayer = _gameUi.GetNode<AnimationPlayer>("AnimationPlayer");
|
||||||
_goldCountLabel.Text = goldCount.ToString();
|
_goldCountLabel.Text = goldCount.ToString();
|
||||||
animationPlayer.CurrentAnimation = "FlashLabel";
|
animationPlayer.CurrentAnimation = "FlashLabel";
|
||||||
animationPlayer.Seek(0);
|
animationPlayer.Seek(0);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4,7 +4,7 @@ using Godot.Collections;
|
||||||
using Vector2 = Godot.Vector2;
|
using Vector2 = Godot.Vector2;
|
||||||
using Vector3 = Godot.Vector3;
|
using Vector3 = Godot.Vector3;
|
||||||
|
|
||||||
public class WorldView : Spatial
|
public class TileInstanceManager : Spatial
|
||||||
{
|
{
|
||||||
// ui elements
|
// ui elements
|
||||||
|
|
||||||
|
@ -22,8 +22,6 @@ public class WorldView : Spatial
|
||||||
delegate void TileClicked(HexTile3D tile3d);
|
delegate void TileClicked(HexTile3D tile3d);
|
||||||
[Signal]
|
[Signal]
|
||||||
delegate void TileHovered(HexTile3D tile3d);
|
delegate void TileHovered(HexTile3D tile3d);
|
||||||
[Signal]
|
|
||||||
delegate void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage);
|
|
||||||
|
|
||||||
// other members
|
// other members
|
||||||
public Vector2 WorldTextureCoordinateOffset = Vector2.Zero;
|
public Vector2 WorldTextureCoordinateOffset = Vector2.Zero;
|
||||||
|
@ -128,41 +126,6 @@ public class WorldView : Spatial
|
||||||
return null;
|
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)
|
private void HandleWorldTileChange(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices)
|
||||||
{
|
{
|
||||||
|
@ -206,8 +169,6 @@ public class WorldView : Spatial
|
||||||
_sceneTileChunks.Add(sceneTileChunk);
|
_sceneTileChunks.Add(sceneTileChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateWorldViewTexture();
|
|
||||||
|
|
||||||
GD.Print("Removed Chunks " + removedChunkIndices.Count);
|
GD.Print("Removed Chunks " + removedChunkIndices.Count);
|
||||||
GD.Print("Added Chunks " + addedChunkIndices.Count);
|
GD.Print("Added Chunks " + addedChunkIndices.Count);
|
||||||
GD.Print("Removed chunk count: " + removedChunks.Count);
|
GD.Print("Removed chunk count: " + removedChunks.Count);
|
344
scenes/World.cs
344
scenes/World.cs
|
@ -1,8 +1,8 @@
|
||||||
using Godot;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Godot;
|
||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
|
|
||||||
public class World : Spatial
|
public class World : Spatial
|
||||||
|
@ -15,46 +15,41 @@ public class World : Spatial
|
||||||
Objects,
|
Objects,
|
||||||
Done
|
Done
|
||||||
}
|
}
|
||||||
public GenerationState State = GenerationState.Done;
|
|
||||||
public Vector2 CenterChunkIndex = Vector2.Zero;
|
|
||||||
|
|
||||||
// referenced scenes
|
|
||||||
private PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
|
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
public const int ChunkSize = 16;
|
public const int ChunkSize = 16;
|
||||||
public const int NumChunkRows = 3;
|
public const int NumChunkRows = 3;
|
||||||
public const int NumChunkColumns = NumChunkRows;
|
public const int NumChunkColumns = NumChunkRows;
|
||||||
public int Seed = 0;
|
private List<Vector2> _activeChunkIndices = new();
|
||||||
public HexGrid HexGrid = new HexGrid();
|
private readonly List<Vector2> _addedChunkIndices = new();
|
||||||
public Spatial Chunks;
|
private readonly Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
|
||||||
public Color DebugColor;
|
private Rect2 _centerChunkRect;
|
||||||
|
|
||||||
// ui elements
|
|
||||||
|
|
||||||
// scene nodes
|
|
||||||
|
|
||||||
// resources
|
|
||||||
|
|
||||||
// exports
|
|
||||||
// [Export] public Vector2 Size = new Vector2(1, 1);
|
|
||||||
|
|
||||||
// signals
|
|
||||||
[Signal]
|
|
||||||
delegate void OnTilesChanged(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices);
|
|
||||||
|
|
||||||
// delegate void OnCoordClicked(Vector2 world_pos);
|
// delegate void OnCoordClicked(Vector2 world_pos);
|
||||||
|
|
||||||
// other members
|
// other members
|
||||||
private Vector2 _centerPlaneCoord;
|
private Vector2 _centerPlaneCoord;
|
||||||
private Rect2 _centerChunkRect = new Rect2();
|
|
||||||
private Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
|
private readonly Image _heightmapImage = new();
|
||||||
private List<Vector2> _activeChunkIndices = new();
|
private ImageTexture _heightmapTexture;
|
||||||
private List<Vector2> _addedChunkIndices = new();
|
private readonly List<Vector2> _removedChunkIndices = new();
|
||||||
private List<Vector2> _removedChunkIndices = new();
|
private TileInstanceManager _tileInstanceManager;
|
||||||
|
|
||||||
|
private readonly Image _tileTypeMapImage = new();
|
||||||
|
private ImageTexture _viewTileTypeTexture;
|
||||||
|
|
||||||
|
// referenced scenes
|
||||||
|
private readonly PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
|
||||||
|
public Vector2 CenterChunkIndex = Vector2.Zero;
|
||||||
|
public Spatial Chunks;
|
||||||
|
public Color DebugColor;
|
||||||
|
public HexGrid HexGrid = new();
|
||||||
|
|
||||||
private OpenSimplexNoise noiseGenerator = new();
|
private OpenSimplexNoise noiseGenerator = new();
|
||||||
|
public int Seed = 0;
|
||||||
|
|
||||||
|
public GenerationState State = GenerationState.Done;
|
||||||
|
|
||||||
public World()
|
public World()
|
||||||
{
|
{
|
||||||
Debug.Assert(ChunkSize % 2 == 0);
|
Debug.Assert(ChunkSize % 2 == 0);
|
||||||
|
@ -68,8 +63,11 @@ public class World : Spatial
|
||||||
Chunks = (Spatial)FindNode("Chunks");
|
Chunks = (Spatial)FindNode("Chunks");
|
||||||
Debug.Assert(Chunks != null);
|
Debug.Assert(Chunks != null);
|
||||||
|
|
||||||
|
_tileInstanceManager = (TileInstanceManager)FindNode("TileInstanceManager");
|
||||||
|
Debug.Assert(_tileInstanceManager != null);
|
||||||
|
|
||||||
InitNoiseGenerator();
|
InitNoiseGenerator();
|
||||||
|
|
||||||
SetCenterPlaneCoord(Vector2.Zero);
|
SetCenterPlaneCoord(Vector2.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +86,7 @@ public class World : Spatial
|
||||||
{
|
{
|
||||||
if (IsTileCached(xIndex, yIndex))
|
if (IsTileCached(xIndex, yIndex))
|
||||||
{
|
{
|
||||||
WorldChunk cachedChunk = _cachedWorldChunks[new Vector2(xIndex, yIndex)];
|
var cachedChunk = _cachedWorldChunks[new Vector2(xIndex, yIndex)];
|
||||||
return cachedChunk;
|
return cachedChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,18 +100,18 @@ public class World : Spatial
|
||||||
|
|
||||||
private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor)
|
private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor)
|
||||||
{
|
{
|
||||||
WorldChunk result = (WorldChunk)_worldChunkScene.Instance();
|
var result = (WorldChunk)_worldChunkScene.Instance();
|
||||||
result.SetSize(ChunkSize);
|
result.SetSize(ChunkSize);
|
||||||
|
|
||||||
Vector2 offsetCoordSouthWest = new Vector2(xIndex, yIndex) * ChunkSize;
|
var offsetCoordSouthWest = new Vector2(xIndex, yIndex) * ChunkSize;
|
||||||
Vector2 offsetCoordNorthEast = offsetCoordSouthWest + new Vector2(1, 1) * (ChunkSize - 1);
|
var offsetCoordNorthEast = offsetCoordSouthWest + new Vector2(1, 1) * (ChunkSize - 1);
|
||||||
|
|
||||||
Vector2 planeCoordSouthWest = HexGrid.GetHexCenterFromOffset(offsetCoordSouthWest) +
|
var planeCoordSouthWest = HexGrid.GetHexCenterFromOffset(offsetCoordSouthWest) +
|
||||||
new Vector2(-HexGrid.HexSize.x, HexGrid.HexSize.y) * 0.5f;
|
new Vector2(-HexGrid.HexSize.x, HexGrid.HexSize.y) * 0.5f;
|
||||||
Vector2 planeCoordNorthEast = HexGrid.GetHexCenterFromOffset(offsetCoordNorthEast) +
|
var planeCoordNorthEast = HexGrid.GetHexCenterFromOffset(offsetCoordNorthEast) +
|
||||||
new Vector2(HexGrid.HexSize.x, -HexGrid.HexSize.y) * 0.5f;
|
new Vector2(HexGrid.HexSize.x, -HexGrid.HexSize.y) * 0.5f;
|
||||||
|
|
||||||
result.ChunkAddress = new Vector2(xIndex, yIndex);
|
result.ChunkIndex = new Vector2(xIndex, yIndex);
|
||||||
result.PlaneRect = new Rect2(
|
result.PlaneRect = new Rect2(
|
||||||
new Vector2(planeCoordSouthWest.x, planeCoordNorthEast.y),
|
new Vector2(planeCoordSouthWest.x, planeCoordNorthEast.y),
|
||||||
new Vector2(planeCoordNorthEast.x - planeCoordSouthWest.x, planeCoordSouthWest.y - planeCoordNorthEast.y));
|
new Vector2(planeCoordNorthEast.x - planeCoordSouthWest.x, planeCoordSouthWest.y - planeCoordNorthEast.y));
|
||||||
|
@ -122,7 +120,7 @@ public class World : Spatial
|
||||||
result.DebugColor.a = 0.6f;
|
result.DebugColor.a = 0.6f;
|
||||||
|
|
||||||
Chunks.AddChild(result);
|
Chunks.AddChild(result);
|
||||||
Vector2 chunkIndex = new Vector2(xIndex, yIndex);
|
var chunkIndex = new Vector2(xIndex, yIndex);
|
||||||
_cachedWorldChunks.Add(chunkIndex, result);
|
_cachedWorldChunks.Add(chunkIndex, result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -135,156 +133,234 @@ public class World : Spatial
|
||||||
GD.PrintErr("Cannot update chunk to new planeCoord " + planeCoord + ": Chunk generation not yet finished!");
|
GD.PrintErr("Cannot update chunk to new planeCoord " + planeCoord + ": Chunk generation not yet finished!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark all chunks as retired
|
// mark all chunks as retired
|
||||||
Godot.Collections.Dictionary<Vector2, WorldChunk> oldCachedChunks = new(_cachedWorldChunks);
|
Godot.Collections.Dictionary<Vector2, WorldChunk> oldCachedChunks = new(_cachedWorldChunks);
|
||||||
|
|
||||||
// set new center chunk
|
// set new center chunk
|
||||||
var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
|
var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
|
||||||
CenterChunkIndex = new Vector2(chunkIndex.Item1, chunkIndex.Item2);
|
CenterChunkIndex = new Vector2(chunkIndex.Item1, chunkIndex.Item2);
|
||||||
|
|
||||||
WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
|
var currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
|
||||||
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||||
_centerChunkRect = currentChunk.PlaneRect;
|
_centerChunkRect = currentChunk.PlaneRect;
|
||||||
|
|
||||||
// load or create adjacent chunks
|
// load or create adjacent chunks
|
||||||
_activeChunkIndices = new List<Vector2>();
|
_activeChunkIndices = new List<Vector2>();
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2 - 1));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2 - 1));
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 - 1));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 - 1));
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 - 1));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 - 1));
|
||||||
|
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2));
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2));
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2));
|
||||||
|
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2 + 1));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 - 1, chunkIndex.Item2 + 1));
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 + 1));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 + 1));
|
||||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 + 1));
|
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 + 1));
|
||||||
|
|
||||||
Debug.Assert(_activeChunkIndices.Count == NumChunkRows * NumChunkColumns);
|
Debug.Assert(_activeChunkIndices.Count == NumChunkRows * NumChunkColumns);
|
||||||
|
|
||||||
foreach(Vector2 activeChunkIndex in _activeChunkIndices)
|
foreach (var activeChunkIndex in _activeChunkIndices)
|
||||||
{
|
GetOrCreateWorldChunk((int)activeChunkIndex.x, (int)activeChunkIndex.y,
|
||||||
GetOrCreateWorldChunk((int) activeChunkIndex.x, (int) activeChunkIndex.y, new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||||
}
|
|
||||||
|
|
||||||
// unload retired chunks
|
// unload retired chunks
|
||||||
_removedChunkIndices.Clear();
|
_removedChunkIndices.Clear();
|
||||||
_addedChunkIndices.Clear();
|
_addedChunkIndices.Clear();
|
||||||
|
|
||||||
foreach (var cachedChunkKey in oldCachedChunks.Keys)
|
foreach (var cachedChunkKey in oldCachedChunks.Keys)
|
||||||
{
|
|
||||||
if (!_activeChunkIndices.Contains(cachedChunkKey))
|
if (!_activeChunkIndices.Contains(cachedChunkKey))
|
||||||
{
|
|
||||||
RemoveChunk(cachedChunkKey);
|
RemoveChunk(cachedChunkKey);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var chunkKey in _activeChunkIndices)
|
foreach (var chunkKey in _activeChunkIndices)
|
||||||
{
|
|
||||||
if (!oldCachedChunks.ContainsKey(chunkKey))
|
if (!oldCachedChunks.ContainsKey(chunkKey))
|
||||||
{
|
{
|
||||||
_addedChunkIndices.Add(chunkKey);
|
_addedChunkIndices.Add(chunkKey);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_addedChunkIndices.Count > 0)
|
var chunk = _cachedWorldChunks[chunkKey];
|
||||||
{
|
GenerateChunkNoiseMap(chunk);
|
||||||
State = GenerationState.Heightmap;
|
|
||||||
}
|
State = GenerationState.Heightmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateChunkNoiseMap(WorldChunk chunk)
|
||||||
|
{
|
||||||
|
var chunkIndex = chunk.ChunkIndex;
|
||||||
|
|
||||||
|
var debugChunkColor = new Color(Mathf.Abs(chunkIndex.x) / 5, Mathf.Abs(chunkIndex.y) / 5,
|
||||||
|
Mathf.RoundToInt(Mathf.Abs(chunkIndex.x + chunkIndex.y)) % 2);
|
||||||
|
|
||||||
|
var noiseImageTexture = new ImageTexture();
|
||||||
|
noiseImageTexture.CreateFromImage(noiseGenerator.GetImage(ChunkSize, ChunkSize, chunkIndex * ChunkSize),
|
||||||
|
0);
|
||||||
|
|
||||||
|
// Debug Texture
|
||||||
|
var simpleImage = new Image();
|
||||||
|
simpleImage.Create(ChunkSize, ChunkSize, false, Image.Format.Rgb8);
|
||||||
|
simpleImage.Lock();
|
||||||
|
|
||||||
|
foreach (var i in Enumerable.Range(0, ChunkSize))
|
||||||
|
foreach (var j in Enumerable.Range(0, ChunkSize))
|
||||||
|
if ((i + j) % 2 == 0)
|
||||||
|
simpleImage.SetPixelv(new Vector2(i, j), Colors.Aqua);
|
||||||
|
else
|
||||||
|
simpleImage.SetPixelv(new Vector2(i, j), debugChunkColor);
|
||||||
|
|
||||||
|
simpleImage.Unlock();
|
||||||
|
// noiseImageTexture.CreateFromImage(simpleImage, 0);
|
||||||
|
|
||||||
|
chunk.SetNoisemap(noiseImageTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveChunk(Vector2 cachedChunkKey)
|
private void RemoveChunk(Vector2 cachedChunkKey)
|
||||||
{
|
{
|
||||||
_cachedWorldChunks.Remove(cachedChunkKey);
|
_cachedWorldChunks.Remove(cachedChunkKey);
|
||||||
_removedChunkIndices.Add(cachedChunkKey);
|
_removedChunkIndices.Add(cachedChunkKey);
|
||||||
|
|
||||||
foreach (WorldChunk chunk in Chunks.GetChildren())
|
foreach (WorldChunk chunk in Chunks.GetChildren())
|
||||||
{
|
if (chunk.ChunkIndex == new Vector2(cachedChunkKey.x, cachedChunkKey.y))
|
||||||
if (chunk.ChunkAddress == new Vector2(cachedChunkKey.x, cachedChunkKey.y))
|
|
||||||
{
|
|
||||||
chunk.QueueFree();
|
chunk.QueueFree();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Tuple<int, int> GetChunkTupleFromPlaneCoord(Vector2 planeCoord)
|
private Tuple<int, int> GetChunkTupleFromPlaneCoord(Vector2 planeCoord)
|
||||||
{
|
{
|
||||||
HexCell centerOffsetCoord = HexGrid.GetHexAt(planeCoord);
|
var centerOffsetCoord = HexGrid.GetHexAt(planeCoord);
|
||||||
Vector2 chunkIndexFloat = (centerOffsetCoord.OffsetCoords / (float)ChunkSize).Floor();
|
var chunkIndexFloat = (centerOffsetCoord.OffsetCoords / ChunkSize).Floor();
|
||||||
Tuple<int, int> chunkIndex = new Tuple<int, int>((int)chunkIndexFloat.x, (int)chunkIndexFloat.y);
|
var chunkIndex = new Tuple<int, int>((int)chunkIndexFloat.x, (int)chunkIndexFloat.y);
|
||||||
return chunkIndex;
|
return chunkIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCenterPlaneCoord(Vector2 centerPlaneCoord)
|
public void SetCenterPlaneCoord(Vector2 centerPlaneCoord)
|
||||||
{
|
{
|
||||||
if (!_centerChunkRect.HasPoint(centerPlaneCoord))
|
if (!_centerChunkRect.HasPoint(centerPlaneCoord)) UpdateCenterChunkFromPlaneCoord(centerPlaneCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateWorldViewTexture()
|
||||||
|
{
|
||||||
|
var worldChunkSize = ChunkSize;
|
||||||
|
var numWorldChunkRows = NumChunkRows;
|
||||||
|
var numWorldChunkColumns = NumChunkColumns;
|
||||||
|
|
||||||
|
_heightmapImage.Create(worldChunkSize * numWorldChunkColumns, worldChunkSize * numWorldChunkRows, false,
|
||||||
|
Image.Format.Rgba8);
|
||||||
|
_tileTypeMapImage.Create(worldChunkSize * numWorldChunkColumns, worldChunkSize * numWorldChunkRows, false,
|
||||||
|
Image.Format.Rgba8);
|
||||||
|
|
||||||
|
var chunkIndexSouthWest = Vector2.Inf;
|
||||||
|
var chunkIndexNorthEast = -Vector2.Inf;
|
||||||
|
|
||||||
|
foreach (var chunkIndex in _activeChunkIndices)
|
||||||
{
|
{
|
||||||
UpdateCenterChunkFromPlaneCoord(centerPlaneCoord);
|
var worldChunk = GetOrCreateWorldChunk((int)chunkIndex.x, (int)chunkIndex.y, Colors.White);
|
||||||
|
|
||||||
|
if (chunkIndex.x <= chunkIndexSouthWest.x && chunkIndex.y <= chunkIndexSouthWest.y)
|
||||||
|
chunkIndexSouthWest = chunkIndex;
|
||||||
|
else if (chunkIndex.x >= chunkIndexNorthEast.x && chunkIndex.y >= chunkIndexNorthEast.y)
|
||||||
|
chunkIndexNorthEast = chunkIndex;
|
||||||
|
|
||||||
|
_heightmapImage.BlendRect(
|
||||||
|
worldChunk.HeightmapOffscreenViewport.GetTexture().GetData(),
|
||||||
|
new Rect2(Vector2.Zero, Vector2.One * worldChunkSize),
|
||||||
|
(chunkIndex - CenterChunkIndex + Vector2.One) * worldChunkSize);
|
||||||
|
|
||||||
|
_tileTypeMapImage.BlendRect(
|
||||||
|
worldChunk.TileTypeOffscreenViewport.GetTexture().GetData(),
|
||||||
|
new Rect2(Vector2.Zero, Vector2.One * worldChunkSize),
|
||||||
|
(chunkIndex - CenterChunkIndex + Vector2.One) * worldChunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
_heightmapTexture = new ImageTexture();
|
||||||
|
_heightmapTexture.CreateFromImage(_heightmapImage);
|
||||||
|
|
||||||
|
_viewTileTypeTexture = new ImageTexture();
|
||||||
|
_viewTileTypeTexture.CreateFromImage(_tileTypeMapImage);
|
||||||
|
|
||||||
|
_tileInstanceManager.WorldTextureCoordinateOffset = chunkIndexSouthWest * worldChunkSize;
|
||||||
|
|
||||||
|
EmitSignal("OnWorldViewTileTypeImageChanged", _tileTypeMapImage);
|
||||||
|
EmitSignal("OnHeightmapImageChanged", _heightmapImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Process(float delta)
|
||||||
|
{
|
||||||
|
if (State == GenerationState.Heightmap)
|
||||||
|
{
|
||||||
|
// generate heightmap for all new chunks
|
||||||
|
foreach (var chunkIndex in _addedChunkIndices)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
State = GenerationState.Heightmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldState = State;
|
||||||
|
|
||||||
|
if (State == GenerationState.Heightmap)
|
||||||
|
{
|
||||||
|
var numChunksGeneratingHeightmap = 0;
|
||||||
|
foreach (var chunkIndex in _addedChunkIndices)
|
||||||
|
{
|
||||||
|
var chunk = _cachedWorldChunks[chunkIndex];
|
||||||
|
if (chunk.HeightMapFrameCount > 0) numChunksGeneratingHeightmap++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numChunksGeneratingHeightmap == 0)
|
||||||
|
{
|
||||||
|
// assign height map images
|
||||||
|
State = GenerationState.TileType;
|
||||||
|
|
||||||
|
foreach (var chunkIndex in _addedChunkIndices)
|
||||||
|
{
|
||||||
|
var chunk = _cachedWorldChunks[chunkIndex];
|
||||||
|
chunk.SetHeightmap(chunk.HeightmapOffscreenViewport.GetTexture());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (State == GenerationState.TileType)
|
||||||
|
{
|
||||||
|
// assign tile type images
|
||||||
|
// generate heightmap for all new chunks
|
||||||
|
foreach (var chunkIndex in _addedChunkIndices)
|
||||||
|
{
|
||||||
|
var chunk = _cachedWorldChunks[chunkIndex];
|
||||||
|
chunk.SetHeightmap(chunk.HeightmapOffscreenViewport.GetTexture());
|
||||||
|
}
|
||||||
|
|
||||||
|
State = GenerationState.Objects;
|
||||||
|
}
|
||||||
|
else if (State == GenerationState.Objects)
|
||||||
|
{
|
||||||
|
// generate objects
|
||||||
|
|
||||||
|
State = GenerationState.Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldState != GenerationState.Done && State == GenerationState.Done)
|
||||||
|
{
|
||||||
|
UpdateWorldViewTexture();
|
||||||
|
EmitSignal("OnTilesChanged", _removedChunkIndices.ToArray(), _addedChunkIndices.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Process(float delta)
|
// ui elements
|
||||||
{
|
|
||||||
GenerationState oldState = State;
|
|
||||||
|
|
||||||
if (State == GenerationState.Heightmap)
|
|
||||||
{
|
|
||||||
// generate heightmap for all new chunks
|
|
||||||
foreach (Vector2 chunkIndex in _addedChunkIndices)
|
|
||||||
{
|
|
||||||
WorldChunk chunk = _cachedWorldChunks[chunkIndex];
|
|
||||||
Color debugChunkColor = new Color(Mathf.Abs(chunkIndex.x) / 5, Mathf.Abs(chunkIndex.y) / 5, Mathf.RoundToInt(Mathf.Abs(chunkIndex.x + chunkIndex.y)) % 2);
|
|
||||||
|
|
||||||
GD.Print("Generating for offset " + chunkIndex + " chunk: " + chunk + " debugChunkColor: " + debugChunkColor);
|
|
||||||
|
|
||||||
ImageTexture noiseImageTexture = new ImageTexture();
|
|
||||||
noiseImageTexture.CreateFromImage(noiseGenerator.GetImage(ChunkSize, ChunkSize, chunkIndex * ChunkSize), (uint) 0);
|
|
||||||
|
|
||||||
// Debug Texture
|
|
||||||
Image simpleImage = new Image();
|
|
||||||
simpleImage.Create(ChunkSize, ChunkSize, false, Image.Format.Rgb8);
|
|
||||||
simpleImage.Lock();
|
|
||||||
|
|
||||||
foreach (int i in Enumerable.Range(0, ChunkSize))
|
// scene nodes
|
||||||
{
|
|
||||||
foreach (int j in Enumerable.Range(0, ChunkSize))
|
|
||||||
{
|
|
||||||
if ((i + j) % 2 == 0)
|
|
||||||
{
|
|
||||||
simpleImage.SetPixelv(new Vector2(i, j), Colors.Aqua);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
simpleImage.SetPixelv(new Vector2(i, j), debugChunkColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
simpleImage.Unlock();
|
// resources
|
||||||
// noiseImageTexture.CreateFromImage(simpleImage, 0);
|
|
||||||
chunk.SetHeightmap(noiseImageTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// assign height map images
|
|
||||||
|
|
||||||
State = GenerationState.TileType;
|
|
||||||
} else if (State == GenerationState.TileType)
|
|
||||||
{
|
|
||||||
// assign tile type images
|
|
||||||
|
|
||||||
State = GenerationState.Objects;
|
// exports
|
||||||
} else if (State == GenerationState.Objects)
|
// [Export] public Vector2 Size = new Vector2(1, 1);
|
||||||
{
|
|
||||||
// generate objects
|
|
||||||
|
|
||||||
State = GenerationState.Done;
|
// signals
|
||||||
}
|
[Signal]
|
||||||
|
private delegate void OnTilesChanged(Array<Vector2> removedChunkIndices, Array<Vector2> addedChunkIndices);
|
||||||
|
|
||||||
if (oldState != GenerationState.Done && State == GenerationState.Done)
|
[Signal]
|
||||||
{
|
private delegate void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage);
|
||||||
EmitSignal("OnTilesChanged", _removedChunkIndices.ToArray(), _addedChunkIndices.ToArray());
|
|
||||||
}
|
[Signal]
|
||||||
}
|
private delegate void OnHeightmapImageChanged(Image heightmapImage);
|
||||||
}
|
}
|
|
@ -1,56 +1,45 @@
|
||||||
using Godot;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
public class WorldChunk : Spatial
|
public class WorldChunk : Spatial
|
||||||
{
|
{
|
||||||
// ui elements
|
private Sprite _heightmapSprite;
|
||||||
|
private TextureRect _heightmapTextureRect;
|
||||||
|
private Sprite _noiseMask;
|
||||||
|
|
||||||
// scene nodes
|
private Sprite _noiseSprite;
|
||||||
private MeshInstance PlaneRectMesh;
|
|
||||||
|
|
||||||
// resources
|
private readonly SpatialMaterial _rectMaterial = new();
|
||||||
|
private bool _showTextureOverlay;
|
||||||
// exports
|
[Export] public Vector2 ChunkIndex;
|
||||||
[Export] public Texture TileTypeMap;
|
public Color DebugColor = Colors.White;
|
||||||
[Export] public Texture NavigationMap;
|
|
||||||
[Export] public Texture HeightMap;
|
[Export] public Texture HeightMap;
|
||||||
[Export] public int Size = 32;
|
public int HeightMapFrameCount;
|
||||||
[Export] public Vector2 ChunkAddress;
|
|
||||||
|
|
||||||
[Export]
|
public Viewport HeightmapOffscreenViewport;
|
||||||
public bool ShowTextureOverlay
|
[Export] public Texture NavigationMap;
|
||||||
{
|
|
||||||
get
|
public bool NoiseTextureCheckerboardOverlay = true;
|
||||||
{
|
|
||||||
return _showTextureOverlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (PlaneRectMesh != null)
|
|
||||||
{
|
|
||||||
PlaneRectMesh.Visible = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
// delegate void OnCoordClicked(Vector2 world_pos);
|
// delegate void OnCoordClicked(Vector2 world_pos);
|
||||||
|
|
||||||
// other members
|
// other members
|
||||||
public Rect2 PlaneRect;
|
public Rect2 PlaneRect;
|
||||||
public Color DebugColor = Colors.White;
|
// ui elements
|
||||||
public Viewport TileTypeOffscreenViewport;
|
|
||||||
public bool NoiseTextureCheckerboardOverlay = true;
|
// scene nodes
|
||||||
|
private MeshInstance PlaneRectMesh;
|
||||||
|
[Export] public int Size = 32;
|
||||||
|
|
||||||
|
// resources
|
||||||
|
|
||||||
|
// exports
|
||||||
|
[Export] public Texture TileTypeMap;
|
||||||
|
public int TileTypeMapFrameCount;
|
||||||
|
public Viewport TileTypeOffscreenViewport;
|
||||||
|
|
||||||
private TextureRect _heightmapRect;
|
|
||||||
private SpatialMaterial _rectMaterial = new SpatialMaterial();
|
|
||||||
private bool _showTextureOverlay = false;
|
|
||||||
|
|
||||||
public WorldChunk()
|
public WorldChunk()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -60,20 +49,70 @@ public class WorldChunk : Spatial
|
||||||
SetSize(size);
|
SetSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public bool ShowTextureOverlay
|
||||||
|
{
|
||||||
|
get => _showTextureOverlay;
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (PlaneRectMesh != null) PlaneRectMesh.Visible = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
PlaneRectMesh = (MeshInstance)FindNode("PlaneRectMesh");
|
||||||
|
Debug.Assert(PlaneRectMesh != null);
|
||||||
|
if (PlaneRectMesh.Visible) _showTextureOverlay = true;
|
||||||
|
|
||||||
|
var planeRectTransform = Transform.Identity;
|
||||||
|
planeRectTransform =
|
||||||
|
planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x, 0.125f, PlaneRect.Size.y));
|
||||||
|
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;
|
||||||
|
|
||||||
|
HeightmapOffscreenViewport = (Viewport)FindNode("HeightmapOffscreenViewport");
|
||||||
|
HeightmapOffscreenViewport.Size = Vector2.One * Size;
|
||||||
|
Debug.Assert(HeightmapOffscreenViewport != null);
|
||||||
|
_noiseSprite = (Sprite)FindNode("NoiseSprite");
|
||||||
|
_noiseMask = (Sprite)FindNode("NoiseMask");
|
||||||
|
_heightmapSprite = (Sprite)FindNode("HeightmapSprite");
|
||||||
|
|
||||||
|
TileTypeOffscreenViewport = (Viewport)FindNode("TileTypeOffscreenViewport");
|
||||||
|
TileTypeOffscreenViewport.Size = Vector2.One * Size;
|
||||||
|
Debug.Assert(TileTypeOffscreenViewport != null);
|
||||||
|
|
||||||
|
SetSize(World.ChunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetSize(int size)
|
public void SetSize(int size)
|
||||||
{
|
{
|
||||||
Size = size;
|
Size = size;
|
||||||
|
|
||||||
if (TileTypeOffscreenViewport != null)
|
if (TileTypeOffscreenViewport != null)
|
||||||
{
|
{
|
||||||
TileTypeOffscreenViewport.Size = Vector2.One * size;
|
TileTypeOffscreenViewport.Size = Vector2.One * size;
|
||||||
|
HeightmapOffscreenViewport.Size = Vector2.One * size;
|
||||||
|
_noiseMask.Transform = Transform2D.Identity.Scaled(Vector2.One * size / _noiseMask.Texture.GetSize().x);
|
||||||
|
_noiseSprite.Transform = Transform2D.Identity.Scaled(Vector2.One * size / _noiseSprite.Texture.GetSize().x);
|
||||||
|
_heightmapSprite.Transform =
|
||||||
|
Transform2D.Identity.Scaled(Vector2.One * size / _heightmapSprite.Texture.GetSize().x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// other members
|
// other members
|
||||||
public void SaveToFile(String chunkName)
|
public void SaveToFile(string chunkName)
|
||||||
{
|
{
|
||||||
Image image = new Image();
|
var image = new Image();
|
||||||
|
|
||||||
image.CreateFromData(Size, Size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData());
|
image.CreateFromData(Size, Size, false, Image.Format.Rgba8, TileTypeMap.GetData().GetData());
|
||||||
image.SavePng(chunkName + "_tileType.png");
|
image.SavePng(chunkName + "_tileType.png");
|
||||||
|
@ -85,91 +124,75 @@ public class WorldChunk : Spatial
|
||||||
image.SavePng(chunkName + "_heightMap.png");
|
image.SavePng(chunkName + "_heightMap.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadFromFile(String chunkName)
|
public void LoadFromFile(string chunkName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the node enters the scene tree for the first time.
|
|
||||||
public override void _Ready()
|
public void SetNoisemap(Texture texture)
|
||||||
{
|
{
|
||||||
PlaneRectMesh = (MeshInstance)FindNode("PlaneRectMesh");
|
_noiseSprite.Texture = texture;
|
||||||
Debug.Assert(PlaneRectMesh != null);
|
_noiseSprite.Transform =
|
||||||
if (PlaneRectMesh.Visible)
|
Transform2D.Identity.Scaled(HeightmapOffscreenViewport.Size / _noiseSprite.Texture.GetSize().x);
|
||||||
{
|
HeightmapOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once;
|
||||||
_showTextureOverlay = true;
|
HeightMapFrameCount = 1;
|
||||||
}
|
|
||||||
|
|
||||||
Transform planeRectTransform = Transform.Identity;
|
|
||||||
planeRectTransform =
|
|
||||||
planeRectTransform.Scaled(new Vector3(PlaneRect.Size.x, 0.125f, PlaneRect.Size.y));
|
|
||||||
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;
|
|
||||||
|
|
||||||
TileTypeOffscreenViewport = (Viewport)FindNode("TileTypeOffscreenViewport");
|
|
||||||
TileTypeOffscreenViewport.Size = Vector2.One * Size;
|
|
||||||
Debug.Assert(TileTypeOffscreenViewport != null);
|
|
||||||
|
|
||||||
_heightmapRect = (TextureRect)FindNode("HeightmapTexture");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetHeightmap(Texture texture)
|
public void SetHeightmap(Texture texture)
|
||||||
{
|
{
|
||||||
GD.Print("Setting HeightmapRect Texture: " + _heightmapRect + " with size " + _heightmapRect.GetSize());
|
_heightmapSprite.Texture = texture;
|
||||||
_heightmapRect.Texture = texture;
|
_heightmapSprite.Transform =
|
||||||
|
Transform2D.Identity.Scaled(TileTypeOffscreenViewport.Size / _heightmapSprite.Texture.GetSize());
|
||||||
|
|
||||||
|
TileTypeOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once;
|
||||||
|
TileTypeMapFrameCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
||||||
public override void _Process(float delta)
|
public override void _Process(float delta)
|
||||||
{
|
{
|
||||||
Texture tileTypeTexture = TileTypeOffscreenViewport.GetTexture();
|
Texture tileTypeTexture = TileTypeOffscreenViewport.GetTexture();
|
||||||
|
|
||||||
if (NoiseTextureCheckerboardOverlay)
|
if (NoiseTextureCheckerboardOverlay)
|
||||||
{
|
{
|
||||||
Image tileTypeImage = tileTypeTexture.GetData();
|
var tileTypeImage = tileTypeTexture.GetData();
|
||||||
tileTypeImage.Lock();
|
tileTypeImage.Lock();
|
||||||
|
|
||||||
foreach (int i in Enumerable.Range(0, Size))
|
foreach (var i in Enumerable.Range(0, Size))
|
||||||
|
foreach (var j in Enumerable.Range(0, Size))
|
||||||
{
|
{
|
||||||
foreach (int j in Enumerable.Range(0, Size))
|
var textureCoord = new Vector2(i, j);
|
||||||
{
|
var baseColor = tileTypeImage.GetPixelv(textureCoord);
|
||||||
Vector2 textureCoord = new Vector2(i, j);
|
|
||||||
Color baseColor = tileTypeImage.GetPixelv(textureCoord);
|
if ((i + j) % 2 == 0)
|
||||||
|
tileTypeImage.SetPixelv(textureCoord, baseColor);
|
||||||
if ((i + j) % 2 == 0)
|
else
|
||||||
{
|
tileTypeImage.SetPixelv(textureCoord, baseColor * 0.6f);
|
||||||
tileTypeImage.SetPixelv(textureCoord, baseColor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tileTypeImage.SetPixelv(textureCoord, baseColor * 0.6f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tileTypeImage.Unlock();
|
tileTypeImage.Unlock();
|
||||||
ImageTexture imageTexture = new ImageTexture();
|
var imageTexture = new ImageTexture();
|
||||||
imageTexture.CreateFromImage(tileTypeImage, (uint) 0);
|
imageTexture.CreateFromImage(tileTypeImage, 0);
|
||||||
tileTypeTexture = imageTexture;
|
tileTypeTexture = imageTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rectMaterial.AlbedoTexture = tileTypeTexture;
|
_rectMaterial.AlbedoTexture = tileTypeTexture;
|
||||||
|
|
||||||
_rectMaterial.FlagsTransparent = true;
|
_rectMaterial.FlagsTransparent = true;
|
||||||
// _rectMaterial.AlbedoTexture = _heightmapRect.Texture;
|
// _rectMaterial.AlbedoTexture = _heightmapRect.Texture;
|
||||||
_rectMaterial.Uv1Scale = new Vector3(-3, -2, 1);
|
_rectMaterial.Uv1Scale = new Vector3(-3, -2, 1);
|
||||||
_rectMaterial.Uv1Offset = Vector3.One * 2;
|
_rectMaterial.Uv1Offset = Vector3.One * 2;
|
||||||
|
|
||||||
//RectMaterial.Uv1Triplanar = true;
|
//RectMaterial.Uv1Triplanar = true;
|
||||||
PlaneRectMesh.SetSurfaceMaterial(0, _rectMaterial);
|
PlaneRectMesh.SetSurfaceMaterial(0, _rectMaterial);
|
||||||
|
|
||||||
TileTypeOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once;
|
if (HeightMapFrameCount == 0) HeightmapOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Disabled;
|
||||||
|
|
||||||
|
HeightMapFrameCount = HeightMapFrameCount > 0 ? HeightMapFrameCount - 1 : 0;
|
||||||
|
|
||||||
|
if (TileTypeMapFrameCount == 0) TileTypeOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Disabled;
|
||||||
|
|
||||||
|
TileTypeMapFrameCount = TileTypeMapFrameCount > 0 ? TileTypeMapFrameCount - 1 : 0;
|
||||||
|
|
||||||
PlaneRectMesh.MaterialOverride = null;
|
PlaneRectMesh.MaterialOverride = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
[gd_scene load_steps=9 format=2]
|
[gd_scene load_steps=10 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://scenes/WorldChunk.cs" type="Script" id=1]
|
[ext_resource path="res://scenes/WorldChunk.cs" type="Script" id=1]
|
||||||
[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=2]
|
[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=2]
|
||||||
[ext_resource path="res://assets/TestHeightmap.tres" type="Texture" id=3]
|
[ext_resource path="res://assets/TestHeightmap.tres" type="Texture" id=3]
|
||||||
[ext_resource path="res://assets/4x4checkerColor.png" type="Texture" id=4]
|
[ext_resource path="res://assets/4x4checkerColor.png" type="Texture" id=4]
|
||||||
|
[ext_resource path="res://addons/gdhexgrid/icon.png" type="Texture" id=6]
|
||||||
|
|
||||||
[sub_resource type="CubeMesh" id=27]
|
[sub_resource type="CubeMesh" id=27]
|
||||||
size = Vector3( 1, 1, 1 )
|
size = Vector3( 1, 1, 1 )
|
||||||
|
@ -15,15 +16,10 @@ albedo_texture = ExtResource( 4 )
|
||||||
uv1_scale = Vector3( -3, -2, 0 )
|
uv1_scale = Vector3( -3, -2, 0 )
|
||||||
uv1_offset = Vector3( 2, 2, 0 )
|
uv1_offset = Vector3( 2, 2, 0 )
|
||||||
|
|
||||||
[sub_resource type="OpenSimplexNoise" id=29]
|
[sub_resource type="CanvasItemMaterial" id=29]
|
||||||
octaves = 1
|
blend_mode = 3
|
||||||
period = 9.0
|
|
||||||
persistence = 0.0
|
|
||||||
|
|
||||||
[sub_resource type="NoiseTexture" id=30]
|
[sub_resource type="ImageTexture" id=30]
|
||||||
width = 8
|
|
||||||
height = 8
|
|
||||||
noise = SubResource( 29 )
|
|
||||||
|
|
||||||
[node name="WorldChunk" type="Spatial"]
|
[node name="WorldChunk" type="Spatial"]
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
|
@ -36,8 +32,8 @@ visible = false
|
||||||
mesh = SubResource( 27 )
|
mesh = SubResource( 27 )
|
||||||
material/0 = SubResource( 28 )
|
material/0 = SubResource( 28 )
|
||||||
|
|
||||||
[node name="TileTypeOffscreenViewport" type="Viewport" parent="."]
|
[node name="HeightmapOffscreenViewport" type="Viewport" parent="."]
|
||||||
size = Vector2( 8, 8 )
|
size = Vector2( 50, 50 )
|
||||||
handle_input_locally = false
|
handle_input_locally = false
|
||||||
hdr = false
|
hdr = false
|
||||||
disable_3d = true
|
disable_3d = true
|
||||||
|
@ -49,19 +45,29 @@ shadow_atlas_quad_1 = 0
|
||||||
shadow_atlas_quad_2 = 0
|
shadow_atlas_quad_2 = 0
|
||||||
shadow_atlas_quad_3 = 0
|
shadow_atlas_quad_3 = 0
|
||||||
|
|
||||||
[node name="NoiseTexture" type="TextureRect" parent="TileTypeOffscreenViewport"]
|
[node name="NoiseSprite" type="Sprite" parent="HeightmapOffscreenViewport"]
|
||||||
visible = false
|
texture = ExtResource( 6 )
|
||||||
margin_right = 40.0
|
centered = false
|
||||||
margin_bottom = 40.0
|
|
||||||
|
[node name="NoiseMask" type="Sprite" parent="HeightmapOffscreenViewport"]
|
||||||
|
material = SubResource( 29 )
|
||||||
texture = SubResource( 30 )
|
texture = SubResource( 30 )
|
||||||
|
centered = false
|
||||||
|
|
||||||
[node name="IslandShader" type="TextureRect" parent="TileTypeOffscreenViewport"]
|
[node name="TileTypeOffscreenViewport" type="Viewport" parent="."]
|
||||||
|
size = Vector2( 100, 100 )
|
||||||
|
handle_input_locally = false
|
||||||
|
hdr = false
|
||||||
|
disable_3d = true
|
||||||
|
usage = 0
|
||||||
|
render_target_v_flip = true
|
||||||
|
render_target_update_mode = 3
|
||||||
|
shadow_atlas_quad_0 = 0
|
||||||
|
shadow_atlas_quad_1 = 0
|
||||||
|
shadow_atlas_quad_2 = 0
|
||||||
|
shadow_atlas_quad_3 = 0
|
||||||
|
|
||||||
|
[node name="HeightmapSprite" type="Sprite" parent="TileTypeOffscreenViewport"]
|
||||||
material = ExtResource( 2 )
|
material = ExtResource( 2 )
|
||||||
margin_right = 100.0
|
|
||||||
margin_bottom = 100.0
|
|
||||||
|
|
||||||
[node name="HeightmapTexture" type="TextureRect" parent="TileTypeOffscreenViewport/IslandShader"]
|
|
||||||
use_parent_material = true
|
|
||||||
margin_right = 100.0
|
|
||||||
margin_bottom = 100.0
|
|
||||||
texture = ExtResource( 3 )
|
texture = ExtResource( 3 )
|
||||||
|
centered = false
|
||||||
|
|
Loading…
Reference in New Issue