This commit is contained in:
2025-01-08 05:05:04 +03:00
parent 3e73544666
commit 353117f97a
5 changed files with 132 additions and 13 deletions

View File

@@ -13,6 +13,11 @@ public class MovementComponent : Engine.Scene.Component.Component
/// </summary>
public float Speed { get; set; } = 10.0f;
/// <summary>
/// The rotation speed in degrees per second.
/// </summary>
public float RotationSpeed { get; set; } = 90.0f;
/// <summary>
/// The rigidbody component for the game object.
/// </summary>
@@ -40,4 +45,14 @@ public class MovementComponent : Engine.Scene.Component.Component
{
_rigidbody.Force += _dragComponent.Drag * Speed * parDirection.Normalized();
}
/// <summary>
/// Applies rotational torque to the object around a specified axis.
/// </summary>
/// <param name="parAxis">The axis of rotation.</param>
public void ApplyRotation(Vector3 parAxis)
{
var radiansPerSecond = MathHelper.DegreesToRadians(RotationSpeed);
_rigidbody.Torque += _dragComponent.RotationalDrag * radiansPerSecond * parAxis.Normalized();
}
}

View File

@@ -12,11 +12,21 @@ public class DragComponent : Engine.Scene.Component.Component
/// </summary>
public float Drag { get; set; } = 1f;
/// <summary>
/// The rotational drag coefficient applied to the angular velocity of the rigidbody.
/// </summary>
public float RotationalDrag { get; set; } = 1f;
/// <summary>
/// A multiplier applied to each axis of the velocity when calculating drag.
/// </summary>
public Vector3 Multiplier { get; set; } = Vector3.One;
/// <summary>
/// A multiplier applied to each axis of the angular velocity when calculating rotational drag.
/// </summary>
public Vector3 RotationalMultiplier { get; set; } = Vector3.One;
/// <summary>
/// The rigidbody to apply drag to.
/// </summary>
@@ -31,6 +41,12 @@ public class DragComponent : Engine.Scene.Component.Component
public override void Update(double parDeltaTime)
{
if (_rigidbody.IsStatic)
{
return;
}
_rigidbody.Force -= Drag * (_rigidbody.Velocity * Multiplier);
_rigidbody.Torque -= RotationalDrag * (_rigidbody.AngularVelocity * RotationalMultiplier);
}
}

View File

@@ -12,6 +12,12 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
/// </summary>
public float Mass { get; set; } = 1.0f;
/// <summary>
/// The moment of inertia of the rigidbody.
/// For simplicity, this assumes a scalar value, suitable for symmetric objects.
/// </summary>
public float MomentOfInertia { get; set; } = 1.0f;
/// <summary>
/// Indicates whether the rigidbody is static and unaffected by forces.
/// </summary>
@@ -34,6 +40,23 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
}
}
/// <summary>
/// The torque currently applied to the rigidbody.
/// </summary>
public Vector3 Torque
{
get => _torque;
set
{
if (IsStatic)
{
return;
}
_torque = value;
}
}
/// <summary>
/// The velocity of the rigidbody.
/// </summary>
@@ -51,6 +74,23 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
}
}
/// <summary>
/// The angular velocity of the rigidbody.
/// </summary>
public Vector3 AngularVelocity
{
get => _angularVelocity;
set
{
if (IsStatic)
{
return;
}
_angularVelocity = value;
}
}
/// <summary>
/// The force currently applied to the rigidbody.
/// </summary>
@@ -66,6 +106,21 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
/// </summary>
private Vector3 _velocity = Vector3.Zero;
/// <summary>
/// The torque currently applied to the rigidbody.
/// </summary>
private Vector3 _torque = Vector3.Zero;
/// <summary>
/// The angular acceleration of the rigidbody.
/// </summary>
private Vector3 _angularAcceleration = Vector3.Zero;
/// <summary>
/// The angular velocity of the rigidbody.
/// </summary>
private Vector3 _angularVelocity = Vector3.Zero;
public override void PostUpdate(double parDeltaTime)
{
if (IsStatic)
@@ -73,10 +128,43 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
return;
}
ApplyForce(parDeltaTime);
ApplyTorque(parDeltaTime);
}
/// <summary>
/// Applies force to the rigidbody.
/// </summary>
/// <param name="parDeltaTime">The time in seconds since the last update.</param>
private void ApplyForce(double parDeltaTime)
{
_acceleration = Force / Mass;
Velocity += _acceleration * (float)parDeltaTime;
GameObject.Transform.Translation += Velocity * (float)parDeltaTime;
Force = Vector3.Zero;
}
/// <summary>
/// Applies torque to the rigidbody.
/// </summary>
/// <param name="parDeltaTime">The time in seconds since the last update.</param>
private void ApplyTorque(double parDeltaTime)
{
_angularAcceleration = Torque / MomentOfInertia;
AngularVelocity += _angularAcceleration * (float)parDeltaTime;
// Update rotation using quaternion math
var rotation = GameObject.Transform.Rotation;
var angularVelocityQuat = new Quaternion(AngularVelocity, 0.0f);
// Quaternion rotation integration: Δq = 0.5 * angularVelocityQuat * rotation
var deltaRotation = 0.5f * angularVelocityQuat * rotation;
rotation += deltaRotation * (float)parDeltaTime;
rotation.Normalize(); // Ensure the quaternion remains normalized
GameObject.Transform.Rotation = rotation;
Torque = Vector3.Zero;
}
}

View File

@@ -10,11 +10,6 @@ namespace DoomDeathmatch.Component.Util;
/// </summary>
public class PlayerMovementComponent : Engine.Scene.Component.Component
{
/// <summary>
/// The speed at which the player rotates in degrees per second.
/// </summary>
public float RotationSpeed { get; set; } = 110.0f;
/// <summary>
/// Handles input from the player.
/// </summary>
@@ -35,7 +30,7 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component
public override void Update(double parDeltaTime)
{
var movement = Vector3.Zero;
var rotation = 0.0f;
var rotation = 0;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.W))
{
@@ -59,12 +54,12 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.Q))
{
rotation += RotationSpeed;
rotation = 1;
}
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.E))
{
rotation -= RotationSpeed;
rotation = -1;
}
if (movement.LengthSquared > 0)
@@ -75,7 +70,9 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component
_movementComponent.ApplyMovement(movement);
}
GameObject.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(rotation) *
(float)parDeltaTime);
if (rotation != 0)
{
_movementComponent.ApplyRotation(Vector3.UnitZ * rotation);
}
}
}

View File

@@ -19,7 +19,7 @@ public static class PlayerPrefab
perspectiveCameraObject.Transform.Translation.Z = 2;
var playerObject = GameObjectUtil.CreateGameObject(parScene, [
new RigidbodyComponent(),
new DragComponent { Drag = 10f, Multiplier = new Vector3(1, 1, 0) },
new DragComponent { Drag = 10f, RotationalDrag = 10f, },
new AABBColliderComponent
{
@@ -29,8 +29,11 @@ public static class PlayerPrefab
ExcludeColliderCollideGroups = { "player" }
},
new MovementComponent { Speed = GameConstants.PLAYER_BASE_SPEED },
new PlayerMovementComponent { RotationSpeed = GameConstants.PLAYER_BASE_ROTATION_SPEED },
new MovementComponent
{
Speed = GameConstants.PLAYER_BASE_SPEED, RotationSpeed = GameConstants.PLAYER_BASE_ROTATION_SPEED
},
new PlayerMovementComponent(),
new PlayerController(perspectiveCamera),