Started refactoring entity movement and structure.

WorldChunkRefactoring
Martin Felis 2022-12-28 21:57:34 +01:00
parent 041d580550
commit 385ed55505
10 changed files with 128 additions and 32 deletions

View File

@ -0,0 +1,28 @@
using Godot;
using System;
/// <summary>
/// </summary>
public class GroundMotionComponent
{
public float MaxSpeed = 3;
public void Process(float delta, Entity entity, Vector3 target_position)
{
Vector3 direction_xy = new Vector3(target_position.x - entity.GlobalTranslation.x,
0,
target_position.z - entity.GlobalTranslation.z);
Vector3 new_velocity = direction_xy.Normalized() * MaxSpeed;
new_velocity.y = entity.Velocity.y - 9.81f * delta;
if (direction_xy.LengthSquared() > 0.01)
{
entity.Velocity = entity.MoveAndSlide(new_velocity);
}
else
{
entity.Velocity = Vector3.Up * -9.81f * delta;
}
}
}

View File

@ -40,10 +40,6 @@ public class MovableComponent : Node
targetDir = targetError.Normalized();
targetAngle = new Vector3(0, 0, 1).SignedAngleTo(targetDir, Vector3.Up);
if (currentAngle < Mathf.Pi && targetAngle > Mathf.Pi)
{
}
if (targetAngle - currentAngle > Mathf.Pi)
{
currentAngle += 2 * Mathf.Pi;
@ -69,13 +65,16 @@ public class MovableComponent : Node
&& (targetPosition - currentPosition).LengthSquared() > 0.01)
{
var springDamperResult =
_positionSpringDamper.CalcClampedSpeed(currentPosition, currentVelocity, targetPosition, delta,
_positionSpringDamper.CalcClampedSpeedXZ(currentPosition, currentVelocity, targetPosition, delta,
maxSpeed);
currentPosition = springDamperResult.Item1;
currentVelocity = springDamperResult.Item2;
}
currentVelocity.y = currentVelocity.y - 9.81f * delta;
currentPosition.y = currentPosition.y + currentVelocity.y * delta;
EmitSignal("PositionUpdated", currentPosition);
}
}
}

20
entities/Entity.cs Normal file
View File

@ -0,0 +1,20 @@
using Godot;
using System;
public class Entity : KinematicBody
{
public Vector3 Position = Vector3.Zero;
public Quat Orientation = Quat.Identity;
public Vector3 Velocity = Vector3.Zero;
public float RotationalVelocity = 0;
public override void _Ready()
{
}
public override void _Process(float _delta)
{
Velocity = MoveAndSlide(Velocity);
}
}

View File

@ -1,21 +1,26 @@
using Godot;
using System;
public class Player : KinematicBody
public class Player : Entity
{
// other members
// public members
public Vector3 TargetPosition = Vector3.Zero;
// private members
private MovableComponent _movable;
private Spatial _geometry;
private WorldInfoComponent _worldInfo;
private Vector2 _offsetCoord = Vector2.Zero;
private GroundMotionComponent _groundMotion;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_groundMotion = new GroundMotionComponent();
_movable = (MovableComponent)FindNode("Movable", false);
if (_movable != null)
{
_movable.Connect("PositionUpdated", this, nameof(OnPositionUpdated));
_movable.Connect("OrientationUpdated", this, nameof(OnOrientationUpdated));
}
@ -24,11 +29,19 @@ public class Player : KinematicBody
_worldInfo = (WorldInfoComponent)FindNode("WorldInfo", false);
}
public override void _Process(float _delta)
{
base._Process(_delta);
_groundMotion.Process(_delta, this, TargetPosition);
}
public void OnPositionUpdated(Vector3 newPosition)
{
if (_worldInfo != null)
{
Vector2 new_offset_coord = _worldInfo.TileWorld.WorldToOffsetCoords(newPosition);
float tile_height = _worldInfo.TileWorld.GetHeightAtOffset(new_offset_coord);
if (_offsetCoord != new_offset_coord)
{
GD.Print("New offset coord " + new_offset_coord);
@ -38,8 +51,11 @@ public class Player : KinematicBody
if (_movable != null)
{
_movable.targetPosition.y = _worldInfo.TileWorld.GetHeightAtOffset(new_offset_coord);
if (_movable.currentPosition.y < tile_height)
{
_movable.currentPosition.y = tile_height;
_movable.currentVelocity.y = 0;
}
}
}

View File

@ -178,13 +178,14 @@ public class AdaptiveWorldStream : Spatial
return;
}
MovableComponent movableComponent = _player.GetNode<MovableComponent>("Movable");
if (movableComponent == null)
{
return;
}
movableComponent.targetPosition = tile.Transform.origin;
_player.TargetPosition = tile.GlobalTranslation;
// MovableComponent movableComponent = _player.GetNode<MovableComponent>("Movable");
// if (movableComponent == null)
// {
// return;
// }
//
// movableComponent.targetPosition = tile.Transform.origin;
}

View File

@ -21,7 +21,7 @@ albedo_color = Color( 1, 1, 1, 0.156863 )
extents = Vector3( 20, 1, 20 )
[sub_resource type="CapsuleShape" id=7]
radius = 0.2
radius = 0.475
height = 0.5
[sub_resource type="CapsuleMesh" id=8]
@ -221,13 +221,13 @@ script = ExtResource( 6 )
[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 )
visible = false
mesh = SubResource( 8 )
[node name="Movable" type="Node" parent="Player"]
script = ExtResource( 8 )
[node name="Geometry" type="Spatial" parent="Player"]
visible = false
[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 )

View File

@ -14,7 +14,7 @@ public class HexTile3D : Spatial
// scene nodes
private MeshInstance _mesh;
private Area _area;
private StaticBody _staticBody;
// signals
[Signal]
@ -87,11 +87,11 @@ public class HexTile3D : Spatial
public override void _Ready()
{
_mesh = GetNode<MeshInstance>("Mesh");
_area = GetNode<Area>("Mesh/Area");
_staticBody = GetNode<StaticBody>("StaticBody");
_area.Connect("input_event", this, nameof(OnAreaInputEvent));
_area.Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
_area.Connect("mouse_exited", this, nameof(OnAreaMouseExited));
_staticBody.Connect("input_event", this, nameof(OnAreaInputEvent));
_staticBody.Connect("mouse_entered", this, nameof(OnAreaMouseEntered));
_staticBody.Connect("mouse_exited", this, nameof(OnAreaMouseExited));
_undefinedMaterial = GD.Load<SpatialMaterial>("res://materials/UndefinedTile.tres");
_sandMaterial = GD.Load<SpatialMaterial>("res://materials/SandTile.tres");

View File

@ -22,10 +22,8 @@ transform = Transform( -4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, -5,
mesh = SubResource( 6 )
material/0 = ExtResource( 2 )
[node name="Area" type="Area" parent="Mesh"]
monitoring = false
monitorable = false
[node name="StaticBody" type="StaticBody" parent="."]
[node name="CollisionShape" type="CollisionShape" parent="Mesh/Area"]
transform = Transform( 1, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0 )
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
transform = Transform( -4.37114e-08, 0, 1, 0, 10, 0, -1, 0, -4.37114e-08, 0, -5, 0 )
shape = SubResource( 5 )

View File

@ -105,7 +105,7 @@ public class TileWorld : Spatial
{
if (!IsOffsetCoordValid(offset_coord))
{
return -0.1f;
return 0;
}
return Heightmap.GetPixel((int)offset_coord.x, (int)offset_coord.y).r * HeightScale - HeightScale * 0.5f ;

View File

@ -60,4 +60,38 @@ public class SpringDamper
return (x_new, vel_new);
}
public (Vector3, Vector3) CalcClampedSpeedXZ(Vector3 x, Vector3 v, Vector3 xt, float h, float speedMax)
{
var result_x = Calc(x.x, v.x, xt.x, h);
var result_z = Calc(x.z, v.z, xt.z, h);
Vector3 x_new = x;
Vector3 v_new = v;
x_new.x = result_x.Item1;
v_new.x = result_x.Item2;
x_new.z = result_z.Item1;
v_new.z = result_z.Item2;
Vector3 result_v_xz = new Vector3(
(result_x.Item1 - x.x) / h,
0,
(result_z.Item1 - x.z) / h);
float speed_new = result_v_xz.Length();
if (speed_new > speedMax)
{
result_v_xz = (result_v_xz) / speed_new * speedMax;
x_new.x = x.x + result_v_xz.x * h;
x_new.z = x.z + result_v_xz.z * h;
}
v.x = result_v_xz.x;
v.z = result_v_xz.z;
return (x_new, v_new);
}
}