KitchenChaos/Assets/Scripts/Player.cs

145 lines
5.3 KiB
C#

using System;
using Counters;
using JetBrains.Annotations;
using UnityEngine;
public class Player : MonoBehaviour, IKitchenObjectParent {
private const float playerRadius = .7f;
private const float playerHeight = 2f;
public event EventHandler OnPickedSomething;
[SerializeField] private GameInput gameInput;
[SerializeField] private float moveSpeed = 7f;
[SerializeField] private float rotateSpeed = 10f;
[SerializeField] private float interactDistance = 2f;
[SerializeField] private LayerMask countersLayerMask;
[SerializeField] private Transform kitchenObjectHoldPoint;
private Vector2 inputVector;
private bool isWalking;
[SerializeField] private KitchenObject kitchenObject;
private Vector3 lastInteractDir;
private Vector3 moveDir;
private BaseCounter selectedCounter;
public static Player Instance { get; private set; }
private void Awake() {
if (Instance != null) Debug.LogError("There is more than one Player instance!");
Instance = this;
}
private void Start() {
gameInput.OnInteractAction += GameInput_OnInteractAction;
gameInput.OnInteractAlternateAction += GameInput_OnInteractAlternateAction;
}
private void Update() {
HandleMovement();
HandleInteractions();
}
public Transform GetKitchenObjectHoldPoint() => kitchenObjectHoldPoint;
public void SetKitchenObject(KitchenObject kO) {
kitchenObject = kO;
if (kitchenObject is not null) {
OnPickedSomething?.Invoke(this, EventArgs.Empty);
}
}
public KitchenObject GetKitchenObject() => kitchenObject;
public void ClearKitchenObject() => kitchenObject = null;
public bool HasKitchenObject() => kitchenObject is not null;
public event EventHandler<SelectedCounterChangedEventArgs> OnSelectedCounterChanged;
private void GameInput_OnInteractAlternateAction(object sender, EventArgs e) {
if (!KitchenGameManager.Instance.IsGamePlaying()) return;
selectedCounter?.InteractAlternate(this);
}
private void GameInput_OnInteractAction(object sender, EventArgs e) {
if (!KitchenGameManager.Instance.IsGamePlaying()) return;
selectedCounter?.Interact(this);
}
private void HandleInteractions() {
if (moveDir != Vector3.zero) lastInteractDir = moveDir;
if (Physics.Raycast(transform.position, lastInteractDir, out RaycastHit raycastHit, interactDistance,
countersLayerMask)) {
if (raycastHit.transform.TryGetComponent(out BaseCounter baseCounter)) {
// Debug.Log("Player stands in front of a BaseCounter");
if (baseCounter != selectedCounter)
SetSelectedCounter(baseCounter);
}
else {
SetSelectedCounter(null);
}
}
else {
SetSelectedCounter(null);
}
}
private void SetSelectedCounter(BaseCounter sC) {
selectedCounter = sC;
// Debug.Log(selectedCounter != null ? "SelectedCounter changed to BaseCounter" : "SelectedCounter changed to null");
OnSelectedCounterChanged?.Invoke(this, new() { SelectedCounter = sC });
}
public bool IsWalking() => isWalking;
private void HandleMovement() {
inputVector = GameInput.GetMovementVectorNormalized();
moveDir = new(inputVector.x, 0, inputVector.y);
float moveDistance = moveSpeed * Time.deltaTime;
bool canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDir, moveDistance);
if (!canMove) {
// Cannot move towars moveDir
//Attempt only x movement
Vector3 moveDirX = new Vector3(moveDir.x, 0, 0).normalized;
canMove = (moveDir.x < -.5f || moveDir.x > +.5f) && !Physics.CapsuleCast(transform.position, transform.position + (Vector3.up * playerHeight), playerRadius, moveDir, moveDistance);
if (canMove) {
//Can move only on the X
MovePlayer(moveDirX, moveDistance);
}
else {
//Cannot move only on the X
//Attempt only Z movement
Vector3 moveDirZ = new Vector3(0, 0, moveDir.z).normalized;
canMove = (moveDir.z < -.5f || moveDir.z > +.5f) && !Physics.CapsuleCast(transform.position, transform.position + (Vector3.up * playerHeight), playerRadius, moveDir, moveDistance);
if (canMove) {
//Can move only on the Z
MovePlayer(moveDirZ, moveDistance);
}
else {
//Cannot move in any direction
}
}
}
else {
MovePlayer(moveDir, moveDistance);
}
isWalking = moveDir != Vector3.zero;
transform.forward = Vector3.Slerp(transform.forward, moveDir, Time.deltaTime * rotateSpeed);
}
private void MovePlayer(Vector3 moveDirection, float moveDistance) {
transform.position += moveDirection * moveDistance;
}
public class SelectedCounterChangedEventArgs : EventArgs {
public BaseCounter SelectedCounter;
}
}