Started migration to C#

WorldChunkRefactoring
Martin Felis 2022-12-02 21:09:40 +01:00
parent dd7fa53c33
commit af9e71e698
14 changed files with 703 additions and 89 deletions

4
.gitignore vendored
View File

@ -1,5 +1,9 @@
.import/*
.mono/*
.idea/*
*.swp
*.apk
*.idsig
mono_crash.*

14
GodotComponentTest.csproj Normal file
View File

@ -0,0 +1,14 @@
<Project Sdk="Godot.NET.Sdk/3.3.0">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>10.0</LangVersion>
<!-- Required for some nuget packages to work -->
<!-- See https://www.reddit.com/r/godot/comments/l0naqg/comment/gjwfspm/ -->
<!-- And https://github.com/godotengine/godot/issues/42271#issuecomment-751423827 -->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.GoDotTest" Version="1.0.0" />
</ItemGroup>
</Project>

19
GodotComponentTest.sln Normal file
View File

@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotComponentTest", "GodotComponentTest.csproj", "{4DD477E5-5F2E-4AB0-A863-E006389DD60E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
ExportDebug|Any CPU = ExportDebug|Any CPU
ExportRelease|Any CPU = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4DD477E5-5F2E-4AB0-A863-E006389DD60E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4DD477E5-5F2E-4AB0-A863-E006389DD60E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
{4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
{4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
{4DD477E5-5F2E-4AB0-A863-E006389DD60E}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
EndGlobalSection
EndGlobal

131
HexCell.cs Normal file
View File

@ -0,0 +1,131 @@
using System;
using System.Diagnostics;
using Godot;
using Array = Godot.Collections.Array;
public class HexCell : Resource
{
public static readonly Vector2 size = new Vector2(1, Mathf.Sqrt(3) / 2);
public static readonly Vector3 DIR_N = new Vector3(0, 1, -1);
public static readonly Vector3 DIR_NE = new Vector3(1, 0, -1);
public static readonly Vector3 DIR_SE = new Vector3(1, -1, 0);
public static readonly Vector3 DIR_S = new Vector3(0, -1, 1);
public static readonly Vector3 DIR_SW = new Vector3(-1, 0, 1);
public static readonly Vector3 DIR_NW = new Vector3(-1, 1, 0);
public static readonly Array DIR_ALL = new Array()
{ DIR_N, DIR_NE, DIR_SE, DIR_S, DIR_SW, DIR_NW };
public HexCell() { }
public HexCell(float cubeX, float cubeY, float cubeZ)
{
CubeCoords = RoundCoords(new Vector3(cubeX, cubeY, cubeZ));
}
public HexCell(Vector3 cubeCoords)
{
CubeCoords = cubeCoords;
}
public HexCell(float axialX, float axialY)
{
AxialCoords = new Vector2(axialX, axialY);
}
public HexCell(Vector2 axialCoords)
{
AxialCoords = axialCoords;
}
public HexCell(HexCell other)
{
CubeCoords = other.CubeCoords;
}
private Vector3 _cubeCoords;
public Vector3 CubeCoords
{
get
{
return _cubeCoords;
}
set
{
if (Mathf.Abs(value.x + value.y + value.z) > 0.0001)
{
GD.Print("Warning: Invalid cube coordinates for hex (x + y + z != 0): ", value.ToString());
}
_cubeCoords = RoundCoords(value);
}
}
public Vector2 AxialCoords
{
get => new Vector2(CubeCoords.x, CubeCoords.y);
set
{
CubeCoords = AxialToCubeCoords(value);
}
}
public Vector2 OffsetCoords
{
get
{
int x = (int)CubeCoords.x;
int y = (int)CubeCoords.y;
int off_y = y + (x - (x & 1)) / 2;
return new Vector2(x, off_y);
}
set
{
int x = (int)value.x;
int y = (int)value.y;
int cube_y = y - (x - (x & 1)) / 2;
AxialCoords = new Vector2(x, cube_y);
}
}
public Vector3 AxialToCubeCoords(Vector2 axialCoords)
{
return new Vector3(axialCoords.x, axialCoords.y, -axialCoords.x - axialCoords.y);
}
public Vector3 RoundCoords(Vector2 coords)
{
Vector3 cubeCoords = AxialToCubeCoords(coords);
return RoundCoords(cubeCoords);
}
public Vector3 RoundCoords(Vector3 cubeCoords)
{
Vector3 rounded = new Vector3(
Mathf.Round(cubeCoords.x),
Mathf.Round(cubeCoords.y),
Mathf.Round(cubeCoords.z));
Vector3 diffs = (rounded - cubeCoords).Abs();
if (diffs.x > diffs.y && diffs.x > diffs.z)
{
rounded.x = -rounded.y - rounded.z;
}
else if (diffs.y > diffs.z)
{
rounded.y = -rounded.x - rounded.z;
}
else
{
rounded.z = -rounded.x - rounded.y;
}
return rounded;
}
public HexCell getAdjacent(Vector3 dir)
{
return new HexCell(this.CubeCoords + dir);
}
}

66
HexGrid.cs Normal file
View File

@ -0,0 +1,66 @@
using System;
using Godot;
public class HexGrid : Resource
{
private Vector2 _baseHexSize = new Vector2(1, Mathf.Sqrt(3) / 2);
private Vector2 _hexSize = new Vector2(1, Mathf.Sqrt(3) / 2);
private Vector2 _hexScale = new Vector2(1, 1);
private Godot.Transform2D _hexTransform;
private Godot.Transform2D _hexTransformInv;
public Vector2 HexSize
{
get { return _hexSize; }
}
public Vector2 HexScale
{
get
{
return _hexScale;
}
set
{
_hexScale = value;
_hexSize = _baseHexSize * _hexScale;
_hexTransform = new Transform2D(
new Vector2(_hexSize.x * 3/4, -_hexSize.y / 2),
new Vector2(0, -_hexSize.y),
new Vector2(0, 0)
);
_hexTransformInv = _hexTransform.AffineInverse();
}
}
public HexGrid()
{
HexScale = new Vector2(1, 1);
}
public Vector2 GetHexCenter(HexCell cell)
{
return _hexTransform * cell.AxialCoords;
}
public Vector2 GetHexCenterFromOffset(Vector2 offsetCoord)
{
HexCell cell = new HexCell();
cell.OffsetCoords = offsetCoord;
return GetHexCenter(cell);
}
public HexCell GetHexAtOffset(Vector2 offsetCoord)
{
HexCell cell = new HexCell();
cell.OffsetCoords = offsetCoord;
return cell;
}
public HexCell GetHexAt(Vector2 planeCoord)
{
HexCell result = new HexCell(_hexTransformInv * planeCoord);
return result;
}
}

21
entities/Player.cs Normal file
View File

@ -0,0 +1,21 @@
using Godot;
using System;
public class Player : KinematicBody
{
// Declare member variables here. Examples:
// private int a = 2;
// private string b = "text";
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
}
// // Called every frame. 'delta' is the elapsed time since the previous frame.
// public override void _Process(float delta)
// {
//
// }
}

View File

@ -0,0 +1,117 @@
using Godot;
using System;
using System.Linq;
using Dictionary = Godot.Collections.Dictionary;
using Array = Godot.Collections.Array;
public class AdaptiveWorldStream : Spatial
{
// ui elements
private Label _tileLabel;
private Label _tileOffsetLabel;
private Label _numTilesLabel;
private Label _mouseWorldLabel;
private Label _mouseTileLabel;
// scene nodes
private Spatial _tileHighlight;
private Spatial _mouseTileHighlight;
private Area _streamContainerArea;
private Player _player;
// Resources
private PackedScene _tileHighlightScene;
// other members
private HexGrid _hexGrid;
private HexCell _lastTile;
private HexCell _currentTile;
private Vector2 _currentTileOffset;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
// UI elements
_tileLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/tile_label");
_tileOffsetLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/tile_offset_label");
_numTilesLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/num_tiles_label");
_mouseWorldLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/mouse_world_label");
_mouseTileLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/mouse_tile_label");
// scene nodes
_tileHighlight = GetNode<Spatial>("TileHighlight");
_mouseTileHighlight = GetNode<Spatial>("MouseTileHighlight");
_streamContainerArea = GetNode<Area>("StreamContainer/Area");
_player = GetNode<Player>("Player");
// resources
_tileHighlightScene = GD.Load<PackedScene>("utils/TileHighlight.tscn");
// other members
_lastTile = new HexCell();
_currentTile = new HexCell();
_currentTileOffset = new Vector2();
_hexGrid = new HexGrid();
// connect signals
var result = _streamContainerArea.Connect("input_event", this, nameof(OnAreaInputEvent));
CreateTileGrid();
}
public void CreateTileGrid()
{
foreach (int x_index in Enumerable.Range(-3, 6))
{
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());
}
}
}
public override void _Process(float delta)
{
_lastTile = _currentTile;
Transform playerTransform = _player.Transform;
Vector3 playerCoord = playerTransform.origin;
_currentTile = _hexGrid.GetHexAt(new Vector2(playerCoord.x, playerCoord.z));
_tileLabel.Text = delta.ToString();
_tileOffsetLabel.Text = _currentTile.OffsetCoords.ToString();
playerTransform.origin += new Vector3(0, 0, -1) * delta;
_player.Transform = playerTransform;
Transform tileHighlightTransform = Transform.Identity;
Vector2 currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
tileHighlightTransform.origin.x = currentTileCenter.x;
tileHighlightTransform.origin.z = currentTileCenter.y;
_tileHighlight.Transform = tileHighlightTransform;
}
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal, int shapeIndex)
{
HexCell cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
Transform highlightTransform = Transform.Identity;
Vector2 cellPlaneCoords = _hexGrid.GetHexCenter(cellAtCursor);
cellPlaneCoords = _hexGrid.GetHexCenterFromOffset(cellAtCursor.OffsetCoords);
highlightTransform.origin.x = cellPlaneCoords.x;
highlightTransform.origin.z = cellPlaneCoords.y;
_mouseWorldLabel.Text = position.ToString();
_mouseTileLabel.Text = cellAtCursor.OffsetCoords.ToString();
_mouseTileHighlight.Transform = highlightTransform;
}
}

View File

@ -1,31 +1,12 @@
[gd_scene load_steps=11 format=2]
[gd_scene load_steps=13 format=2]
[ext_resource path="res://scenes/AdaptiveWorldStream.gd" type="Script" id=1]
[ext_resource path="res://scenes/AdaptiveWorldStream.cs" type="Script" id=1]
[ext_resource path="res://entities/Player3D.tscn" type="PackedScene" id=2]
[ext_resource path="res://scenes/World.gd" type="Script" id=3]
[ext_resource path="res://scenes/StreamContainer.gd" type="Script" id=4]
[sub_resource type="CylinderMesh" id=3]
top_radius = 0.5
bottom_radius = 0.5
height = 0.1
radial_segments = 6
rings = 1
[sub_resource type="SpatialMaterial" id=4]
render_priority = 1
flags_transparent = true
albedo_color = Color( 1, 1, 1, 0.407843 )
roughness = 0.0
[sub_resource type="OpenSimplexNoise" id=5]
period = 15.0
[sub_resource type="NoiseTexture" id=6]
flags = 3
width = 100
height = 100
noise = SubResource( 5 )
[ext_resource path="res://scenes/StreamContainer.cs" type="Script" id=4]
[ext_resource path="res://entities/Player.cs" type="Script" id=5]
[ext_resource path="res://scenes/DebugCamera.gd" type="Script" id=6]
[ext_resource path="res://utils/TileHighlight.tscn" type="PackedScene" id=7]
[sub_resource type="CubeMesh" id=1]
@ -33,16 +14,39 @@ noise = SubResource( 5 )
params_blend_mode = 3
albedo_color = Color( 1, 1, 1, 0.156863 )
[sub_resource type="BoxShape" id=9]
extents = Vector3( 10, 1, 10 )
[sub_resource type="CapsuleShape" id=7]
radius = 0.2
height = 0.5
[sub_resource type="CapsuleMesh" id=8]
radius = 0.2
mid_height = 0.5
radial_segments = 16
[node name="AdaptiveWorldStream" type="Spatial"]
script = ExtResource( 1 )
[node name="TileHighlight" type="MeshInstance" parent="."]
transform = Transform( -1.62921e-07, 0, 1, 0, 1, 0, -1, 0, -1.62921e-07, 0, 0.2, 0 )
cast_shadow = 0
mesh = SubResource( 3 )
material/0 = SubResource( 4 )
[node name="TileHighlight" parent="." instance=ExtResource( 7 )]
[node name="Player" parent="." instance=ExtResource( 2 )]
[node name="MouseTileHighlight" parent="." instance=ExtResource( 7 )]
[node name="OPlayer" parent="." instance=ExtResource( 2 )]
visible = false
[node name="Camera" parent="OPlayer" index="0"]
visible = false
[node name="MeshInstance" parent="OPlayer" index="1"]
visible = false
[node name="Collision" parent="OPlayer" index="2"]
visible = false
[node name="Movable" parent="OPlayer" index="3"]
visible = false
[node name="World" type="Spatial" parent="."]
script = ExtResource( 3 )
@ -55,90 +59,125 @@ margin_bottom = 40.0
margin_right = 40.0
margin_bottom = 40.0
[node name="WorldMapRect" type="TextureRect" parent="Control/HBoxContainer"]
margin_right = 100.0
margin_bottom = 100.0
rect_min_size = Vector2( 100, 100 )
texture = SubResource( 6 )
expand = true
[node name="GridContainer" type="GridContainer" parent="Control/HBoxContainer"]
margin_right = 109.0
margin_bottom = 104.0
columns = 2
[node name="GenerateWorldButton" type="Button" parent="Control/HBoxContainer"]
margin_left = 104.0
margin_right = 175.0
margin_bottom = 100.0
text = "Generate"
[node name="Label" type="Label" parent="Control/HBoxContainer"]
margin_left = 179.0
margin_top = 43.0
margin_right = 202.0
margin_bottom = 57.0
[node name="Label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_right = 85.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( -335, -33 )
text = "Tile"
[node name="tile_label" type="Label" parent="Control/HBoxContainer"]
margin_left = 206.0
margin_top = 43.0
margin_right = 226.0
margin_bottom = 57.0
[node name="tile_label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_left = 89.0
margin_right = 109.0
margin_bottom = 14.0
text = "0,0"
[node name="Label2" type="Label" parent="Control/HBoxContainer"]
margin_left = 230.0
margin_top = 43.0
margin_right = 296.0
margin_bottom = 57.0
[node name="Label2" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_top = 18.0
margin_right = 85.0
margin_bottom = 32.0
text = "Tile Offset"
[node name="tile_offset_label" type="Label" parent="Control/HBoxContainer"]
margin_left = 300.0
margin_top = 43.0
margin_right = 320.0
margin_bottom = 57.0
[node name="tile_offset_label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_left = 89.0
margin_top = 18.0
margin_right = 109.0
margin_bottom = 32.0
text = "0,0"
[node name="Label3" type="Label" parent="Control/HBoxContainer"]
margin_left = 324.0
margin_top = 43.0
margin_right = 363.0
margin_bottom = 57.0
[node name="Label4" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_top = 36.0
margin_right = 85.0
margin_bottom = 50.0
rect_pivot_offset = Vector2( -335, -33 )
text = "Mouse World"
[node name="mouse_world_label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_left = 89.0
margin_top = 36.0
margin_right = 109.0
margin_bottom = 50.0
text = "0,0"
[node name="Label6" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_top = 54.0
margin_right = 85.0
margin_bottom = 68.0
rect_pivot_offset = Vector2( -335, -33 )
text = "Mouse Tile"
[node name="mouse_tile_label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_left = 89.0
margin_top = 54.0
margin_right = 109.0
margin_bottom = 68.0
text = "0,0"
[node name="Label3" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_top = 72.0
margin_right = 85.0
margin_bottom = 86.0
text = "#Tiles"
[node name="num_tiles_label" type="Label" parent="Control/HBoxContainer"]
margin_left = 367.0
margin_top = 43.0
margin_right = 375.0
margin_bottom = 57.0
[node name="num_tiles_label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_left = 89.0
margin_top = 72.0
margin_right = 109.0
margin_bottom = 86.0
text = "0"
[node name="Label5" type="Label" parent="Control/HBoxContainer"]
margin_left = 379.0
margin_top = 43.0
margin_right = 428.0
margin_bottom = 57.0
[node name="Label5" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_top = 90.0
margin_right = 85.0
margin_bottom = 104.0
text = "#Active"
[node name="num_active_tiles_label" type="Label" parent="Control/HBoxContainer"]
margin_left = 432.0
margin_top = 43.0
margin_right = 440.0
margin_bottom = 57.0
[node name="num_active_tiles_label" type="Label" parent="Control/HBoxContainer/GridContainer"]
margin_left = 89.0
margin_top = 90.0
margin_right = 109.0
margin_bottom = 104.0
text = "0"
[node name="StreamContainer" type="Spatial" parent="."]
script = ExtResource( 4 )
world_rect = Rect2( 0, 0, 20, 20 )
_dimensions = Vector2( 4, 8 )
[node name="ActiveTiles" type="Spatial" parent="StreamContainer"]
[node name="Bounds" type="MeshInstance" parent="StreamContainer"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 )
visible = false
transform = Transform( 4, 0, 0, 0, 1, 0, 0, 0, 2, 0, -1, 0 )
mesh = SubResource( 1 )
skeleton = NodePath("../..")
material/0 = SubResource( 2 )
[connection signal="world_generated" from="World" to="." method="_on_World_world_generated"]
[connection signal="pressed" from="Control/HBoxContainer/GenerateWorldButton" to="." method="_on_GenerateWorldButton_pressed"]
[node name="Area" type="Area" parent="StreamContainer"]
[editable path="Player"]
[node name="CollisionShape" type="CollisionShape" parent="StreamContainer/Area"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 )
shape = SubResource( 9 )
[node name="Camera" type="Camera" parent="."]
transform = Transform( 1, 0, 0, 0, 0.511698, 0.859165, 0, -0.859165, 0.511698, -4.76837e-07, 7.29903, 4.46831 )
current = true
fov = 60.0
script = ExtResource( 6 )
[node name="Player" type="KinematicBody" parent="."]
script = ExtResource( 5 )
[node name="CollisionShape" type="CollisionShape" parent="Player"]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.5, 0 )
shape = SubResource( 7 )
[node name="MeshInstance" type="MeshInstance" parent="Player"]
transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.5, 0 )
mesh = SubResource( 8 )
[connection signal="world_generated" from="World" to="." method="_on_World_world_generated"]
[editable path="OPlayer"]

28
scenes/StreamContainer.cs Normal file
View File

@ -0,0 +1,28 @@
using Godot;
using System;
public class StreamContainer : Spatial
{
// scene nodes
private MeshInstance _bounds;
private Spatial _activeTiles;
// resources
private PackedScene _hexTileScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
[Export] public Vector2 _dimensions = new Vector2(8, 4);
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_bounds = GetNode<MeshInstance>("Bounds");
_activeTiles = GetNode<Spatial>("ActiveTiles");
Transform boundsTransform = Transform.Identity;
boundsTransform = boundsTransform.Scaled(new Vector3(_dimensions.x / 2, 1, _dimensions.y / 2));
_bounds.Transform = boundsTransform;
Update
}
}

108
tests/HexCellTests.cs Normal file
View File

@ -0,0 +1,108 @@
using Godot;
using GoDotTest;
using System.Diagnostics;
public class HexCellTests : TestClass
{
public HexCellTests(Node testScene) : base(testScene)
{
}
[Test]
public void TestHexCellSimple()
{
HexCell cell = new HexCell();
Debug.Assert(cell.CubeCoords == new Vector3(0, 0, 0));
}
[Test]
public void TestAxialCoords()
{
HexCell cell = new HexCell(1, 1, -2);
Debug.Assert(cell.AxialCoords == new Vector2(1, 1));
cell = new HexCell(1, -1);
Debug.Assert(cell.AxialCoords == new Vector2(1, -1));
cell = new HexCell(new Vector3(-1, 2, -1));
HexCell otherCell = cell;
Debug.Assert(otherCell.AxialCoords == new Vector2(-1, 2));
}
[Test]
public void TestAxialCoordsRounded()
{
HexCell cell = new HexCell(new Vector2(-0.1f, 0.6f));
Debug.Assert(cell.CubeCoords == new Vector3(0, 1, -1));
cell = new HexCell(new Vector2(4.2f, -5.5f));
Debug.Assert(cell.CubeCoords == new Vector3(4, -5, 1));
}
[Test]
public void TestConversion()
{
HexCell cell = new HexCell();
Debug.Assert(cell.AxialToCubeCoords(new Vector2(2, 1)) == new Vector3(2, 1, -3));
Debug.Assert(cell.AxialToCubeCoords(new Vector2(-1, -1)) == new Vector3(-1, -1, 2));
}
[Test]
public void TestRounding()
{
HexCell cell = new HexCell();
Debug.Assert(cell.RoundCoords(new Vector3(0.1f, 0.5f, -0.6f)) == new Vector3(0, 1, -1));
Debug.Assert(cell.RoundCoords(new Vector3(-0.4f, -1.3f, 1.7f)) == new Vector3(-1, -1, 2));
Debug.Assert(cell.RoundCoords(new Vector2(-0.1f, 0.6f)) == new Vector3(0, 1, -1));
Debug.Assert(cell.RoundCoords(new Vector2(4.2f, -5.5f)) == new Vector3(4, -5, 1));
}
[Test]
public void TestCoords()
{
HexCell cell = new HexCell();
// from cubic positive
cell.CubeCoords = new Vector3(2, 1, -3);
Debug.Assert(cell.CubeCoords == new Vector3(2, 1, -3));
Debug.Assert(cell.AxialCoords == new Vector2(2, 1));
Debug.Assert(cell.OffsetCoords == new Vector2(2, 2));
// from offset positive
cell.OffsetCoords = new Vector2(2, 2);
Debug.Assert(cell.CubeCoords == new Vector3(2, 1, -3));
Debug.Assert(cell.AxialCoords == new Vector2(2, 1));
Debug.Assert(cell.OffsetCoords == new Vector2(2, 2));
// from offset negative
cell.OffsetCoords = new Vector2(-1, -2);
Debug.Assert(cell.CubeCoords == new Vector3(-1, -1, 2));
Debug.Assert(cell.AxialCoords == new Vector2(-1, -1));
Debug.Assert(cell.OffsetCoords == new Vector2(-1, -2));
}
[Test]
public void TestNearby()
{
HexCell cell = new HexCell(new Vector2(1, 2));
// adjacent
HexCell otherCell = cell.getAdjacent(HexCell.DIR_N);
Debug.Assert(otherCell.AxialCoords == new Vector2(1, 3));
otherCell = cell.getAdjacent(HexCell.DIR_NE);
Debug.Assert(otherCell.AxialCoords == new Vector2(2, 2));
otherCell = cell.getAdjacent(HexCell.DIR_SE);
Debug.Assert(otherCell.AxialCoords == new Vector2(2, 1));
otherCell = cell.getAdjacent(HexCell.DIR_S);
Debug.Assert(otherCell.AxialCoords == new Vector2(1, 1));
otherCell = cell.getAdjacent(HexCell.DIR_SW);
Debug.Assert(otherCell.AxialCoords == new Vector2(0, 2));
otherCell = cell.getAdjacent(HexCell.DIR_NW);
Debug.Assert(otherCell.AxialCoords == new Vector2(0, 3));
// not really adjacent
otherCell = cell.getAdjacent(new Vector3(-3, -3, 6));
Debug.Assert(otherCell.AxialCoords == new Vector2(-2, -1));
}
}

23
tests/HexGridTests.cs Normal file
View File

@ -0,0 +1,23 @@
using Godot;
using GoDotTest;
using System.Diagnostics;
public class HexGridTests : TestClass
{
public HexGridTests(Node testScene) : base(testScene)
{
}
[Test]
public void TestGetAt()
{
HexGrid grid = new HexGrid();
float w = grid.HexSize.x;
float h = grid.HexSize.y;
Debug.Assert(grid.GetHexAt(new Vector2(0, 0)).AxialCoords == new Vector2(0, 0));
Debug.Assert(grid.GetHexAt(new Vector2(w / 2 - 0.01f, 0)).AxialCoords == new Vector2(0, 0));
Debug.Assert(grid.GetHexAt(new Vector2(w / 2 - 0.01f, -h/2)).AxialCoords == new Vector2(1, 0));
Debug.Assert(grid.GetHexAt(new Vector2(w / 2 - 0.01f, h/2)).AxialCoords == new Vector2(1, -1));
}
}

9
tests/Tests.cs Normal file
View File

@ -0,0 +1,9 @@
using System.Reflection;
using Godot;
using GoDotTest;
public class Tests : Control
{
public override async void _Ready()
=> await GoTest.RunTests(Assembly.GetExecutingAssembly(), this);
}

8
tests/Tests.tscn Normal file
View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://tests/Tests.cs" type="Script" id=1]
[node name="Control" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 1 )

27
utils/TileHighlight.tscn Normal file
View File

@ -0,0 +1,27 @@
[gd_scene load_steps=4 format=2]
[sub_resource type="SpatialMaterial" id=10]
albedo_color = Color( 0.803922, 0.34902, 0.34902, 1 )
[sub_resource type="CylinderMesh" id=3]
material = SubResource( 10 )
top_radius = 0.5
bottom_radius = 0.5
height = 0.1
radial_segments = 6
rings = 1
[sub_resource type="SpatialMaterial" id=4]
render_priority = 1
flags_transparent = true
albedo_color = Color( 1, 1, 1, 0.407843 )
roughness = 0.0
[node name="TileHighlight" type="Spatial"]
[node name="TileMesh" type="MeshInstance" parent="."]
transform = Transform( -4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0, 0 )
cast_shadow = 0
mesh = SubResource( 3 )
skeleton = NodePath("../..")
material/0 = SubResource( 4 )