Compare commits
6 Commits
da09c66cb3
...
a0a3fea598
Author | SHA1 | Date |
---|---|---|
Martin Felis | a0a3fea598 | |
Martin Felis | d918da6fd6 | |
Martin Felis | aaa286bf77 | |
Martin Felis | c808739b78 | |
Martin Felis | d70d9cd682 | |
Martin Felis | 01fde34276 |
22
HexGrid.cs
22
HexGrid.cs
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using GodotComponentTest.utils;
|
||||
using Priority_Queue;
|
||||
using AxialCoordDirectionPair = System.Tuple<Godot.Vector2, Godot.Vector3>;
|
||||
|
||||
|
@ -22,7 +21,7 @@ public class HexGrid : Resource
|
|||
|
||||
|
||||
public float PathCostDefault = 1;
|
||||
public int FindPathCheckedCells = 0;
|
||||
public int FindPathCheckedCellCount;
|
||||
|
||||
public Vector2 HexSize
|
||||
{
|
||||
|
@ -76,11 +75,6 @@ public class HexGrid : Resource
|
|||
return result;
|
||||
}
|
||||
|
||||
public void SetBoundsOffset(Vector2 minOffset, Vector2 maxOffset)
|
||||
{
|
||||
SetBounds(HexCell.FromOffsetCoords(minOffset), HexCell.FromOffsetCoords(maxOffset));
|
||||
}
|
||||
|
||||
public void SetBounds(Vector2 minAxial, Vector2 maxAxial)
|
||||
{
|
||||
SetBounds(new HexCell(minAxial), new HexCell(maxAxial));
|
||||
|
@ -94,6 +88,13 @@ public class HexGrid : Resource
|
|||
(_maxCoords.AxialCoords - _minCoords.AxialCoords) + Vector2.One);
|
||||
}
|
||||
|
||||
public void SetBounds(HexCell center, int size)
|
||||
{
|
||||
Vector2 centerOffset = center.OffsetCoords;
|
||||
SetBounds(GetHexAtOffset(centerOffset - Vector2.One * size / 2),
|
||||
GetHexAtOffset(centerOffset + Vector2.One * size / 2));
|
||||
}
|
||||
|
||||
public void AddObstacle(Vector2 axialCoords, float cost = 0)
|
||||
{
|
||||
AddObstacle(new HexCell(axialCoords), cost);
|
||||
|
@ -221,11 +222,11 @@ public class HexGrid : Resource
|
|||
cameFrom.Add(startHex.AxialCoords, startHex.AxialCoords);
|
||||
costSoFar.Add(startHex.AxialCoords, 0);
|
||||
|
||||
FindPathCheckedCells = 0;
|
||||
FindPathCheckedCellCount = 0;
|
||||
|
||||
while (frontier.Any())
|
||||
{
|
||||
FindPathCheckedCells++;
|
||||
FindPathCheckedCellCount++;
|
||||
HexCell currentHex = new HexCell(frontier.Dequeue());
|
||||
Vector2 currentAxial = currentHex.AxialCoords;
|
||||
|
||||
|
@ -264,7 +265,7 @@ public class HexGrid : Resource
|
|||
}
|
||||
}
|
||||
|
||||
// GD.Print("Checked Cell Count: " + FindPathCheckedCells);
|
||||
// GD.Print("Checked Cell Count: " + FindPathCheckedCellCount);
|
||||
|
||||
List<HexCell> result = new List<HexCell>();
|
||||
if (!cameFrom.ContainsKey(goalHex.AxialCoords))
|
||||
|
@ -293,7 +294,6 @@ public class HexGrid : Resource
|
|||
{
|
||||
List<HexCell> result = new List<HexCell>();
|
||||
|
||||
HexCell toCell = GetHexAt(toPlane);
|
||||
float distance = (toPlane - fromPlane).Length();
|
||||
Vector2 direction = (toPlane - fromPlane) / distance;
|
||||
|
||||
|
|
|
@ -11,35 +11,58 @@ public class GroundMotionComponent : Component
|
|||
public float Accel = 50;
|
||||
public float Damping = 0.2f;
|
||||
public float MaxSpeed = 8;
|
||||
|
||||
|
||||
public float RotationSpeedRadPerSecond = 270 * Mathf.Pi / 180;
|
||||
|
||||
public Vector3 DirectionToTarget = Vector3.Zero;
|
||||
public float DistanceToTarget = 0;
|
||||
public float TargetAngle = 0;
|
||||
public float TargetDeltaAngle = 0;
|
||||
|
||||
|
||||
private void CalcAndApplyOrientation(float delta, Entity entity, Vector3 targetPosition, Quat targetOrientation)
|
||||
{
|
||||
float deltaAngleAbsolute = Mathf.Abs(TargetDeltaAngle);
|
||||
if (deltaAngleAbsolute > 0.001)
|
||||
{
|
||||
Transform entityTransform = entity.Transform;
|
||||
if (RotationSpeedRadPerSecond * delta + 0.001 >= deltaAngleAbsolute)
|
||||
{
|
||||
GD.Print("Target Angle " + TargetAngle + " reached! Current Angle: " + entity.PlaneAngle);
|
||||
entity.PlaneAngle = TargetAngle;
|
||||
TargetDeltaAngle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.PlaneAngle += Mathf.Sign(TargetDeltaAngle) * RotationSpeedRadPerSecond * delta;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetDeltaAngle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalcPlaneVelocity(float delta, Entity entity, Vector3 targetPosition)
|
||||
{
|
||||
Vector2 planeTargetVector = new Vector2(targetPosition.x - entity.GlobalTranslation.x,
|
||||
targetPosition.z - entity.GlobalTranslation.z);
|
||||
float targetDistance = planeTargetVector.Length();
|
||||
Vector2 planeTargetDirection = planeTargetVector / targetDistance;
|
||||
Vector2 planeOrientation = new Vector2(entity.GlobalTransform.basis.z[0], entity.GlobalTransform.basis.z[2]);
|
||||
Vector2 planeTargetDirection = new Vector2(DirectionToTarget.x, DirectionToTarget.z);
|
||||
|
||||
Vector2 planeVelocity = new Vector2(entity.Velocity.x, entity.Velocity.z);
|
||||
// GD.Print("-- Step: distance: " + targetDistance + " dir: " + planeTargetDirection + " speed: " + planeVelocity.Length() + " vel dir: " + planeVelocity.Normalized());
|
||||
planeVelocity -= planeVelocity * Damping;
|
||||
// GD.Print(" damp : speed: " + planeVelocity.Length() + " vel dir: " + planeVelocity.Normalized());
|
||||
|
||||
if (targetDistance < 0.01 || planeOrientation.Dot(planeTargetDirection) < 0.9)
|
||||
if (DistanceToTarget < 0.01)
|
||||
{
|
||||
planeVelocity = Vector2.Zero;
|
||||
} else {
|
||||
} else if (TargetDeltaAngle == 0.0) {
|
||||
planeVelocity = planeVelocity.Length() * planeTargetDirection + planeTargetDirection * Accel * delta;
|
||||
// GD.Print(" accel: speed: " + planeVelocity.Length() + " vel dir: " + planeVelocity.Normalized());
|
||||
|
||||
float projectedStep = planeTargetDirection.Dot(planeVelocity * delta);
|
||||
// GD.Print(" Projected step: " + projectedStep + " Speed: " + planeVelocity.Length() + " delta: " + delta);
|
||||
if (projectedStep > targetDistance)
|
||||
if (projectedStep > DistanceToTarget)
|
||||
{
|
||||
planeVelocity *= targetDistance / projectedStep;
|
||||
planeVelocity *= DistanceToTarget / projectedStep;
|
||||
projectedStep = planeTargetDirection.Dot(planeVelocity * delta);
|
||||
// GD.Print(" corr speed: " + planeVelocity.Length() + " step: " + projectedStep);
|
||||
}
|
||||
|
@ -50,6 +73,10 @@ public class GroundMotionComponent : Component
|
|||
planeVelocity *= MaxSpeed / planeSpeed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
planeVelocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
entity.Velocity = new Vector3(planeVelocity.x, entity.Velocity.y, planeVelocity.y);
|
||||
}
|
||||
|
@ -88,9 +115,30 @@ public class GroundMotionComponent : Component
|
|||
|
||||
public void PhysicsProcess(float delta, Entity entity, Vector3 targetPosition, Quat targetOrientation, TileWorld tileWorld)
|
||||
{
|
||||
DirectionToTarget = (targetPosition - entity.GlobalTranslation);
|
||||
DirectionToTarget.y = 0;
|
||||
DistanceToTarget = DirectionToTarget.Length();
|
||||
|
||||
if (DistanceToTarget >= Globals.EpsPosition)
|
||||
{
|
||||
DirectionToTarget = DirectionToTarget.Normalized();
|
||||
TargetAngle = Vector3.Right.SignedAngleTo(DirectionToTarget, Vector3.Up);
|
||||
TargetDeltaAngle = entity.CalcShortestPlaneRotationToTarget(targetPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.Print("Target Position reached!");
|
||||
DirectionToTarget = Vector3.Right;
|
||||
TargetAngle = entity.PlaneAngle;
|
||||
TargetDeltaAngle = 0;
|
||||
entity.GlobalTranslation = targetPosition;
|
||||
entity.Velocity = new Vector3(0, entity.Velocity.y, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
CalcAndApplyOrientation(delta, entity, targetPosition, targetOrientation);
|
||||
CalcPlaneVelocity(delta, entity, targetPosition);
|
||||
CalcVerticalVelocity(delta, entity, tileWorld);
|
||||
// CalcVerticalVelocity(delta, entity, tileWorld);
|
||||
|
||||
entity.Velocity = entity.MoveAndSlide(entity.Velocity);
|
||||
|
||||
|
@ -98,38 +146,4 @@ public class GroundMotionComponent : Component
|
|||
//GD.Print("Post: speed: " + entity.Velocity.Length() + " Velocity: " + entity.Velocity);
|
||||
}
|
||||
|
||||
private void CalcAndApplyOrientation(float delta, Entity entity, Vector3 targetPosition, Quat targetOrientation)
|
||||
{
|
||||
Vector3 direction_to_target = targetPosition - entity.GlobalTranslation;
|
||||
|
||||
if (direction_to_target.LengthSquared() > Globals.EpsPositionSquared)
|
||||
{
|
||||
direction_to_target = direction_to_target.Normalized();
|
||||
Vector3 localXAxis = Vector3.Up.Cross(direction_to_target);
|
||||
targetOrientation = new Basis(localXAxis, Vector3.Up, direction_to_target).Quat().Normalized();
|
||||
}
|
||||
|
||||
float orientationErrorRadians = entity.GlobalTransform.basis.Quat().AngleTo(targetOrientation);
|
||||
if (Mathf.Abs(orientationErrorRadians) > Mathf.Pi * 1.1)
|
||||
{
|
||||
GD.Print("moep");
|
||||
}
|
||||
if (orientationErrorRadians > 0)
|
||||
{
|
||||
Transform entityTransform = entity.Transform;
|
||||
if (orientationErrorRadians < RotationSpeedRadPerSecond * delta)
|
||||
{
|
||||
entityTransform.basis = new Basis(targetOrientation);
|
||||
}
|
||||
else if (orientationErrorRadians > 0f)
|
||||
{
|
||||
Quat entityRotation = new Quat(entityTransform.basis);
|
||||
float slerpWeight = RotationSpeedRadPerSecond / (orientationErrorRadians / delta);
|
||||
entityRotation = entityRotation.Slerp(targetOrientation, slerpWeight).Normalized();
|
||||
entityTransform.basis = new Basis(entityRotation);
|
||||
}
|
||||
|
||||
entity.Transform = entityTransform;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -79,6 +79,7 @@ public class NavigationComponent : Spatial
|
|||
|
||||
private NavigationPoint _currentGoal;
|
||||
private Vector3 _currentGoalPositionWorld = Vector3.Zero;
|
||||
private float _currentGoalAngleWorld = 0;
|
||||
private Quat _currentGoalOrientationWorld = Quat.Identity;
|
||||
|
||||
private List<NavigationPoint> _planningPathWorldNavigationPoints = new List<NavigationPoint>();
|
||||
|
@ -140,6 +141,7 @@ public class NavigationComponent : Spatial
|
|||
return;
|
||||
}
|
||||
|
||||
TileWorld.HexGrid.SetBounds(fromCell, 40);
|
||||
List<HexCell> path = TileWorld.HexGrid.FindPath(fromCell, toCell);
|
||||
|
||||
// Generate grid navigation points
|
||||
|
@ -151,7 +153,7 @@ public class NavigationComponent : Spatial
|
|||
}
|
||||
|
||||
// Ensure the last point coincides with the target position
|
||||
if ((_planningPathWorldNavigationPoints.Last().WorldPosition - toPositionWorld).LengthSquared() <
|
||||
if (_planningPathWorldNavigationPoints.Count > 0 && (_planningPathWorldNavigationPoints.Last().WorldPosition - toPositionWorld).LengthSquared() <
|
||||
0.5f * 0.5f)
|
||||
{
|
||||
_planningPathWorldNavigationPoints[_planningPathWorldNavigationPoints.Count - 1].WorldPosition = toPositionWorld;
|
||||
|
@ -159,6 +161,7 @@ public class NavigationComponent : Spatial
|
|||
|
||||
// Perform smoothing
|
||||
_planningPathSmoothedWorldNavigationPoints = SmoothPath(body, _planningPathWorldNavigationPoints);
|
||||
_planningPathSmoothedWorldNavigationPoints[0] = new NavigationPoint(fromPositionWorld);
|
||||
}
|
||||
|
||||
public void FindPath(KinematicBody body, Vector3 fromPositionWorld, NavigationPoint navigationPoint)
|
||||
|
@ -398,7 +401,7 @@ public class NavigationComponent : Spatial
|
|||
|
||||
_currentGoal = _pathWorldNavigationPoints[0];
|
||||
_currentGoalPositionWorld = _pathWorldNavigationPoints[0].WorldPosition;
|
||||
_currentGoalOrientationWorld = _pathWorldNavigationPoints[0].WorldOrientation;
|
||||
//_currentGoalOrientationWorld = Vector3.Right.SignedAngleTo(_pathWorldNavigationPoints[0].WorldOrientation);
|
||||
|
||||
// GD.Print("Navigation Goal: pos " + _currentGoal.WorldPosition + " " + " rot: " + _currentGoal.WorldOrientation +
|
||||
// " flags: " + _currentGoal.Flags + " path length: " +
|
||||
|
|
|
@ -6,6 +6,23 @@ public class Entity : KinematicBody
|
|||
public Vector3 Velocity { get; set; } = Vector3.Zero;
|
||||
public float RotationalVelocity { get; set; } = 0;
|
||||
|
||||
/** Defines the angle in plane coordinates, 0 => pointing to the right/east, pi/2 pointing up/north, range [-pi,pi]. */
|
||||
public float PlaneAngle
|
||||
{
|
||||
get => GlobalTransform.basis.x.SignedAngleTo(Vector3.Right.Rotated(Vector3.Up, Mathf.Pi * 0.5f), -Vector3.Up);
|
||||
set => GlobalTransform = new Transform(new Basis(Vector3.Up, value + Mathf.Pi * 0.5f), GlobalTranslation);
|
||||
}
|
||||
|
||||
public float CalcShortestPlaneRotationToTarget(Vector3 globalTargetPosition)
|
||||
{
|
||||
float angleToTarget = Vector3.Right.SignedAngleTo(globalTargetPosition - GlobalTranslation, Vector3.Up);
|
||||
float currentAngle = PlaneAngle;
|
||||
|
||||
float delta = angleToTarget - currentAngle;
|
||||
delta += (delta > Mathf.Pi) ? -Mathf.Pi * 2 : (delta < -Mathf.Pi) ? Mathf.Pi * 2 : 0;
|
||||
return delta;
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -6,4 +6,6 @@
|
|||
[resource]
|
||||
shader = ExtResource( 2 )
|
||||
shader_param/TextureSize = 4
|
||||
shader_param/CoordinateOffsetU = null
|
||||
shader_param/CoordinateOffsetV = null
|
||||
shader_param/MapAlbedoTexture = ExtResource( 1 )
|
||||
|
|
|
@ -4,3 +4,11 @@
|
|||
|
||||
[resource]
|
||||
shader = ExtResource( 1 )
|
||||
shader_param/DeepWaterColor = Color( 0, 0, 0.6, 1 )
|
||||
shader_param/WaterColor = Color( 0, 0, 0.7, 1 )
|
||||
shader_param/LightWaterColor = Color( 0, 0, 1, 1 )
|
||||
shader_param/SandColor = Color( 0.8, 0.8, 0.1, 1 )
|
||||
shader_param/GrassColor = Color( 0, 0.6, 0, 1 )
|
||||
shader_param/ForestColor = Color( 0, 0.4, 0, 1 )
|
||||
shader_param/RockColor = Color( 0.5, 0.5, 0.4, 1 )
|
||||
shader_param/SnowColor = Color( 1, 1, 1, 1 )
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
[ext_resource path="res://materials/shader/IslandHeightmapFalloffShader.gdshader" type="Shader" id=1]
|
||||
|
||||
[resource]
|
||||
render_priority = -1
|
||||
shader = ExtResource( 1 )
|
||||
|
|
|
@ -3,6 +3,8 @@ render_mode specular_schlick_ggx, async_visible;
|
|||
|
||||
uniform sampler2D MapAlbedoTexture : hint_black_albedo;
|
||||
uniform int TextureSize: hint_range(0, 1024, 4);
|
||||
uniform int CoordinateOffsetU: hint_range(-32000, 32000);
|
||||
uniform int CoordinateOffsetV: hint_range(-32000, 32000);
|
||||
varying vec2 map_coord;
|
||||
|
||||
const mat2 _HexAffineInverse = mat2(vec2(1.333333, -0.6666667), vec2(0, -1.154701));
|
||||
|
@ -41,13 +43,12 @@ void vertex() {
|
|||
vec3 origin = vec4(WORLD_MATRIX * vec4(0, 0, 0, 1)).xyz;
|
||||
vec3 axial_coords = vec3(_HexAffineInverse * origin.xz, 0);
|
||||
|
||||
map_coord = axial_to_offset(axial_coords.xy);
|
||||
map_coord = axial_to_offset(axial_coords.xy) - vec2(ivec2(CoordinateOffsetU, CoordinateOffsetV));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
float size = float(TextureSize);
|
||||
vec2 texel_offset = vec2(ceil(size / 2.0));
|
||||
ivec2 texel_coord = ivec2(mod(map_coord.xy - texel_offset, vec2(size)));
|
||||
ivec2 texel_coord = ivec2(mod(map_coord.xy, vec2(size)));
|
||||
vec4 texel_value = texelFetch(MapAlbedoTexture, texel_coord, 0);
|
||||
|
||||
ALBEDO = texelFetch(MapAlbedoTexture, texel_coord, 0).rgb;
|
||||
|
|
|
@ -1,28 +1,38 @@
|
|||
shader_type canvas_item;
|
||||
render_mode skip_vertex_transform;
|
||||
|
||||
uniform vec4 DeepWaterColor : hint_color = vec4(0, 0, 0.6, 1);
|
||||
uniform vec4 WaterColor : hint_color = vec4(0, 0, 0.7, 1);
|
||||
uniform vec4 LightWaterColor : hint_color = vec4(0, 0, 1, 1);
|
||||
uniform vec4 SandColor : hint_color = vec4(0.8, 0.8, 0.1, 1);
|
||||
uniform vec4 GrassColor : hint_color = vec4(0, 0.6, 0, 1);
|
||||
uniform vec4 ForestColor : hint_color = vec4(0, 0.4, 0, 1);
|
||||
uniform vec4 RockColor : hint_color = vec4(0.5, 0.5, 0.4, 1);
|
||||
uniform vec4 SnowColor : hint_color = vec4(1);
|
||||
uniform sampler2D TextureMask : hint_albedo;
|
||||
|
||||
void vertex() {
|
||||
VERTEX = (WORLD_MATRIX * (EXTRA_MATRIX * vec4(VERTEX, 0.0, 1.0))).xy;
|
||||
}
|
||||
|
||||
vec3 color_ramp(float h) {
|
||||
if (h < 0.4f) {
|
||||
return vec3(0, 0, 0.6);
|
||||
if (h < 0.1f) {
|
||||
return DeepWaterColor.rgb;
|
||||
} else if (h < 0.12f) {
|
||||
return WaterColor.rgb;
|
||||
} else if (h < 0.45f) {
|
||||
return vec3(0, 0, 0.7);
|
||||
} else if (h < 0.5f) {
|
||||
return vec3(0, 0, 1);
|
||||
} else if (h < 0.55){
|
||||
return vec3(0.8, 0.8, 0.1);
|
||||
} else if (h < 0.6){
|
||||
return vec3(0, 0.6, 0);
|
||||
} else if (h < 0.78){
|
||||
return vec3(0, 0.4, 0);
|
||||
return LightWaterColor.rgb;
|
||||
// } else if (h < 0.25){
|
||||
// return SandColor.rgb;
|
||||
} else if (h < 0.75){
|
||||
return GrassColor.rgb;
|
||||
// } else if (h < 0.78){
|
||||
// return ForestColor.rgb;
|
||||
} else if (h < 1.0){
|
||||
return vec3(0.5, 0.5, 0.4);
|
||||
return RockColor.rgb;
|
||||
}
|
||||
|
||||
return vec3(1.0);
|
||||
return SnowColor.rgb;
|
||||
}
|
||||
|
||||
vec3 rgbToGrayscale(vec3 color) {
|
||||
|
@ -42,9 +52,11 @@ float borderFalloffCircle(vec2 uv) {
|
|||
void fragment() {
|
||||
vec4 texture_color = texture(TEXTURE, UV);
|
||||
|
||||
|
||||
COLOR.rgb = vec3(abs(UV.x - 0.5) * 2.0);
|
||||
//COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
|
||||
COLOR.rgb = color_ramp(texture_color.r);
|
||||
|
||||
// COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
|
||||
COLOR.rgb = color_ramp(texture_color.r * texture(TextureMask, UV).r);
|
||||
COLOR.a = 0.8;
|
||||
// COLOR.rgb = vec3(1, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ public class Game : Spatial
|
|||
_player.Connect("GoldCountChanged", this, nameof(OnGoldCountChanged));
|
||||
_worldView.Connect("TileClicked", this, nameof(OnTileClicked));
|
||||
_worldView.Connect("TileHovered", this, nameof(OnTileHovered));
|
||||
_worldView.Connect("OnWorldViewTileTypeImageChanged", this, nameof(OnWorldViewTileTypeImageChanged));
|
||||
|
||||
// register entity events
|
||||
foreach (Node node in GetNode("Entities").GetChildren())
|
||||
|
@ -356,6 +357,20 @@ public class Game : Spatial
|
|||
_heightTextureRect.Texture = newHeightTexture;
|
||||
}
|
||||
|
||||
private void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage)
|
||||
{
|
||||
ImageTexture newWorldTexture = new ImageTexture();
|
||||
newWorldTexture.CreateFromImage(viewTileTypeImage,
|
||||
(uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
|
||||
|
||||
_worldTextureRect.Texture = newWorldTexture;
|
||||
|
||||
_tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture);
|
||||
_tileMaterial.SetShaderParam("TextureSize", (int)newWorldTexture.GetSize().x);
|
||||
_tileMaterial.SetShaderParam("CoordinateOffsetU", (int) _worldView.WorldTextureCoordinateOffset.x);
|
||||
_tileMaterial.SetShaderParam("CoordinateOffsetV", (int) _worldView.WorldTextureCoordinateOffset.y);
|
||||
}
|
||||
|
||||
public void OnGoldCountChanged(int goldCount)
|
||||
{
|
||||
AnimationPlayer animationPlayer = _gameUi.GetNode<AnimationPlayer>("AnimationPlayer");
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[ext_resource path="res://scenes/TileWorld.tscn" type="PackedScene" id=8]
|
||||
[ext_resource path="res://scenes/Game.cs" type="Script" id=9]
|
||||
[ext_resource path="res://scenes/WorldView.cs" type="Script" id=10]
|
||||
[ext_resource path="res://entities/Chest.tscn" type="PackedScene" id=11]
|
||||
[ext_resource path="res://ui/WorldGeneratorUI.gd" type="Script" id=12]
|
||||
[ext_resource path="res://entities/Axe.tscn" type="PackedScene" id=14]
|
||||
[ext_resource path="res://systems/InteractionSystem.cs" type="Script" id=15]
|
||||
|
@ -355,9 +356,13 @@ parameters/playback = SubResource( 26 )
|
|||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.79762, 0, 0 )
|
||||
input_ray_pickable = false
|
||||
|
||||
[node name="Chest" parent="Entities" instance=ExtResource( 11 )]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -3.27709, 0, 1.02593 )
|
||||
|
||||
[node name="WorldView" type="Spatial" parent="."]
|
||||
script = ExtResource( 10 )
|
||||
World = NodePath("../World")
|
||||
ShowHexTiles = true
|
||||
|
||||
[node name="World" type="Spatial" parent="."]
|
||||
script = ExtResource( 7 )
|
||||
|
|
|
@ -16,12 +16,15 @@ public class World : Spatial
|
|||
Done
|
||||
}
|
||||
public GenerationState State = GenerationState.Done;
|
||||
public Vector2 CenterChunkIndex = Vector2.Zero;
|
||||
|
||||
// referenced scenes
|
||||
private PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
|
||||
|
||||
// constants
|
||||
public const int ChunkSize = 16;
|
||||
public const int NumChunkRows = 3;
|
||||
public const int NumChunkColumns = NumChunkRows;
|
||||
public int Seed = 0;
|
||||
public HexGrid HexGrid = new HexGrid();
|
||||
public Spatial Chunks;
|
||||
|
@ -44,10 +47,7 @@ public class World : Spatial
|
|||
|
||||
// other members
|
||||
private Vector2 _centerPlaneCoord;
|
||||
private int[] _centerChunkCoord = { 0, 0 };
|
||||
private int[] _previousCenterChunkCoord = { 0, 0 };
|
||||
private Rect2 _centerChunkRect = new Rect2();
|
||||
private Random _debugColorRandom = new Random();
|
||||
private Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
|
||||
private List<Vector2> _activeChunkIndices = new();
|
||||
private List<Vector2> _addedChunkIndices = new();
|
||||
|
@ -141,6 +141,8 @@ public class World : Spatial
|
|||
|
||||
// set new center chunk
|
||||
var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
|
||||
CenterChunkIndex = new Vector2(chunkIndex.Item1, chunkIndex.Item2);
|
||||
|
||||
WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
|
||||
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||
_centerChunkRect = currentChunk.PlaneRect;
|
||||
|
@ -159,6 +161,8 @@ public class World : Spatial
|
|||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1, chunkIndex.Item2 + 1));
|
||||
_activeChunkIndices.Add(new Vector2(chunkIndex.Item1 + 1, chunkIndex.Item2 + 1));
|
||||
|
||||
Debug.Assert(_activeChunkIndices.Count == NumChunkRows * NumChunkColumns);
|
||||
|
||||
foreach(Vector2 activeChunkIndex in _activeChunkIndices)
|
||||
{
|
||||
GetOrCreateWorldChunk((int) activeChunkIndex.x, (int) activeChunkIndex.y, new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||
|
|
|
@ -19,10 +19,25 @@ public class WorldChunk : Spatial
|
|||
[Export] public Texture NavigationMap;
|
||||
[Export] public Texture HeightMap;
|
||||
[Export] public int Size = 32;
|
||||
|
||||
[Export] public Vector2 ChunkAddress;
|
||||
// [Export] public Vector2 Size = new Vector2(1, 1);
|
||||
|
||||
[Export]
|
||||
public bool ShowTextureOverlay
|
||||
{
|
||||
get
|
||||
{
|
||||
return _showTextureOverlay;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (PlaneRectMesh != null)
|
||||
{
|
||||
PlaneRectMesh.Visible = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// signals
|
||||
// delegate void OnCoordClicked(Vector2 world_pos);
|
||||
|
||||
|
@ -34,6 +49,7 @@ public class WorldChunk : Spatial
|
|||
|
||||
private TextureRect _heightmapRect;
|
||||
private SpatialMaterial _rectMaterial = new SpatialMaterial();
|
||||
private bool _showTextureOverlay = false;
|
||||
|
||||
public WorldChunk()
|
||||
{
|
||||
|
@ -78,6 +94,10 @@ public class WorldChunk : Spatial
|
|||
{
|
||||
PlaneRectMesh = (MeshInstance)FindNode("PlaneRectMesh");
|
||||
Debug.Assert(PlaneRectMesh != null);
|
||||
if (PlaneRectMesh.Visible)
|
||||
{
|
||||
_showTextureOverlay = true;
|
||||
}
|
||||
|
||||
Transform planeRectTransform = Transform.Identity;
|
||||
planeRectTransform =
|
||||
|
|
|
@ -32,6 +32,7 @@ script = ExtResource( 1 )
|
|||
|
||||
[node name="PlaneRectMesh" type="MeshInstance" parent="."]
|
||||
transform = Transform( 2, 0, 0, 0, 0.125, 0, 0, 0, 2, 0, -0.1, 0 )
|
||||
visible = false
|
||||
mesh = SubResource( 27 )
|
||||
material/0 = SubResource( 28 )
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System.Linq;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using Vector2 = Godot.Vector2;
|
||||
using Vector3 = Godot.Vector3;
|
||||
|
||||
public class WorldView : Spatial
|
||||
{
|
||||
|
@ -13,15 +15,22 @@ public class WorldView : Spatial
|
|||
// exports
|
||||
[Export] public NodePath World;
|
||||
[Export] public Vector2 ViewCenterPlaneCoord;
|
||||
[Export] public bool ShowHexTiles = false;
|
||||
|
||||
// signals
|
||||
[Signal]
|
||||
delegate void TileClicked(HexTile3D tile3d);
|
||||
[Signal]
|
||||
delegate void TileHovered(HexTile3D tile3d);
|
||||
[Signal]
|
||||
delegate void OnWorldViewTileTypeImageChanged(Image viewTileTypeImage);
|
||||
|
||||
// other members
|
||||
public Vector2 WorldTextureCoordinateOffset = Vector2.Zero;
|
||||
|
||||
private World _world;
|
||||
private ImageTexture _viewTileTypeTexture;
|
||||
private Image _viewTileTypeImage = new();
|
||||
|
||||
private class SceneTileChunk : Spatial
|
||||
{
|
||||
|
@ -118,6 +127,42 @@ public class WorldView : Spatial
|
|||
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)
|
||||
{
|
||||
Array<SceneTileChunk> removedChunks = new();
|
||||
|
@ -147,9 +192,21 @@ public class WorldView : Spatial
|
|||
}
|
||||
|
||||
sceneTileChunk.ChunkIndex = chunkIndex;
|
||||
|
||||
if (ShowHexTiles)
|
||||
{
|
||||
foreach (HexTile3D tile3D in sceneTileChunk.TileNodes)
|
||||
{
|
||||
tile3D.Transform = new Transform(Basis.Identity.Scaled(Vector3.One * 0.95f),
|
||||
tile3D.Transform.origin);
|
||||
}
|
||||
}
|
||||
|
||||
_sceneTileChunks.Add(sceneTileChunk);
|
||||
}
|
||||
|
||||
UpdateWorldViewTexture();
|
||||
|
||||
GD.Print("Removed Chunks " + removedChunkIndices.Count);
|
||||
GD.Print("Added Chunks " + addedChunkIndices.Count);
|
||||
GD.Print("Removed chunk count: " + removedChunks.Count);
|
||||
|
|
Loading…
Reference in New Issue