2022-12-28 16:22:53 +01:00
|
|
|
using Godot;
|
|
|
|
using System;
|
|
|
|
using System.Linq;
|
2023-05-05 16:26:33 +02:00
|
|
|
using System.Numerics;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using GoDotLog;
|
|
|
|
using Vector2 = Godot.Vector2;
|
|
|
|
using Vector3 = Godot.Vector3;
|
2022-12-28 16:22:53 +01:00
|
|
|
|
|
|
|
public class TileWorld : Spatial
|
|
|
|
{
|
|
|
|
// signals
|
|
|
|
[Signal]
|
|
|
|
delegate void WorldGenerated();
|
|
|
|
|
|
|
|
// public members
|
2023-05-09 21:51:45 +02:00
|
|
|
public Vector2 Size = new Vector2(100, 100);
|
2023-05-11 22:26:06 +02:00
|
|
|
public float HeightScale = 2;
|
2023-05-05 16:26:33 +02:00
|
|
|
public Image Heightmap;
|
|
|
|
public Image Colormap;
|
|
|
|
public int Seed = 0;
|
2022-12-28 16:22:53 +01:00
|
|
|
|
|
|
|
// private members
|
|
|
|
private HexGrid _hexGrid;
|
|
|
|
private Random _tileTypeRandom;
|
2023-05-05 16:26:33 +02:00
|
|
|
private Viewport _offscreenViewport;
|
|
|
|
private TextureRect _offscreenTextureRect;
|
2022-12-28 16:22:53 +01:00
|
|
|
|
|
|
|
// Called when the node enters the scene tree for the first time.
|
|
|
|
public override void _Ready()
|
|
|
|
{
|
|
|
|
_hexGrid = new HexGrid();
|
|
|
|
_tileTypeRandom = new Random();
|
2023-05-05 16:26:33 +02:00
|
|
|
|
|
|
|
_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));
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Generate()
|
|
|
|
{
|
2023-01-04 22:49:00 +01:00
|
|
|
GenerateSimpleMap();
|
2023-05-05 16:26:33 +02:00
|
|
|
// GenerateNoiseMap();
|
2022-12-28 16:22:53 +01:00
|
|
|
|
2023-05-05 16:26:33 +02:00
|
|
|
GenerateNoiseColorMap();
|
|
|
|
|
2022-12-28 16:22:53 +01:00
|
|
|
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))
|
2022-12-28 16:22:53 +01:00
|
|
|
{
|
2023-04-30 15:33:46 +02:00
|
|
|
foreach (int coord_y in Enumerable.Range(-(int) Size.y / 2, (int)Size.y))
|
2022-12-28 16:22:53 +01:00
|
|
|
{
|
2023-01-04 22:49:00 +01:00
|
|
|
SetHeightAtOffset(new Vector2(coord_x, coord_y), 5f);
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
2023-05-05 16:26:33 +02:00
|
|
|
noise_generator.Seed = Seed;
|
|
|
|
noise_generator.Octaves = 4;
|
2023-01-03 17:46:55 +01:00
|
|
|
noise_generator.Period = 20;
|
|
|
|
noise_generator.Persistence = 0.1f;
|
2022-12-28 16:22:53 +01:00
|
|
|
noise_generator.Lacunarity = 2;
|
|
|
|
|
|
|
|
Heightmap.CopyFrom(noise_generator.GetImage((int)Size.x, (int)Size.y, null));
|
|
|
|
}
|
2023-05-05 16:26:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
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;
|
2023-05-11 22:26:06 +02:00
|
|
|
|
2023-05-05 16:26:33 +02:00
|
|
|
ImageTexture imageTexture = new ImageTexture();
|
2023-05-11 22:26:06 +02:00
|
|
|
Heightmap.Unlock();
|
|
|
|
Heightmap = noise_generator.GetSeamlessImage((int)Size.x);
|
|
|
|
imageTexture.CreateFromImage(Heightmap);
|
2023-05-05 16:26:33 +02:00
|
|
|
imageTexture.Flags = 0;
|
|
|
|
_offscreenTextureRect.Texture = imageTexture;
|
|
|
|
Colormap.CopyFrom(_offscreenViewport.GetTexture().GetData());
|
2023-05-11 22:26:06 +02:00
|
|
|
Heightmap.Lock();
|
2023-05-05 16:26:33 +02:00
|
|
|
}
|
2022-12-28 16:22:53 +01:00
|
|
|
|
|
|
|
|
|
|
|
private void ApplyHeightMap()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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));
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public float GetHeightAtOffset(Vector2 offset_coord)
|
|
|
|
{
|
|
|
|
if (!IsOffsetCoordValid(offset_coord))
|
|
|
|
{
|
2022-12-28 21:57:34 +01:00
|
|
|
return 0;
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|
|
|
|
|
2023-04-30 15:33:46 +02:00
|
|
|
Vector2 texture_coord = offset_coord + Size / 2;
|
|
|
|
|
2023-05-11 22:26:06 +02:00
|
|
|
return Heightmap.GetPixel((int)texture_coord.x, (int)(texture_coord.y)).r * HeightScale - HeightScale * 0.5f ;
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Vector2 WorldToOffsetCoords(Vector3 world_coord)
|
|
|
|
{
|
|
|
|
return _hexGrid.GetHexAt(new Vector2(world_coord.x, world_coord.z)).OffsetCoords;
|
|
|
|
}
|
|
|
|
|
2023-01-03 17:46:55 +01:00
|
|
|
|
|
|
|
public Vector3 GetTileWorldCenterFromOffset(Vector2 offset_coord)
|
|
|
|
{
|
|
|
|
Vector2 tileCenter = _hexGrid.GetHexCenterFromOffset(offset_coord);
|
|
|
|
|
|
|
|
return new Vector3(
|
|
|
|
tileCenter.x,
|
|
|
|
GetHeightAtOffset(offset_coord),
|
|
|
|
tileCenter.y);
|
|
|
|
}
|
2022-12-28 16:22:53 +01:00
|
|
|
}
|