Noise based map generation, movement component uses height.
parent
12c1e4df86
commit
041d580550
|
@ -5,7 +5,9 @@
|
||||||
<!-- Required for some nuget packages to work -->
|
<!-- Required for some nuget packages to work -->
|
||||||
<!-- See https://www.reddit.com/r/godot/comments/l0naqg/comment/gjwfspm/ -->
|
<!-- See https://www.reddit.com/r/godot/comments/l0naqg/comment/gjwfspm/ -->
|
||||||
<!-- And https://github.com/godotengine/godot/issues/42271#issuecomment-751423827 -->
|
<!-- And https://github.com/godotengine/godot/issues/42271#issuecomment-751423827 -->
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
||||||
|
<DefaultItemExcludes>$(DefaultItemExcludes);script_templates/*</DefaultItemExcludes>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
19
HexCell.cs
19
HexCell.cs
|
@ -15,8 +15,11 @@ public class HexCell : Resource
|
||||||
|
|
||||||
public static readonly Array DIR_ALL = new Array()
|
public static readonly Array DIR_ALL = new Array()
|
||||||
{ DIR_N, DIR_NE, DIR_SE, DIR_S, DIR_SW, DIR_NW };
|
{ DIR_N, DIR_NE, DIR_SE, DIR_S, DIR_SW, DIR_NW };
|
||||||
|
|
||||||
public HexCell() { }
|
public HexCell()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public HexCell(float cubeX, float cubeY, float cubeZ)
|
public HexCell(float cubeX, float cubeY, float cubeZ)
|
||||||
{
|
{
|
||||||
CubeCoords = RoundCoords(new Vector3(cubeX, cubeY, cubeZ));
|
CubeCoords = RoundCoords(new Vector3(cubeX, cubeY, cubeZ));
|
||||||
|
@ -43,18 +46,17 @@ public class HexCell : Resource
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector3 _cubeCoords;
|
private Vector3 _cubeCoords;
|
||||||
|
|
||||||
public Vector3 CubeCoords
|
public Vector3 CubeCoords
|
||||||
{
|
{
|
||||||
get
|
get { return _cubeCoords; }
|
||||||
{
|
|
||||||
return _cubeCoords;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (Mathf.Abs(value.x + value.y + value.z) > 0.0001)
|
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());
|
GD.Print("Warning: Invalid cube coordinates for hex (x + y + z != 0): ", value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
_cubeCoords = RoundCoords(value);
|
_cubeCoords = RoundCoords(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,10 +65,7 @@ public class HexCell : Resource
|
||||||
{
|
{
|
||||||
get => new Vector2(CubeCoords.x, CubeCoords.y);
|
get => new Vector2(CubeCoords.x, CubeCoords.y);
|
||||||
|
|
||||||
set
|
set { CubeCoords = AxialToCubeCoords(value); }
|
||||||
{
|
|
||||||
CubeCoords = AxialToCubeCoords(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 OffsetCoords
|
public Vector2 OffsetCoords
|
||||||
|
|
11
HexGrid.cs
11
HexGrid.cs
|
@ -13,22 +13,20 @@ public class HexGrid : Resource
|
||||||
{
|
{
|
||||||
get { return _hexSize; }
|
get { return _hexSize; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 HexScale
|
public Vector2 HexScale
|
||||||
{
|
{
|
||||||
get
|
get { return _hexScale; }
|
||||||
{
|
|
||||||
return _hexScale;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_hexScale = value;
|
_hexScale = value;
|
||||||
_hexSize = _baseHexSize * _hexScale;
|
_hexSize = _baseHexSize * _hexScale;
|
||||||
_hexTransform = new Transform2D(
|
_hexTransform = new Transform2D(
|
||||||
new Vector2(_hexSize.x * 3/4, -_hexSize.y / 2),
|
new Vector2(_hexSize.x * 3 / 4, -_hexSize.y / 2),
|
||||||
new Vector2(0, -_hexSize.y),
|
new Vector2(0, -_hexSize.y),
|
||||||
new Vector2(0, 0)
|
new Vector2(0, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
_hexTransformInv = _hexTransform.AffineInverse();
|
_hexTransformInv = _hexTransform.AffineInverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,5 +60,4 @@ public class HexGrid : Resource
|
||||||
HexCell result = new HexCell(_hexTransformInv * planeCoord);
|
HexCell result = new HexCell(_hexTransformInv * planeCoord);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@ public class MovableComponent : Node
|
||||||
public float targetAngle = 0;
|
public float targetAngle = 0;
|
||||||
public float currentAngle = 0;
|
public float currentAngle = 0;
|
||||||
public float currentAngularVelocity = 0;
|
public float currentAngularVelocity = 0;
|
||||||
|
|
||||||
[Export] public float maxSpeed = 3;
|
[Export] public float maxSpeed = 3;
|
||||||
|
|
||||||
private SpringDamper _positionSpringDamper;
|
private SpringDamper _positionSpringDamper;
|
||||||
|
@ -32,49 +32,50 @@ public class MovableComponent : Node
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
public override void _Process(float delta)
|
public override void _Process(float delta)
|
||||||
{
|
{
|
||||||
Vector3 targetDir = Vector3.Zero;
|
Vector3 targetDir = Vector3.Zero;
|
||||||
Vector3 targetError = targetPosition - currentPosition;
|
Vector3 targetError = targetPosition - currentPosition;
|
||||||
|
|
||||||
if (targetError.LengthSquared() > 0.01)
|
if (targetError.LengthSquared() > 0.01)
|
||||||
{
|
{
|
||||||
targetDir = targetError.Normalized();
|
targetDir = targetError.Normalized();
|
||||||
targetAngle = new Vector3(0, 0, 1).SignedAngleTo(targetDir, Vector3.Up);
|
targetAngle = new Vector3(0, 0, 1).SignedAngleTo(targetDir, Vector3.Up);
|
||||||
|
|
||||||
if (currentAngle < Mathf.Pi && targetAngle > Mathf.Pi)
|
if (currentAngle < Mathf.Pi && targetAngle > Mathf.Pi)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (targetAngle - currentAngle > Mathf.Pi)
|
if (targetAngle - currentAngle > Mathf.Pi)
|
||||||
{
|
{
|
||||||
currentAngle += 2 * Mathf.Pi;
|
currentAngle += 2 * Mathf.Pi;
|
||||||
}
|
}
|
||||||
else if (targetAngle - currentAngle < -Mathf.Pi)
|
else if (targetAngle - currentAngle < -Mathf.Pi)
|
||||||
{
|
{
|
||||||
currentAngle -= 2 * Mathf.Pi;
|
currentAngle -= 2 * Mathf.Pi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mathf.Abs(currentAngularVelocity) > 0.1 || Mathf.Abs(targetAngle - currentAngle) > 0.01)
|
|
||||||
{
|
|
||||||
var springDamperResult = _angleSpringDamper.Calc(currentAngle, currentAngularVelocity, targetAngle, delta);
|
|
||||||
|
|
||||||
currentAngle = springDamperResult.Item1;
|
if (Mathf.Abs(currentAngularVelocity) > 0.1 || Mathf.Abs(targetAngle - currentAngle) > 0.01)
|
||||||
currentAngularVelocity = springDamperResult.Item2;
|
{
|
||||||
|
var springDamperResult =
|
||||||
EmitSignal("OrientationUpdated", this.currentAngle);
|
_angleSpringDamper.Calc(currentAngle, currentAngularVelocity, targetAngle, delta);
|
||||||
}
|
|
||||||
|
|
||||||
if (( Mathf.Abs(currentAngularVelocity) < 5 && Mathf.Abs(targetAngle - currentAngle) < 0.3)
|
|
||||||
&& (targetPosition - currentPosition).LengthSquared() > 0.01)
|
|
||||||
{
|
|
||||||
var springDamperResult =
|
|
||||||
_positionSpringDamper.CalcClampedSpeed(currentPosition, currentVelocity, targetPosition, delta, maxSpeed);
|
|
||||||
|
|
||||||
currentPosition = springDamperResult.Item1;
|
currentAngle = springDamperResult.Item1;
|
||||||
currentVelocity = springDamperResult.Item2;
|
currentAngularVelocity = springDamperResult.Item2;
|
||||||
|
|
||||||
EmitSignal("PositionUpdated", currentPosition);
|
EmitSignal("OrientationUpdated", this.currentAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((Mathf.Abs(currentAngularVelocity) < 5 && Mathf.Abs(targetAngle - currentAngle) < 0.3)
|
||||||
|
&& (targetPosition - currentPosition).LengthSquared() > 0.01)
|
||||||
|
{
|
||||||
|
var springDamperResult =
|
||||||
|
_positionSpringDamper.CalcClampedSpeed(currentPosition, currentVelocity, targetPosition, delta,
|
||||||
|
maxSpeed);
|
||||||
|
|
||||||
|
currentPosition = springDamperResult.Item1;
|
||||||
|
currentVelocity = springDamperResult.Item2;
|
||||||
|
|
||||||
|
EmitSignal("PositionUpdated", currentPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public class WorldInfoComponent : Node
|
||||||
|
{
|
||||||
|
[Export] public NodePath World;
|
||||||
|
|
||||||
|
private HexTile3D _currentHexTile3D;
|
||||||
|
public TileWorld TileWorld;
|
||||||
|
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
TileWorld = GetNode<TileWorld>(World);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetWorld(TileWorld tileWorld)
|
||||||
|
{
|
||||||
|
TileWorld = tileWorld;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,11 @@ using System;
|
||||||
|
|
||||||
public class Player : KinematicBody
|
public class Player : KinematicBody
|
||||||
{
|
{
|
||||||
|
// other members
|
||||||
private MovableComponent _movable;
|
private MovableComponent _movable;
|
||||||
private Spatial _geometry;
|
private Spatial _geometry;
|
||||||
|
private WorldInfoComponent _worldInfo;
|
||||||
|
private Vector2 _offsetCoord = Vector2.Zero;
|
||||||
|
|
||||||
// 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()
|
||||||
|
@ -17,17 +20,36 @@ public class Player : KinematicBody
|
||||||
}
|
}
|
||||||
|
|
||||||
_geometry = (Spatial)FindNode("Geometry", false);
|
_geometry = (Spatial)FindNode("Geometry", false);
|
||||||
|
|
||||||
|
_worldInfo = (WorldInfoComponent)FindNode("WorldInfo", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPositionUpdated(Vector3 newPosition)
|
public void OnPositionUpdated(Vector3 newPosition)
|
||||||
{
|
{
|
||||||
|
if (_worldInfo != null)
|
||||||
|
{
|
||||||
|
Vector2 new_offset_coord = _worldInfo.TileWorld.WorldToOffsetCoords(newPosition);
|
||||||
|
if (_offsetCoord != new_offset_coord)
|
||||||
|
{
|
||||||
|
GD.Print("New offset coord " + new_offset_coord);
|
||||||
|
_offsetCoord = new_offset_coord;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_movable != null)
|
||||||
|
{
|
||||||
|
_movable.targetPosition.y = _worldInfo.TileWorld.GetHeightAtOffset(new_offset_coord);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Transform transform = Transform;
|
Transform transform = Transform;
|
||||||
transform.origin = newPosition;
|
transform.origin = newPosition;
|
||||||
Transform = transform;
|
Transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOrientationUpdated(float newOrientation)
|
private void OnOrientationUpdated(float newOrientation)
|
||||||
{
|
{
|
||||||
_geometry.Transform = new Transform (new Quat(Vector3.Up, newOrientation), Vector3.Zero);
|
_geometry.Transform = new Transform(new Quat(Vector3.Up, newOrientation), Vector3.Zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
[gd_resource type="SpatialMaterial" format=2]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
albedo_color = Color( 1, 0, 1, 1 )
|
|
@ -9,17 +9,17 @@
|
||||||
config_version=4
|
config_version=4
|
||||||
|
|
||||||
_global_script_classes=[ {
|
_global_script_classes=[ {
|
||||||
"base": "Node",
|
"base": "Reference",
|
||||||
"class": "ClickableComponent",
|
"class": "ClickableComponent",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://components/ClickableComponent.gd"
|
"path": "res://components/ClickableComponent.gd"
|
||||||
}, {
|
}, {
|
||||||
"base": "KinematicBody2D",
|
"base": "Reference",
|
||||||
"class": "CollisionLine",
|
"class": "CollisionLine",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://utils/CollisionLine.gd"
|
"path": "res://utils/CollisionLine.gd"
|
||||||
}, {
|
}, {
|
||||||
"base": "Node",
|
"base": "Reference",
|
||||||
"class": "ColorComponent",
|
"class": "ColorComponent",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://components/ColorComponent.gd"
|
"path": "res://components/ColorComponent.gd"
|
||||||
|
@ -54,7 +54,7 @@ _global_script_classes=[ {
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://utils/SpringDamper.gd"
|
"path": "res://utils/SpringDamper.gd"
|
||||||
}, {
|
}, {
|
||||||
"base": "Sprite",
|
"base": "Reference",
|
||||||
"class": "TintedSpriteComponent",
|
"class": "TintedSpriteComponent",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://components/TintedSpriteComponent.gd"
|
"path": "res://components/TintedSpriteComponent.gd"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using GoDotLog;
|
||||||
using Dictionary = Godot.Collections.Dictionary;
|
using Dictionary = Godot.Collections.Dictionary;
|
||||||
using Array = Godot.Collections.Array;
|
using Array = Godot.Collections.Array;
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@ public class AdaptiveWorldStream : Spatial
|
||||||
private Label _mouseTileLabel;
|
private Label _mouseTileLabel;
|
||||||
private Label _numCoordsAddedLabel;
|
private Label _numCoordsAddedLabel;
|
||||||
private Label _numCoordsRemovedLabel;
|
private Label _numCoordsRemovedLabel;
|
||||||
|
private TextureRect _worldTextureRect;
|
||||||
|
|
||||||
// scene nodes
|
// scene nodes
|
||||||
private Spatial _tileHighlight;
|
private Spatial _tileHighlight;
|
||||||
|
@ -23,6 +26,7 @@ public class AdaptiveWorldStream : Spatial
|
||||||
private Area _streamContainerArea;
|
private Area _streamContainerArea;
|
||||||
private Spatial _streamContainerActiveTiles;
|
private Spatial _streamContainerActiveTiles;
|
||||||
private Player _player;
|
private Player _player;
|
||||||
|
private TileWorld _tileWorld;
|
||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
private PackedScene _tileHighlightScene;
|
private PackedScene _tileHighlightScene;
|
||||||
|
@ -45,6 +49,7 @@ public class AdaptiveWorldStream : Spatial
|
||||||
_mouseTileLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/mouse_tile_label");
|
_mouseTileLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/mouse_tile_label");
|
||||||
_numCoordsAddedLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/num_coords_added_label");
|
_numCoordsAddedLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/num_coords_added_label");
|
||||||
_numCoordsRemovedLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/num_coords_removed_label");
|
_numCoordsRemovedLabel = GetNode<Label>("Control/HBoxContainer/GridContainer/num_coords_removed_label");
|
||||||
|
_worldTextureRect = GetNode<TextureRect>("Control/WorldTextureRect");
|
||||||
|
|
||||||
// scene nodes
|
// scene nodes
|
||||||
_tileHighlight = GetNode<Spatial>("TileHighlight");
|
_tileHighlight = GetNode<Spatial>("TileHighlight");
|
||||||
|
@ -53,6 +58,9 @@ public class AdaptiveWorldStream : Spatial
|
||||||
_streamContainerArea = GetNode<Area>("StreamContainer/Area");
|
_streamContainerArea = GetNode<Area>("StreamContainer/Area");
|
||||||
_streamContainerActiveTiles = GetNode<Spatial>("StreamContainer/ActiveTiles");
|
_streamContainerActiveTiles = GetNode<Spatial>("StreamContainer/ActiveTiles");
|
||||||
_player = GetNode<Player>("Player");
|
_player = GetNode<Player>("Player");
|
||||||
|
_tileWorld = GetNode<TileWorld>("TileWorld");
|
||||||
|
|
||||||
|
Debug.Assert(_tileWorld != null);
|
||||||
|
|
||||||
// resources
|
// resources
|
||||||
_tileHighlightScene = GD.Load<PackedScene>("utils/TileHighlight.tscn");
|
_tileHighlightScene = GD.Load<PackedScene>("utils/TileHighlight.tscn");
|
||||||
|
@ -63,10 +71,23 @@ public class AdaptiveWorldStream : Spatial
|
||||||
_currentTileOffset = new Vector2();
|
_currentTileOffset = new Vector2();
|
||||||
_hexGrid = new HexGrid();
|
_hexGrid = new HexGrid();
|
||||||
|
|
||||||
|
// update data
|
||||||
|
_worldTextureRect.RectSize = _tileWorld.Size;
|
||||||
|
|
||||||
// connect signals
|
// connect signals
|
||||||
_streamContainerArea.Connect("input_event", this, nameof(OnAreaInputEvent));
|
_streamContainerArea.Connect("input_event", this, nameof(OnAreaInputEvent));
|
||||||
_streamContainer.Connect("TileSelected", this, nameof(OnTileSelected));
|
_streamContainer.Connect("TileSelected", this, nameof(OnTileSelected));
|
||||||
|
_tileWorld.Connect("WorldGenerated", this, nameof(OnWorldGenerated));
|
||||||
|
|
||||||
|
// perform dependency injection
|
||||||
|
//_streamContainer.SetWorld(_tileWorld);
|
||||||
|
WorldInfoComponent worldInfoComponent = _player.GetNode<WorldInfoComponent>("WorldInfo");
|
||||||
|
if (worldInfoComponent != null)
|
||||||
|
{
|
||||||
|
worldInfoComponent.SetWorld(_tileWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
_tileWorld.Generate();
|
||||||
UpdateCurrentTile();
|
UpdateCurrentTile();
|
||||||
_streamContainer.SetCenterTile(_currentTile);
|
_streamContainer.SetCenterTile(_currentTile);
|
||||||
}
|
}
|
||||||
|
@ -97,21 +118,21 @@ public class AdaptiveWorldStream : Spatial
|
||||||
Transform playerTransform = _player.Transform;
|
Transform playerTransform = _player.Transform;
|
||||||
Vector3 playerCoord = playerTransform.origin;
|
Vector3 playerCoord = playerTransform.origin;
|
||||||
_currentTile = _hexGrid.GetHexAt(new Vector2(playerCoord.x, playerCoord.z));
|
_currentTile = _hexGrid.GetHexAt(new Vector2(playerCoord.x, playerCoord.z));
|
||||||
|
|
||||||
_tileLabel.Text = playerTransform.ToString();
|
_tileLabel.Text = playerTransform.ToString();
|
||||||
_tileOffsetLabel.Text = _currentTile.OffsetCoords.ToString();
|
_tileOffsetLabel.Text = _currentTile.OffsetCoords.ToString();
|
||||||
|
|
||||||
//playerTransform.origin += new Vector3(-0.1f, 0, 1) * delta;
|
|
||||||
_player.Transform = playerTransform;
|
_player.Transform = playerTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void _Process(float delta)
|
public override void _Process(float delta)
|
||||||
{
|
{
|
||||||
_framesPerSecondLabel.Text = Engine.GetFramesPerSecond().ToString();
|
_framesPerSecondLabel.Text = Engine.GetFramesPerSecond().ToString();
|
||||||
_lastTile = _currentTile;
|
_lastTile = _currentTile;
|
||||||
|
|
||||||
UpdateCurrentTile();
|
UpdateCurrentTile();
|
||||||
|
|
||||||
Transform tileHighlightTransform = Transform.Identity;
|
Transform tileHighlightTransform = Transform.Identity;
|
||||||
Vector2 currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
|
Vector2 currentTileCenter = _hexGrid.GetHexCenter(_currentTile);
|
||||||
tileHighlightTransform.origin.x = currentTileCenter.x;
|
tileHighlightTransform.origin.x = currentTileCenter.x;
|
||||||
|
@ -121,7 +142,6 @@ public class AdaptiveWorldStream : Spatial
|
||||||
if (_currentTile.CubeCoords != _lastTile.CubeCoords)
|
if (_currentTile.CubeCoords != _lastTile.CubeCoords)
|
||||||
{
|
{
|
||||||
_streamContainer.SetCenterTile(_currentTile);
|
_streamContainer.SetCenterTile(_currentTile);
|
||||||
// CreateStreamActiveTiles();
|
|
||||||
|
|
||||||
_numTilesLabel.Text = _streamContainerActiveTiles.GetChildCount().ToString();
|
_numTilesLabel.Text = _streamContainerActiveTiles.GetChildCount().ToString();
|
||||||
_numCoordsAddedLabel.Text = _streamContainer.AddedCoords.Count.ToString();
|
_numCoordsAddedLabel.Text = _streamContainer.AddedCoords.Count.ToString();
|
||||||
|
@ -129,7 +149,9 @@ public class AdaptiveWorldStream : Spatial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal, int shapeIndex)
|
|
||||||
|
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
|
||||||
|
int shapeIndex)
|
||||||
{
|
{
|
||||||
HexCell cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
|
HexCell cellAtCursor = _hexGrid.GetHexAt(new Vector2(position.x, position.z));
|
||||||
Transform highlightTransform = Transform.Identity;
|
Transform highlightTransform = Transform.Identity;
|
||||||
|
@ -140,15 +162,15 @@ public class AdaptiveWorldStream : Spatial
|
||||||
|
|
||||||
_mouseWorldLabel.Text = position.ToString();
|
_mouseWorldLabel.Text = position.ToString();
|
||||||
_mouseTileLabel.Text = cellAtCursor.OffsetCoords.ToString();
|
_mouseTileLabel.Text = cellAtCursor.OffsetCoords.ToString();
|
||||||
|
|
||||||
_mouseTileHighlight.Transform = highlightTransform;
|
_mouseTileHighlight.Transform = highlightTransform;
|
||||||
|
|
||||||
if (inputEvent is InputEventMouseButton)
|
if (inputEvent is InputEventMouseButton && ((InputEventMouseButton) inputEvent).Pressed)
|
||||||
{
|
{
|
||||||
_player.Transform = highlightTransform;
|
_streamContainer.EmitSignal("TileSelected", _streamContainer.GetTile3dAt(cellAtCursor.OffsetCoords));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnTileSelected(HexTile3D tile)
|
public void OnTileSelected(HexTile3D tile)
|
||||||
{
|
{
|
||||||
if (_player == null)
|
if (_player == null)
|
||||||
|
@ -164,4 +186,17 @@ public class AdaptiveWorldStream : Spatial
|
||||||
|
|
||||||
movableComponent.targetPosition = tile.Transform.origin;
|
movableComponent.targetPosition = tile.Transform.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void OnWorldGenerated()
|
||||||
|
{
|
||||||
|
GD.Print("Using new map");
|
||||||
|
ImageTexture new_world_texture = new ImageTexture();
|
||||||
|
|
||||||
|
_tileWorld.Heightmap.Unlock();
|
||||||
|
new_world_texture.CreateFromImage(_tileWorld.Heightmap);
|
||||||
|
_tileWorld.Heightmap.Lock();
|
||||||
|
|
||||||
|
_worldTextureRect.Texture = new_world_texture;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
[gd_scene load_steps=14 format=2]
|
[gd_scene load_steps=15 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://scenes/AdaptiveWorldStream.cs" type="Script" id=1]
|
[ext_resource path="res://scenes/AdaptiveWorldStream.cs" type="Script" id=1]
|
||||||
[ext_resource path="res://assets/CreatusPiratePack/characters/Pirate1final_0.01.glb" type="PackedScene" id=2]
|
[ext_resource path="res://assets/CreatusPiratePack/characters/Pirate1final_0.01.glb" type="PackedScene" id=2]
|
||||||
[ext_resource path="res://scenes/World.gd" type="Script" id=3]
|
[ext_resource path="res://components/WorldInfoComponent.cs" type="Script" id=3]
|
||||||
[ext_resource path="res://scenes/StreamContainer.cs" type="Script" id=4]
|
[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://entities/Player.cs" type="Script" id=5]
|
||||||
[ext_resource path="res://scenes/DebugCamera.gd" type="Script" id=6]
|
[ext_resource path="res://scenes/DebugCamera.gd" type="Script" id=6]
|
||||||
[ext_resource path="res://utils/TileHighlight.tscn" type="PackedScene" id=7]
|
[ext_resource path="res://utils/TileHighlight.tscn" type="PackedScene" id=7]
|
||||||
[ext_resource path="res://components/MovableComponent.cs" type="Script" id=8]
|
[ext_resource path="res://components/MovableComponent.cs" type="Script" id=8]
|
||||||
|
[ext_resource path="res://scenes/TileWorld.cs" type="Script" id=9]
|
||||||
|
|
||||||
[sub_resource type="CubeMesh" id=1]
|
[sub_resource type="CubeMesh" id=1]
|
||||||
size = Vector3( 1, 1, 1 )
|
size = Vector3( 1, 1, 1 )
|
||||||
|
@ -32,13 +33,14 @@ radial_segments = 16
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
[node name="TileHighlight" parent="." instance=ExtResource( 7 )]
|
[node name="TileHighlight" parent="." instance=ExtResource( 7 )]
|
||||||
|
visible = false
|
||||||
|
|
||||||
[node name="MouseTileHighlight" parent="." instance=ExtResource( 7 )]
|
[node name="MouseTileHighlight" parent="." instance=ExtResource( 7 )]
|
||||||
|
|
||||||
[node name="World" type="Spatial" parent="."]
|
[node name="TileWorld" type="Spatial" parent="."]
|
||||||
script = ExtResource( 3 )
|
script = ExtResource( 9 )
|
||||||
|
|
||||||
[node name="DirectionalLight" type="DirectionalLight" parent="World"]
|
[node name="DirectionalLight" type="DirectionalLight" parent="TileWorld"]
|
||||||
transform = Transform( 0.328059, -0.878387, 0.347583, 0, 0.367946, 0.929847, -0.944657, -0.305045, 0.120708, 0, 6.59293, 1.20265 )
|
transform = Transform( 0.328059, -0.878387, 0.347583, 0, 0.367946, 0.929847, -0.944657, -0.305045, 0.120708, 0, 6.59293, 1.20265 )
|
||||||
shadow_enabled = true
|
shadow_enabled = true
|
||||||
directional_shadow_mode = 0
|
directional_shadow_mode = 0
|
||||||
|
@ -178,9 +180,16 @@ margin_right = 127.0
|
||||||
margin_bottom = 158.0
|
margin_bottom = 158.0
|
||||||
text = "0"
|
text = "0"
|
||||||
|
|
||||||
|
[node name="WorldTextureRect" type="TextureRect" parent="Control"]
|
||||||
|
margin_left = 1.0
|
||||||
|
margin_top = 300.0
|
||||||
|
margin_right = 101.0
|
||||||
|
margin_bottom = 400.0
|
||||||
|
|
||||||
[node name="StreamContainer" type="Spatial" parent="."]
|
[node name="StreamContainer" type="Spatial" parent="."]
|
||||||
script = ExtResource( 4 )
|
script = ExtResource( 4 )
|
||||||
Dimensions = Vector2( 18, 17 )
|
Dimensions = Vector2( 18, 17 )
|
||||||
|
World = NodePath("../TileWorld")
|
||||||
|
|
||||||
[node name="ActiveTiles" type="Spatial" parent="StreamContainer"]
|
[node name="ActiveTiles" type="Spatial" parent="StreamContainer"]
|
||||||
|
|
||||||
|
@ -222,3 +231,7 @@ script = ExtResource( 8 )
|
||||||
|
|
||||||
[node name="Pirate1final_001" parent="Player/Geometry" instance=ExtResource( 2 )]
|
[node name="Pirate1final_001" parent="Player/Geometry" instance=ExtResource( 2 )]
|
||||||
transform = Transform( 0.4, 0, 0, 0, 0.4, 0, 0, 0, 0.4, 0, 0, 0 )
|
transform = Transform( 0.4, 0, 0, 0, 0.4, 0, 0, 0, 0.4, 0, 0, 0 )
|
||||||
|
|
||||||
|
[node name="WorldInfo" type="Node" parent="Player"]
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
World = NodePath("../../TileWorld")
|
||||||
|
|
|
@ -4,37 +4,37 @@ public class HexTile3D : Spatial
|
||||||
{
|
{
|
||||||
public enum TileType
|
public enum TileType
|
||||||
{
|
{
|
||||||
|
Undefined,
|
||||||
Sand,
|
Sand,
|
||||||
Grass,
|
Grass,
|
||||||
DeepGrass
|
DeepGrass
|
||||||
}
|
}
|
||||||
|
|
||||||
static public TileType[] ValidTileTypes = { TileType.Sand, TileType.Grass, TileType.DeepGrass };
|
static public TileType[] ValidTileTypes = { TileType.Sand, TileType.Grass, TileType.DeepGrass };
|
||||||
|
|
||||||
// scene nodes
|
// scene nodes
|
||||||
private MeshInstance _mesh;
|
private MeshInstance _mesh;
|
||||||
private Area _area;
|
private Area _area;
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
[Signal]
|
[Signal]
|
||||||
delegate void TileSelected(HexTile3D tile3d);
|
delegate void TileSelected(HexTile3D tile3d);
|
||||||
|
|
||||||
// other member variables
|
// other member variables
|
||||||
|
private SpatialMaterial _undefinedMaterial;
|
||||||
private SpatialMaterial _sandMaterial;
|
private SpatialMaterial _sandMaterial;
|
||||||
private SpatialMaterial _grassMaterial;
|
private SpatialMaterial _grassMaterial;
|
||||||
private SpatialMaterial _deepGrassMaterial;
|
private SpatialMaterial _deepGrassMaterial;
|
||||||
private SpatialMaterial _previousMaterial;
|
private SpatialMaterial _previousMaterial;
|
||||||
|
|
||||||
private HexGrid _hexGrid;
|
private HexGrid _hexGrid;
|
||||||
|
|
||||||
public HexCell Cell = new HexCell();
|
public HexCell Cell = new HexCell();
|
||||||
public bool IsMouseOver = false;
|
public bool IsMouseOver = false;
|
||||||
|
|
||||||
public Vector2 OffsetCoords
|
public Vector2 OffsetCoords
|
||||||
{
|
{
|
||||||
get
|
get { return Cell.OffsetCoords; }
|
||||||
{
|
|
||||||
return Cell.OffsetCoords;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
@ -46,14 +46,12 @@ public class HexTile3D : Spatial
|
||||||
Transform = tile3dTransform;
|
Transform = tile3dTransform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TileType _type;
|
private TileType _type;
|
||||||
|
|
||||||
public TileType Type
|
public TileType Type
|
||||||
{
|
{
|
||||||
get
|
get { return _type; }
|
||||||
{
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
@ -61,11 +59,17 @@ public class HexTile3D : Spatial
|
||||||
|
|
||||||
switch (_type)
|
switch (_type)
|
||||||
{
|
{
|
||||||
case TileType.Sand: _mesh.SetSurfaceMaterial(0, _sandMaterial);
|
case TileType.Undefined:
|
||||||
|
_mesh.SetSurfaceMaterial(0, _undefinedMaterial);
|
||||||
|
break;
|
||||||
|
case TileType.Sand:
|
||||||
|
_mesh.SetSurfaceMaterial(0, _sandMaterial);
|
||||||
break;
|
break;
|
||||||
case TileType.Grass: _mesh.SetSurfaceMaterial(0, _grassMaterial);
|
case TileType.Grass:
|
||||||
|
_mesh.SetSurfaceMaterial(0, _grassMaterial);
|
||||||
break;
|
break;
|
||||||
case TileType.DeepGrass: _mesh.SetSurfaceMaterial(0, _deepGrassMaterial);
|
case TileType.DeepGrass:
|
||||||
|
_mesh.SetSurfaceMaterial(0, _deepGrassMaterial);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GD.Print("Invalid tile type: " + value.ToString());
|
GD.Print("Invalid tile type: " + value.ToString());
|
||||||
|
@ -78,7 +82,7 @@ public class HexTile3D : Spatial
|
||||||
{
|
{
|
||||||
_hexGrid = new HexGrid();
|
_hexGrid = new HexGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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()
|
||||||
{
|
{
|
||||||
|
@ -89,15 +93,17 @@ public class HexTile3D : Spatial
|
||||||
_area.Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
|
_area.Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
|
||||||
_area.Connect("mouse_exited", this, nameof(OnAreaMouseExited));
|
_area.Connect("mouse_exited", this, nameof(OnAreaMouseExited));
|
||||||
|
|
||||||
|
_undefinedMaterial = GD.Load<SpatialMaterial>("res://materials/UndefinedTile.tres");
|
||||||
_sandMaterial = GD.Load<SpatialMaterial>("res://materials/SandTile.tres");
|
_sandMaterial = GD.Load<SpatialMaterial>("res://materials/SandTile.tres");
|
||||||
_grassMaterial = GD.Load<SpatialMaterial>("res://materials/GrassTile.tres");
|
_grassMaterial = GD.Load<SpatialMaterial>("res://materials/GrassTile.tres");
|
||||||
_deepGrassMaterial = GD.Load<SpatialMaterial>("res://materials/DeepGrassTile.tres");
|
_deepGrassMaterial = GD.Load<SpatialMaterial>("res://materials/DeepGrassTile.tres");
|
||||||
|
|
||||||
this.Type = TileType.Grass;
|
this.Type = TileType.Undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal, int shapeIndex)
|
public void OnAreaInputEvent(Node camera, InputEvent inputEvent, Vector3 position, Vector3 normal,
|
||||||
|
int shapeIndex)
|
||||||
{
|
{
|
||||||
if (IsMouseOver && inputEvent is InputEventMouseButton)
|
if (IsMouseOver && inputEvent is InputEventMouseButton)
|
||||||
{
|
{
|
||||||
|
@ -124,11 +130,10 @@ public class HexTile3D : Spatial
|
||||||
IsMouseOver = false;
|
IsMouseOver = false;
|
||||||
_mesh.MaterialOverride = _previousMaterial;
|
_mesh.MaterialOverride = _previousMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Called every frame. 'delta' is the elapsed time since the previous frame.
|
// // Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
// public override void _Process(float delta)
|
// public override void _Process(float delta)
|
||||||
// {
|
// {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[gd_scene load_steps=5 format=2]
|
[gd_scene load_steps=5 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://scenes/HexTile3D.cs" type="Script" id=1]
|
[ext_resource path="res://scenes/HexTile3D.cs" type="Script" id=1]
|
||||||
[ext_resource path="res://materials/DeepGrassTile.tres" type="Material" id=2]
|
[ext_resource path="res://materials/UndefinedTile.tres" type="Material" id=2]
|
||||||
|
|
||||||
[sub_resource type="CylinderMesh" id=6]
|
[sub_resource type="CylinderMesh" id=6]
|
||||||
top_radius = 0.5
|
top_radius = 0.5
|
||||||
|
|
|
@ -5,30 +5,29 @@ using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using GoDotLog;
|
using GoDotLog;
|
||||||
|
|
||||||
//using Dictionary = Godot.Collections.Dictionary;
|
|
||||||
|
|
||||||
public class StreamContainer : Spatial
|
public class StreamContainer : Spatial
|
||||||
{
|
{
|
||||||
// scene nodes
|
// scene nodes
|
||||||
private MeshInstance _bounds;
|
private MeshInstance _bounds;
|
||||||
private Spatial _activeTiles;
|
private Spatial _activeTiles;
|
||||||
private Queue<HexTile3D> _unusedTiles;
|
private Queue<HexTile3D> _unusedTiles;
|
||||||
|
private TileWorld _tileWorld;
|
||||||
|
|
||||||
// resources
|
// resources
|
||||||
private PackedScene _hexTileScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
|
private PackedScene _hexTileScene = GD.Load<PackedScene>("res://scenes/HexTile3D.tscn");
|
||||||
|
|
||||||
// exports
|
// exports
|
||||||
[Export] public Vector2 Dimensions = new Vector2(8, 4);
|
[Export] public Vector2 Dimensions = new Vector2(8, 4);
|
||||||
|
[Export] public NodePath World;
|
||||||
|
|
||||||
[Signal]
|
[Signal]
|
||||||
delegate void TileSelected(HexTile3D tile3d);
|
delegate void TileSelected(HexTile3D tile3d);
|
||||||
|
|
||||||
// other members
|
// other members
|
||||||
private Rect2 _worldRect;
|
private Rect2 _worldRect;
|
||||||
private Rect2 _currentOffsetCoordRect;
|
private Rect2 _currentOffsetCoordRect;
|
||||||
private Rect2 _oldOffsetCoordRect;
|
private Rect2 _oldOffsetCoordRect;
|
||||||
private HexGrid _hexGrid;
|
private HexGrid _hexGrid;
|
||||||
private Random _tileTypeRandom;
|
|
||||||
|
|
||||||
private Dictionary<Vector2, HexTile3D> _coordToTile = new Dictionary<Vector2, HexTile3D>();
|
private Dictionary<Vector2, HexTile3D> _coordToTile = new Dictionary<Vector2, HexTile3D>();
|
||||||
public List<Vector2> RemovedCoords = new List<Vector2>();
|
public List<Vector2> RemovedCoords = new List<Vector2>();
|
||||||
|
@ -39,19 +38,25 @@ public class StreamContainer : Spatial
|
||||||
get { return _currentOffsetCoordRect; }
|
get { return _currentOffsetCoordRect; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetWorld(TileWorld tileWorld)
|
||||||
|
{
|
||||||
|
_tileWorld = tileWorld;
|
||||||
|
}
|
||||||
|
|
||||||
// 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()
|
||||||
{
|
{
|
||||||
_unusedTiles = new Queue<HexTile3D>();
|
_unusedTiles = new Queue<HexTile3D>();
|
||||||
_bounds = GetNode<MeshInstance>("Bounds");
|
_bounds = GetNode<MeshInstance>("Bounds");
|
||||||
_activeTiles = GetNode<Spatial>("ActiveTiles");
|
_activeTiles = GetNode<Spatial>("ActiveTiles");
|
||||||
_tileTypeRandom = new Random();
|
|
||||||
|
|
||||||
_hexGrid = new HexGrid();
|
_hexGrid = new HexGrid();
|
||||||
|
|
||||||
Transform boundsTransform = Transform.Identity;
|
Transform boundsTransform = Transform.Identity;
|
||||||
boundsTransform = boundsTransform.Scaled(new Vector3(Dimensions.x, 1, Dimensions.y));
|
boundsTransform = boundsTransform.Scaled(new Vector3(Dimensions.x, 1, Dimensions.y));
|
||||||
_bounds.Transform = boundsTransform;
|
_bounds.Transform = boundsTransform;
|
||||||
|
|
||||||
|
_tileWorld = GetNode<TileWorld>(World);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,30 +92,30 @@ public class StreamContainer : Spatial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void UpdateTileCache()
|
public void UpdateTileCache()
|
||||||
{
|
{
|
||||||
RemovedCoords.Clear();
|
RemovedCoords.Clear();
|
||||||
AddedCoords.Clear();
|
AddedCoords.Clear();
|
||||||
_unusedTiles.Clear();
|
_unusedTiles.Clear();
|
||||||
|
|
||||||
Rect2 expandedRect = _currentOffsetCoordRect.Merge(_oldOffsetCoordRect).Grow(2);
|
Rect2 expandedRect = _currentOffsetCoordRect.Merge(_oldOffsetCoordRect).Grow(2);
|
||||||
Rect2 clippedRect = _currentOffsetCoordRect.Clip(_oldOffsetCoordRect);
|
Rect2 clippedRect = _currentOffsetCoordRect.Clip(_oldOffsetCoordRect);
|
||||||
|
|
||||||
MarkUnusedTiles(expandedRect, clippedRect);
|
MarkUnusedTiles(expandedRect, clippedRect);
|
||||||
AddNewTiles(expandedRect, clippedRect);
|
AddNewTiles(expandedRect, clippedRect);
|
||||||
|
|
||||||
foreach (HexTile3D tile3D in _unusedTiles.ToArray())
|
foreach (HexTile3D tile3D in _unusedTiles.ToArray())
|
||||||
{
|
{
|
||||||
RemovedCoords.Add(tile3D.OffsetCoords);
|
RemovedCoords.Add(tile3D.OffsetCoords);
|
||||||
_activeTiles.RemoveChild(tile3D);
|
_activeTiles.RemoveChild(tile3D);
|
||||||
tile3D.Disconnect("TileSelected", this, nameof(OnTileClicked));
|
tile3D.Disconnect("TileSelected", this, nameof(OnTileClicked));
|
||||||
tile3D.QueueFree();
|
tile3D.QueueFree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void MarkUnusedTiles(Rect2 expandedRect, Rect2 clippedRect)
|
public void MarkUnusedTiles(Rect2 expandedRect, Rect2 clippedRect)
|
||||||
{
|
{
|
||||||
foreach (int coord_x in Enumerable.Range(Mathf.FloorToInt(expandedRect.Position.x) - 5,
|
foreach (int coord_x in Enumerable.Range(Mathf.FloorToInt(expandedRect.Position.x) - 5,
|
||||||
Mathf.CeilToInt(expandedRect.Size.x) + 20))
|
Mathf.CeilToInt(expandedRect.Size.x) + 20))
|
||||||
|
@ -119,18 +124,19 @@ public class StreamContainer : Spatial
|
||||||
Mathf.CeilToInt(expandedRect.Size.y) + 20))
|
Mathf.CeilToInt(expandedRect.Size.y) + 20))
|
||||||
{
|
{
|
||||||
Vector2 coord = new Vector2(coord_x, coord_y);
|
Vector2 coord = new Vector2(coord_x, coord_y);
|
||||||
|
|
||||||
if (clippedRect.HasPoint(coord))
|
if (clippedRect.HasPoint(coord))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInCurrent = _currentOffsetCoordRect.HasPoint(coord);
|
bool isInCurrent = _currentOffsetCoordRect.HasPoint(coord);
|
||||||
bool isInOld = _oldOffsetCoordRect.HasPoint(coord);
|
bool isInOld = _oldOffsetCoordRect.HasPoint(coord);
|
||||||
|
|
||||||
if (isInOld && !isInCurrent && _coordToTile.Keys.Contains(coord))
|
if (isInOld && !isInCurrent && _coordToTile.Keys.Contains(coord))
|
||||||
{
|
{
|
||||||
HexTile3D tile3D = _coordToTile[coord];
|
HexTile3D tile3D = _coordToTile[coord];
|
||||||
|
tile3D.Type = HexTile3D.TileType.Undefined;
|
||||||
_unusedTiles.Enqueue(tile3D);
|
_unusedTiles.Enqueue(tile3D);
|
||||||
_coordToTile.Remove(coord);
|
_coordToTile.Remove(coord);
|
||||||
RemovedCoords.Add(coord);
|
RemovedCoords.Add(coord);
|
||||||
|
@ -159,10 +165,15 @@ public class StreamContainer : Spatial
|
||||||
AddedCoords.Add(coord);
|
AddedCoords.Add(coord);
|
||||||
HexTile3D tile3D = GetTile3dAt(coord);
|
HexTile3D tile3D = GetTile3dAt(coord);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HexTile3D tile3D = _unusedTiles.Dequeue();
|
HexTile3D tile3D = _unusedTiles.Dequeue();
|
||||||
tile3D.OffsetCoords = coord;
|
tile3D.OffsetCoords = coord;
|
||||||
|
tile3D.Type = _tileWorld.GetTileTypeAtOffset(coord);
|
||||||
|
Transform tileTransform = tile3D.Transform;
|
||||||
|
tileTransform.origin.y = _tileWorld.GetHeightAtOffset(coord);
|
||||||
|
tile3D.Transform = tileTransform;
|
||||||
|
|
||||||
_coordToTile[coord] = tile3D;
|
_coordToTile[coord] = tile3D;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,10 +191,10 @@ public class StreamContainer : Spatial
|
||||||
tile3D.Connect("TileSelected", this, nameof(OnTileClicked));
|
tile3D.Connect("TileSelected", this, nameof(OnTileClicked));
|
||||||
|
|
||||||
Transform tileTransform = tile3D.Transform;
|
Transform tileTransform = tile3D.Transform;
|
||||||
tileTransform.origin.y = GD.Randf() * 0.2f;
|
tileTransform.origin.y = _tileWorld.GetHeightAtOffset(offsetCoords);
|
||||||
tile3D.Transform = tileTransform;
|
tile3D.Transform = tileTransform;
|
||||||
|
tile3D.Type = _tileWorld.GetTileTypeAtOffset(offsetCoords);
|
||||||
tile3D.Type = HexTile3D.ValidTileTypes[_tileTypeRandom.Next(HexTile3D.ValidTileTypes.Length)];
|
|
||||||
_coordToTile[offsetCoords] = tile3D;
|
_coordToTile[offsetCoords] = tile3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public class TileWorld : Spatial
|
||||||
|
{
|
||||||
|
// signals
|
||||||
|
[Signal]
|
||||||
|
delegate void WorldGenerated();
|
||||||
|
|
||||||
|
// public members
|
||||||
|
public Image Heightmap;
|
||||||
|
public Vector2 Size = new Vector2(100, 100);
|
||||||
|
public float HeightScale = 10;
|
||||||
|
|
||||||
|
// private members
|
||||||
|
private HexGrid _hexGrid;
|
||||||
|
private Random _tileTypeRandom;
|
||||||
|
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_hexGrid = new HexGrid();
|
||||||
|
_tileTypeRandom = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Generate()
|
||||||
|
{
|
||||||
|
// GenerateSimpleMap();
|
||||||
|
GenerateNoiseMap();
|
||||||
|
|
||||||
|
EmitSignal("WorldGenerated");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void GenerateSimpleMap()
|
||||||
|
{
|
||||||
|
Heightmap = new Image();
|
||||||
|
Heightmap.Create((int)Size.x, (int)Size.y, false, Image.Format.Rf);
|
||||||
|
Heightmap.Lock();
|
||||||
|
|
||||||
|
foreach (int coord_x in Enumerable.Range(0, (int)Size.x))
|
||||||
|
{
|
||||||
|
foreach (int coord_y in Enumerable.Range(0, (int)Size.y))
|
||||||
|
{
|
||||||
|
SetHeightAtOffset(new Vector2(coord_x, coord_y), 0.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 = -1626828106;
|
||||||
|
noise_generator.Octaves = 3;
|
||||||
|
noise_generator.Period = 5;
|
||||||
|
noise_generator.Persistence = 0.5f;
|
||||||
|
noise_generator.Lacunarity = 2;
|
||||||
|
|
||||||
|
Heightmap.CopyFrom(noise_generator.GetImage((int)Size.x, (int)Size.y, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ApplyHeightMap()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsOffsetCoordValid(Vector2 offset_coord)
|
||||||
|
{
|
||||||
|
return ((int)Math.Clamp(offset_coord.x, 0, Size.x) == (int)offset_coord.x
|
||||||
|
&& (int)Math.Clamp(offset_coord.y, 0, Size.y) == (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Heightmap.SetPixel((int) offset_coord.x, (int) offset_coord.y, new Color(height / HeightScale, 0f, 0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetHeightAtOffset(Vector2 offset_coord)
|
||||||
|
{
|
||||||
|
if (!IsOffsetCoordValid(offset_coord))
|
||||||
|
{
|
||||||
|
return -0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Heightmap.GetPixel((int)offset_coord.x, (int)offset_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
// public override void _Process(float delta)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
|
@ -12,9 +12,9 @@ public class HexCellTests : TestClass
|
||||||
public void TestHexCellSimple()
|
public void TestHexCellSimple()
|
||||||
{
|
{
|
||||||
HexCell cell = new HexCell();
|
HexCell cell = new HexCell();
|
||||||
Debug.Assert(cell.CubeCoords == new Vector3(0, 0, 0));
|
Debug.Assert(cell.CubeCoords == new Vector3(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAxialCoords()
|
public void TestAxialCoords()
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ public class HexCellTests : TestClass
|
||||||
|
|
||||||
cell = new HexCell(new Vector3(-1, 2, -1));
|
cell = new HexCell(new Vector3(-1, 2, -1));
|
||||||
HexCell otherCell = cell;
|
HexCell otherCell = cell;
|
||||||
Debug.Assert(otherCell.AxialCoords == new Vector2(-1, 2));
|
Debug.Assert(otherCell.AxialCoords == new Vector2(-1, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -38,7 +38,7 @@ public class HexCellTests : TestClass
|
||||||
cell = new HexCell(new Vector2(4.2f, -5.5f));
|
cell = new HexCell(new Vector2(4.2f, -5.5f));
|
||||||
Debug.Assert(cell.CubeCoords == new Vector3(4, -5, 1));
|
Debug.Assert(cell.CubeCoords == new Vector3(4, -5, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestConversion()
|
public void TestConversion()
|
||||||
{
|
{
|
||||||
|
@ -53,7 +53,7 @@ public class HexCellTests : TestClass
|
||||||
HexCell cell = new HexCell();
|
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.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 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(-0.1f, 0.6f)) == new Vector3(0, 1, -1));
|
||||||
Debug.Assert(cell.RoundCoords(new Vector2(4.2f, -5.5f)) == new Vector3(4, -5, 1));
|
Debug.Assert(cell.RoundCoords(new Vector2(4.2f, -5.5f)) == new Vector3(4, -5, 1));
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class HexCellTests : TestClass
|
||||||
public void TestCoords()
|
public void TestCoords()
|
||||||
{
|
{
|
||||||
HexCell cell = new HexCell();
|
HexCell cell = new HexCell();
|
||||||
|
|
||||||
// from cubic positive
|
// from cubic positive
|
||||||
cell.CubeCoords = new Vector3(2, 1, -3);
|
cell.CubeCoords = new Vector3(2, 1, -3);
|
||||||
Debug.Assert(cell.CubeCoords == new Vector3(2, 1, -3));
|
Debug.Assert(cell.CubeCoords == new Vector3(2, 1, -3));
|
||||||
|
@ -74,7 +74,7 @@ public class HexCellTests : TestClass
|
||||||
Debug.Assert(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.AxialCoords == new Vector2(2, 1));
|
||||||
Debug.Assert(cell.OffsetCoords == new Vector2(2, 2));
|
Debug.Assert(cell.OffsetCoords == new Vector2(2, 2));
|
||||||
|
|
||||||
// from offset negative
|
// from offset negative
|
||||||
cell.OffsetCoords = new Vector2(-1, -2);
|
cell.OffsetCoords = new Vector2(-1, -2);
|
||||||
Debug.Assert(cell.CubeCoords == new Vector3(-1, -1, 2));
|
Debug.Assert(cell.CubeCoords == new Vector3(-1, -1, 2));
|
||||||
|
@ -86,7 +86,7 @@ public class HexCellTests : TestClass
|
||||||
public void TestNearby()
|
public void TestNearby()
|
||||||
{
|
{
|
||||||
HexCell cell = new HexCell(new Vector2(1, 2));
|
HexCell cell = new HexCell(new Vector2(1, 2));
|
||||||
|
|
||||||
// adjacent
|
// adjacent
|
||||||
HexCell otherCell = cell.getAdjacent(HexCell.DIR_N);
|
HexCell otherCell = cell.getAdjacent(HexCell.DIR_N);
|
||||||
Debug.Assert(otherCell.AxialCoords == new Vector2(1, 3));
|
Debug.Assert(otherCell.AxialCoords == new Vector2(1, 3));
|
||||||
|
@ -100,7 +100,7 @@ public class HexCellTests : TestClass
|
||||||
Debug.Assert(otherCell.AxialCoords == new Vector2(0, 2));
|
Debug.Assert(otherCell.AxialCoords == new Vector2(0, 2));
|
||||||
otherCell = cell.getAdjacent(HexCell.DIR_NW);
|
otherCell = cell.getAdjacent(HexCell.DIR_NW);
|
||||||
Debug.Assert(otherCell.AxialCoords == new Vector2(0, 3));
|
Debug.Assert(otherCell.AxialCoords == new Vector2(0, 3));
|
||||||
|
|
||||||
// not really adjacent
|
// not really adjacent
|
||||||
otherCell = cell.getAdjacent(new Vector3(-3, -3, 6));
|
otherCell = cell.getAdjacent(new Vector3(-3, -3, 6));
|
||||||
Debug.Assert(otherCell.AxialCoords == new Vector2(-2, -1));
|
Debug.Assert(otherCell.AxialCoords == new Vector2(-2, -1));
|
||||||
|
|
|
@ -14,10 +14,10 @@ public class HexGridTests : TestClass
|
||||||
HexGrid grid = new HexGrid();
|
HexGrid grid = new HexGrid();
|
||||||
float w = grid.HexSize.x;
|
float w = grid.HexSize.x;
|
||||||
float h = grid.HexSize.y;
|
float h = grid.HexSize.y;
|
||||||
|
|
||||||
Debug.Assert(grid.GetHexAt(new Vector2(0, 0)).AxialCoords == new Vector2(0, 0));
|
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, 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, 0));
|
||||||
Debug.Assert(grid.GetHexAt(new Vector2(w / 2 - 0.01f, h/2)).AxialCoords == new Vector2(1, -1));
|
Debug.Assert(grid.GetHexAt(new Vector2(w / 2 - 0.01f, h / 2)).AxialCoords == new Vector2(1, -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,53 +11,53 @@ public class SpringDamper
|
||||||
|
|
||||||
public SpringDamper(float osc_freq = 1.0f, float osc_red = 0.1f, float osc_red_h = 1.0f)
|
public SpringDamper(float osc_freq = 1.0f, float osc_red = 0.1f, float osc_red_h = 1.0f)
|
||||||
{
|
{
|
||||||
Debug.Assert(osc_red > 0.001 && osc_red < 0.999);
|
Debug.Assert(osc_red > 0.001 && osc_red < 0.999);
|
||||||
omega = osc_freq * 2 * Mathf.Pi;
|
omega = osc_freq * 2 * Mathf.Pi;
|
||||||
zeta = Mathf.Log(1.0f - osc_red) / (-omega * osc_red_h);
|
zeta = Mathf.Log(1.0f - osc_red) / (-omega * osc_red_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (float, float) Calc(float x, float v, float xt, float h)
|
public (float, float) Calc(float x, float v, float xt, float h)
|
||||||
{
|
{
|
||||||
float f = 1 + 2 * h * zeta * omega;
|
float f = 1 + 2 * h * zeta * omega;
|
||||||
float oo = omega * omega;
|
float oo = omega * omega;
|
||||||
float hoo = oo * h;
|
float hoo = oo * h;
|
||||||
float hhoo = hoo * h;
|
float hhoo = hoo * h;
|
||||||
|
|
||||||
float det_inv = 1.0f / (f + hhoo);
|
float det_inv = 1.0f / (f + hhoo);
|
||||||
float det_x = f * x + h * v + hhoo * xt;
|
float det_x = f * x + h * v + hhoo * xt;
|
||||||
float det_v = v + hoo * (xt - x);
|
float det_v = v + hoo * (xt - x);
|
||||||
|
|
||||||
return (det_x * det_inv, det_v * det_inv);
|
return (det_x * det_inv, det_v * det_inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (Vector3, Vector3) Calc(Vector3 x, Vector3 v, Vector3 xt, float h)
|
public (Vector3, Vector3) Calc(Vector3 x, Vector3 v, Vector3 xt, float h)
|
||||||
{
|
{
|
||||||
float f = 1 + 2 * h * zeta * omega;
|
float f = 1 + 2 * h * zeta * omega;
|
||||||
float oo = omega * omega;
|
float oo = omega * omega;
|
||||||
float hoo = oo * h;
|
float hoo = oo * h;
|
||||||
float hhoo = hoo * h;
|
float hhoo = hoo * h;
|
||||||
|
|
||||||
float det_inv = 1.0f / (f + hhoo);
|
float det_inv = 1.0f / (f + hhoo);
|
||||||
Vector3 det_x = f * x + h * v + hhoo * xt;
|
Vector3 det_x = f * x + h * v + hhoo * xt;
|
||||||
Vector3 det_v = v + hoo * (xt - x);
|
Vector3 det_v = v + hoo * (xt - x);
|
||||||
|
|
||||||
return (det_x * det_inv, det_v * det_inv);
|
return (det_x * det_inv, det_v * det_inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (Vector3, Vector3) CalcClampedSpeed(Vector3 x, Vector3 v, Vector3 xt, float h, float speedMax)
|
public (Vector3, Vector3) CalcClampedSpeed(Vector3 x, Vector3 v, Vector3 xt, float h, float speedMax)
|
||||||
{
|
{
|
||||||
var defaultResult = Calc(x, v, xt, h);
|
var defaultResult = Calc(x, v, xt, h);
|
||||||
|
|
||||||
Vector3 x_new = defaultResult.Item1;
|
Vector3 x_new = defaultResult.Item1;
|
||||||
Vector3 vel_new = (x_new - x) / h;
|
Vector3 vel_new = (x_new - x) / h;
|
||||||
float speed_new = vel_new.Length();
|
float speed_new = vel_new.Length();
|
||||||
|
|
||||||
if (speed_new > speedMax)
|
if (speed_new > speedMax)
|
||||||
{
|
{
|
||||||
vel_new = (vel_new / speed_new) * speedMax;
|
vel_new = (vel_new / speed_new) * speedMax;
|
||||||
x_new = x + vel_new * h;
|
x_new = x + vel_new * h;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (x_new, vel_new);
|
return (x_new, vel_new);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue