160 lines
4.6 KiB
C#
160 lines
4.6 KiB
C#
using System;
|
|
using Code.UI;
|
|
using UnityEngine;
|
|
|
|
namespace Code.Gameplay.Player
|
|
{
|
|
public class PlayerController : MonoBehaviour
|
|
{
|
|
[SerializeField] private float forwardSpeed = 10f;
|
|
[SerializeField] private float maxSpeed = 40f;
|
|
[SerializeField] private float laneDistance = 5f;
|
|
[SerializeField] private float jumpForce = 11f;
|
|
[SerializeField] private float gravity = 20f;
|
|
|
|
[SerializeField] private Animator animator;
|
|
[SerializeField] private RuntimeAnimatorController runController;
|
|
[SerializeField] private RuntimeAnimatorController jumpController;
|
|
|
|
private int _targetLane = 1;
|
|
|
|
private CharacterController _controller;
|
|
private Vector3 _direction;
|
|
|
|
public Action OnPlayerDeath;
|
|
private bool _isDead;
|
|
|
|
private bool _isDoubleCoins;
|
|
private float _bonusTimer;
|
|
|
|
private void Start()
|
|
{
|
|
_controller = GetComponent<CharacterController>();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_isDead) return;
|
|
|
|
if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D))
|
|
{
|
|
_targetLane = Mathf.Min(_targetLane + 1, 2);
|
|
}
|
|
else if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A))
|
|
{
|
|
_targetLane = Mathf.Max(_targetLane - 1, 0);
|
|
}
|
|
|
|
var targetPosition = transform.position.z * transform.forward + transform.position.y * transform.up;
|
|
|
|
switch (_targetLane)
|
|
{
|
|
case 0:
|
|
targetPosition += Vector3.left * laneDistance;
|
|
break;
|
|
case 2:
|
|
targetPosition += Vector3.right * laneDistance;
|
|
break;
|
|
}
|
|
|
|
if (_controller.isGrounded)
|
|
{
|
|
_direction.y = -1f;
|
|
|
|
if (Input.GetKeyDown(KeyCode.Space))
|
|
{
|
|
animator.runtimeAnimatorController = jumpController;
|
|
_direction.y = jumpForce;
|
|
}
|
|
else
|
|
{
|
|
animator.runtimeAnimatorController = runController;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_direction.y -= gravity * Time.deltaTime;
|
|
}
|
|
|
|
_direction.z = forwardSpeed;
|
|
|
|
var diff = targetPosition - transform.position;
|
|
var moveDir = diff.normalized * (25f * Time.deltaTime);
|
|
|
|
var moveX = Mathf.Clamp(diff.x, -moveDir.magnitude, moveDir.magnitude);
|
|
|
|
var finalMove = new Vector3(moveX, _direction.y * Time.deltaTime, _direction.z * Time.deltaTime);
|
|
|
|
_controller.Move(finalMove);
|
|
CheckForDeath();
|
|
HandleBonusTimer();
|
|
}
|
|
|
|
public void IncreaseSpeed(float amount)
|
|
{
|
|
if (forwardSpeed < maxSpeed)
|
|
{
|
|
var desirableSpeed = forwardSpeed + amount;
|
|
forwardSpeed = Mathf.Min(desirableSpeed, maxSpeed);
|
|
}
|
|
}
|
|
|
|
private void OnTriggerEnter(Collider foreign)
|
|
{
|
|
if (foreign.CompareTag("Obstacle"))
|
|
{
|
|
Die();
|
|
}
|
|
|
|
if (foreign.CompareTag("Coin"))
|
|
{
|
|
var amount = _isDoubleCoins ? 2 : 1;
|
|
for(var i = 0; i < amount; i++) GameplayController.Instance.AddCoin();
|
|
|
|
Destroy(foreign.gameObject);
|
|
}
|
|
|
|
if (foreign.CompareTag("BonusX2"))
|
|
{
|
|
ActivateDoubleCoins(10f);
|
|
Destroy(foreign.gameObject);
|
|
}
|
|
}
|
|
|
|
private void ActivateDoubleCoins(float duration)
|
|
{
|
|
_isDoubleCoins = true;
|
|
_bonusTimer = duration;
|
|
}
|
|
|
|
private void HandleBonusTimer()
|
|
{
|
|
if (_bonusTimer > 0)
|
|
{
|
|
_bonusTimer -= Time.deltaTime;
|
|
if (_bonusTimer <= 0)
|
|
{
|
|
_isDoubleCoins = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckForDeath()
|
|
{
|
|
if (_isDead) return;
|
|
|
|
if (Time.timeSinceLevelLoad > 1f && _controller.velocity.z <= 0.1f)
|
|
{
|
|
Die();
|
|
}
|
|
}
|
|
|
|
private void Die()
|
|
{
|
|
_isDead = true;
|
|
forwardSpeed = 0;
|
|
_direction = Vector3.zero;
|
|
OnPlayerDeath?.Invoke();
|
|
}
|
|
}
|
|
} |