using Terrain; using UI; using UnityEngine; namespace User { public class Player : MonoBehaviour { public float walkSpeed = 3.0f; public float sprintSpeed = 6.0f; public float jumpForce = 5.0f; public float playerRadius = 0.3f; public float playerHeight = 2.0f; public GameObject debugScreen; [Header("Block Breaking/Destroying")] public Transform highlightBlock; public float checkIncrement = 0.1f; public float reach = 8.0f; public Toolbar toolbar; private bool _grounded; private bool _sprinting; private Transform _camera; private World _world; private float _horizontal; private float _vertical; private float _mouseHorizontal; private float _mouseVertical; private Vector3 _velocity; private float _verticalMomentum; private bool _jumpRequest; private Vector3 _placeBlockPosition; private Vector3 _destroyBlockPosition; private void Start() { _camera = GameObject.Find("Main Camera").transform; _world = GameObject.Find("World").GetComponent(); _camera.Translate(new Vector3(0, playerHeight - 0.2f, 0), Space.Self); _world.MenuOpen = false; } private void Update() { if (Input.GetKeyDown(KeyCode.E)) { _world.MenuOpen = !_world.MenuOpen; } if (!_world.MenuOpen) { GetPlayerInputs(); PlaceCursorBlock(); } else { _horizontal = 0; _vertical = 0; _mouseHorizontal = 0; _mouseVertical = 0; } } private void FixedUpdate() { CalculateVelocity(); if (_jumpRequest) Jump(); transform.Rotate(Vector3.up * _mouseHorizontal * World.Settings.mouseSensitivity); _camera.Rotate(Vector3.right * -_mouseVertical * World.Settings.mouseSensitivity); transform.Translate(_velocity, Space.World); } private void GetPlayerInputs() { if (Input.GetKeyDown(KeyCode.Escape)) Application.Quit(); _horizontal = Input.GetAxis("Horizontal"); _vertical = Input.GetAxis("Vertical"); _mouseHorizontal = Input.GetAxis("Mouse X"); _mouseVertical = Input.GetAxis("Mouse Y"); if (Input.GetButtonDown("Fire3")) _sprinting = true; if (Input.GetButtonUp("Fire3")) _sprinting = false; if (_grounded && Input.GetButtonDown("Jump")) _jumpRequest = true; if (highlightBlock.gameObject.activeSelf) { if (Input.GetMouseButtonDown(0)) _world.GetChunkFromWorldPosition(_destroyBlockPosition)?.EditBlock(_destroyBlockPosition, 0); if (Input.GetMouseButtonDown(1)) { ItemSlot slot = toolbar.slots[toolbar.slotIndex].itemSlot; if (!slot.HasItem) return; _world.GetChunkFromWorldPosition(_placeBlockPosition)?.EditBlock(_placeBlockPosition, slot.Stack.Block); slot.Take(1); } } if (Input.GetKeyDown(KeyCode.F3)) debugScreen.SetActive(!debugScreen.activeSelf); } private void PlaceCursorBlock() { float step = checkIncrement; Vector3 lastPos = new Vector3(); while (step < reach) { Vector3 pos = _camera.position + (_camera.forward * step); if (_world.CheckForBlock(pos)) { highlightBlock.position = new Vector3( Mathf.FloorToInt(pos.x), Mathf.FloorToInt(pos.y), Mathf.FloorToInt(pos.z) ); highlightBlock.gameObject.SetActive(true); _placeBlockPosition = lastPos; _destroyBlockPosition = highlightBlock.position; return; } lastPos = new Vector3( Mathf.FloorToInt(pos.x), Mathf.FloorToInt(pos.y), Mathf.FloorToInt(pos.z) ); step += checkIncrement; } highlightBlock.gameObject.SetActive(false); } private void Jump() { _verticalMomentum = jumpForce; _grounded = false; _jumpRequest = false; } private void CalculateVelocity() { if (_verticalMomentum > WorldData.Gravity) _verticalMomentum += Time.fixedDeltaTime * WorldData.Gravity; if (_sprinting) _velocity = ((transform.forward * _vertical) + (transform.right * _horizontal)) * Time.fixedDeltaTime * sprintSpeed; else _velocity = ((transform.forward * _vertical) + (transform.right * _horizontal)) * Time.fixedDeltaTime * walkSpeed; _velocity += Vector3.up * _verticalMomentum * Time.fixedDeltaTime; if ((_velocity.z > 0 && Front) || (_velocity.z < 0 && Back)) _velocity.z = 0; if ((_velocity.x > 0 && Right) || (_velocity.x < 0 && Left)) _velocity.x = 0; if (_velocity.y < 0) _velocity.y = CheckDownSpeed(_velocity.y); if (_velocity.y > 0) _velocity.y = CheckUpSpeed(_velocity.y); } private float CheckDownSpeed(in float downSpeed) { if (_world.CheckForBlock(new Vector3(transform.position.x - playerRadius, transform.position.y + downSpeed, transform.position.z - playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x + playerRadius, transform.position.y + downSpeed, transform.position.z - playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x + playerRadius, transform.position.y + downSpeed, transform.position.z + playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x - playerRadius, transform.position.y + downSpeed, transform.position.z + playerRadius))) { _grounded = true; return 0; } _grounded = false; return downSpeed; } private float CheckUpSpeed(in float upSpeed) { if (_world.CheckForBlock(new Vector3(transform.position.x - playerRadius, transform.position.y + playerHeight + upSpeed, transform.position.z - playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x + playerRadius, transform.position.y + playerHeight + upSpeed, transform.position.z - playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x + playerRadius, transform.position.y + playerHeight + upSpeed, transform.position.z + playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x - playerRadius, transform.position.y + playerHeight + upSpeed, transform.position.z + playerRadius))) { return 0; } return upSpeed; } private bool Front => _world.CheckForBlock(new Vector3(transform.position.x, transform.position.y, transform.position.z + playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x, transform.position.y + 1.0f, transform.position.z + playerRadius)); private bool Back => _world.CheckForBlock(new Vector3(transform.position.x, transform.position.y, transform.position.z - playerRadius)) || _world.CheckForBlock(new Vector3(transform.position.x, transform.position.y + 1.0f, transform.position.z - playerRadius)); private bool Left => _world.CheckForBlock(new Vector3(transform.position.x - playerRadius, transform.position.y, transform.position.z)) || _world.CheckForBlock(new Vector3(transform.position.x - playerRadius, transform.position.y + 1.0f, transform.position.z)); private bool Right => _world.CheckForBlock(new Vector3(transform.position.x + playerRadius, transform.position.y, transform.position.z)) || _world.CheckForBlock(new Vector3(transform.position.x + playerRadius, transform.position.y + 1.0f, transform.position.z)); } }