Files
Prism/ExampleApp/Src/FPSPlayer.cs

170 lines
6.2 KiB
C#

using System.Runtime.InteropServices;
using Prism;
namespace FPSExample
{
public class FPSPlayer : Entity
{
public float WalkingSpeed = 10.0f;
public float RunSpeed = 20.0f;
public float JumpForce = 50.0f;
[NonSerialized]
public float MouseSensitivity = 10.0f;
public float CameraForwardOffset = 0.5f;
public float CameraYOffset = 0.5f;
private bool m_Colliding = false;
private float m_CurrentSpeed;
private RigidBodyComponent m_RigidBody;
private TransformComponent m_Transform;
private TransformComponent m_CameraTransform;
private Entity m_CameraEntity;
private Vec2 m_LastMousePosition;
private float m_CurrentYMovement = 0.0f;
private Vec2 m_MovementDirection = new Vec2(0.0f);
private bool m_ShouldJump = false;
void OnCreate()
{
m_Transform = GetComponent<TransformComponent>();
m_RigidBody = GetComponent<RigidBodyComponent>();
m_CurrentSpeed = WalkingSpeed;
AddCollisionBeginCallback((n) => { m_Colliding = true; });
AddCollisionEndCallback((n) => { m_Colliding = false; });
m_CameraEntity = FindEntityByTag("Camera");
m_CameraTransform = m_CameraEntity.GetComponent<TransformComponent>();
m_LastMousePosition = Input.GetMousePosition();
Input.SetCursorMode(Input.CursorMode.Locked);
int size = Marshal.SizeOf<Transform>();
Console.WriteLine($"C# size of Transform: {size}");
}
void OnUpdate(float ts)
{
if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked)
Input.SetCursorMode(Input.CursorMode.Normal);
if(Input.IsMouseButtonPressed(Input.MouseButton.Left) && Input.GetCursorMode() == Input.CursorMode.Normal)
Input.SetCursorMode(Input.CursorMode.Locked);
m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed;
UpdateRayCasting();
UpdateMovementInput();
UpdateRotation(ts);
UpdateCameraTransform();
}
private void UpdateRotation(float ts)
{
Vec2 currentMousePosition = Input.GetMousePosition();
Vec2 delta = m_LastMousePosition - currentMousePosition;
float m_CurrentYMovement = delta.X * MouseSensitivity * ts;
float xRotation = delta.Y * MouseSensitivity * ts;
m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
if (delta.X != 0 || delta.Y != 0)
{
m_CameraTransform.Rotation += new Vec3(xRotation, m_CurrentYMovement, 0.0f);
}
m_CameraTransform.Rotation = new Vec3(Mathf.Clamp(m_CameraTransform.Rotation.X, -89.0f, 89.0f), m_CameraTransform.Rotation.YZ);
m_LastMousePosition = currentMousePosition;
}
private void UpdateMovementInput()
{
if (Input.IsKeyPressed(KeyCode.W))
m_MovementDirection.Y += 1.0f;
else if (Input.IsKeyPressed(KeyCode.S))
m_MovementDirection.Y -= 1.0f;
else
m_MovementDirection.Y = 0.0f;
if(Input.IsKeyPressed(KeyCode.A))
m_MovementDirection.X -= 1.0f;
else if (Input.IsKeyPressed(KeyCode.D))
m_MovementDirection.X += 1.0f;
else
m_MovementDirection.X = 0.0f;
m_ShouldJump = Input.IsKeyPressed(KeyCode.Space) && !m_ShouldJump;
}
Collider[] colliders = new Collider[10];
private void UpdateRayCasting()
{
RaycastHit hitInfo;
if (Input.IsKeyPressed(KeyCode.H) &&
Physics.Raycast(m_CameraTransform.Translation + (m_CameraTransform.Transform.Forward),
m_CameraTransform.Transform.Forward, 20.0f, out hitInfo))
{
FindEntityByID(hitInfo.EntityID).GetComponent<MeshComponent>().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f));
}
if (Input.IsKeyPressed(KeyCode.I))
{
// NOTE: The NonAlloc version of Overlap functions should be used when possible since it doesn't allocate a new array
// whenever you call it. The normal versions allocates a brand new array every time.
int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Translation, new Vec3(1.0f), colliders);
Console.WriteLine("Colliders: {0}", numColliders);
// When using NonAlloc it's not safe to use a foreach loop since some of the colliders may not exist
for (int i = 0; i < numColliders; i++)
{
Console.WriteLine(colliders[i]);
}
}
}
void OnPhysicsUpdate(float fixedTimeStep)
{
UpdateMovement();
}
private void UpdateMovement()
{
m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f));
Vec3 movement = m_CameraTransform.Transform.Right * m_MovementDirection.X + m_CameraTransform.Transform.Forward * m_MovementDirection.Y;
if (m_MovementDirection.LengthSquared() != 0.0f)
{
movement.Normalize();
Vec3 velocity = movement * m_CurrentSpeed;
velocity.Y = m_RigidBody.GetLinearVelocity().Y;
m_RigidBody.SetLinearVelocity(velocity);
}
if (m_ShouldJump && m_Colliding)
{
m_RigidBody.AddForce(Vec3.Up * JumpForce, RigidBodyComponent.ForceMode.Impulse);
m_ShouldJump = false;
}
}
private void UpdateCameraTransform(){
Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset;
position.Y += m_Transform.Translation.Y + CameraYOffset;
m_CameraTransform.Translation = position;
}
}
}