GodotComponentTest/scenes/TileWorld.cs

174 lines
5.0 KiB
C#
Raw Normal View History

using Godot;
using System;
using System.Linq;
using System.Numerics;
using System.Diagnostics;
using GoDotLog;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
public class TileWorld : Spatial
{
// signals
[Signal]
delegate void WorldGenerated();
// public members
public Vector2 Size = new Vector2(10, 10);
public float HeightScale = 2;
public Image Heightmap;
public Image Colormap;
public int Seed = 0;
// private members
private HexGrid _hexGrid;
private Random _tileTypeRandom;
private Viewport _offscreenViewport;
private TextureRect _offscreenTextureRect;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_hexGrid = new HexGrid();
_tileTypeRandom = new Random();
_offscreenViewport = (Viewport)GetNode("OffscreenViewport");
Debug.Assert(_offscreenViewport != null);
_offscreenViewport.Size = Size;
_offscreenTextureRect = (TextureRect)GetNode("OffscreenViewport/TextureRect");
Debug.Assert(_offscreenTextureRect != null);
_offscreenTextureRect.SetSize(Size);
//VisualServer.Singleton.Connect("frame_post_draw", this, nameof(GenerateNoiseColorMap));
}
public void Generate()
{
//GenerateSimpleMap();
// GenerateNoiseMap();
GenerateNoiseColorMap();
EmitSignal("WorldGenerated");
}
private void GenerateSimpleMap()
{
Heightmap = new Image();
Heightmap.Create((int)Size.x, (int)Size.y, false, Image.Format.Rf);
Heightmap.Lock();
2023-04-30 15:33:46 +02:00
foreach (int coord_x in Enumerable.Range(-(int) Size.x / 2, (int)Size.x))
{
2023-04-30 15:33:46 +02:00
foreach (int coord_y in Enumerable.Range(-(int) Size.y / 2, (int)Size.y))
{
2023-01-04 22:49:00 +01:00
SetHeightAtOffset(new Vector2(coord_x, coord_y), 5f);
}
}
}
private void GenerateNoiseMap()
{
Heightmap = new Image();
Heightmap.Create((int)Size.x, (int)Size.y, false, Image.Format.Rf);
NoiseTexture noise_texture = new NoiseTexture();
OpenSimplexNoise noise_generator = new OpenSimplexNoise();
noise_generator.Seed = Seed;
noise_generator.Octaves = 4;
noise_generator.Period = 20;
noise_generator.Persistence = 0.1f;
noise_generator.Lacunarity = 2;
Heightmap.CopyFrom(noise_generator.GetImage((int)Size.x, (int)Size.y, null));
}
private void GenerateNoiseColorMap()
{
Colormap = new Image();
Colormap.Create((int)Size.x, (int)Size.y, false, Image.Format.Rgba8);
NoiseTexture noise_texture = new NoiseTexture();
OpenSimplexNoise noise_generator = new OpenSimplexNoise();
noise_generator.Seed = Seed;
noise_generator.Octaves = 4;
noise_generator.Period = 20;
noise_generator.Persistence = 0.2f;
noise_generator.Lacunarity = 4;
ImageTexture imageTexture = new ImageTexture();
//Heightmap.Unlock();
Heightmap = noise_generator.GetSeamlessImage((int)Size.x);
imageTexture.CreateFromImage(Heightmap);
imageTexture.Flags = 0;
_offscreenTextureRect.Texture = imageTexture;
Colormap.CopyFrom(_offscreenViewport.GetTexture().GetData());
Heightmap.Lock();
}
public bool IsOffsetCoordValid(Vector2 offset_coord)
{
2023-04-30 15:33:46 +02:00
return ((int)Math.Clamp(offset_coord.x, -Size.x / 2, Size.x / 2 - 1) == (int)offset_coord.x
&& (int)Math.Clamp(offset_coord.y, -Size.y / 2, Size.y / 2 - 1) == (int)offset_coord.y);
}
public HexTile3D.TileType GetTileTypeAtOffset(Vector2 offset_coord)
{
if (!IsOffsetCoordValid(offset_coord))
{
return HexTile3D.TileType.Undefined;
}
return HexTile3D.ValidTileTypes[_tileTypeRandom.Next(HexTile3D.ValidTileTypes.Length)];
}
public void SetHeightAtOffset(Vector2 offset_coord, float height)
{
if (!IsOffsetCoordValid(offset_coord))
{
return;
}
2023-04-30 15:33:46 +02:00
Vector2 texture_coord = offset_coord + Size / 2;
Heightmap.SetPixel((int) texture_coord.x, (int) texture_coord.y, new Color(height / HeightScale, 0f, 0f));
}
public float GetHeightAtOffset(Vector2 offset_coord)
{
if (!IsOffsetCoordValid(offset_coord))
{
return 0;
}
2023-04-30 15:33:46 +02:00
Vector2 texture_coord = offset_coord + Size / 2;
return Heightmap.GetPixel((int)texture_coord.x, (int)(texture_coord.y)).r * HeightScale - HeightScale * 0.5f ;
}
public Vector2 WorldToOffsetCoords(Vector3 world_coord)
{
return _hexGrid.GetHexAt(new Vector2(world_coord.x, world_coord.z)).OffsetCoords;
}
public Vector3 GetTileWorldCenterFromOffset(Vector2 offset_coord)
{
Vector2 tileCenter = _hexGrid.GetHexCenterFromOffset(offset_coord);
return new Vector3(
tileCenter.x,
GetHeightAtOffset(offset_coord),
tileCenter.y);
}
}