using Components; using Core; using DG.Tweening; using Panels; using PermanentSystems; using Sirenix.OdinInspector; using UnityEngine; using Application = Core.Application; namespace Systems { public class PlayerController : SystemBase, ITick { [SerializeField] private float editorSpeed = 1f; [BoxGroup("Player Settings")] [SerializeField] private Transform playerTransform; [BoxGroup("Player Settings")] [SerializeField] private Transform jumpTransform; [BoxGroup("Player Settings")] [SerializeField] private CollisionListener collisionListener; // [BoxGroup("Player Settings")] [SerializeField] private Material playerMaterial; [BoxGroup("Player Effects")] [SerializeField] private ParticleSystem trailEffect; [BoxGroup("Player Effects")] [SerializeField] private ParticleSystem jumpEffect; [BoxGroup("Player Effects")] [SerializeField] private ParticleSystem collectBlueEffect; [BoxGroup("Player Effects")] [SerializeField] private ParticleSystem collectRedEffect; [BoxGroup("Player Effects")] [SerializeField] private ParticleSystem collectGreenEffect; [BoxGroup("Movement Settings")] [SerializeField] private float limitUnit = 2; [BoxGroup("Jump Settings")] [SerializeField] private float jumpHeight = .2f; [BoxGroup("Jump Settings")] [SerializeField] private float jumpDuration = .5f; [BoxGroup("Jump Settings")] [SerializeField] private Ease jumpEase; [BoxGroup("Boost Settings")] [SerializeField] private int boostRequirement = 6; [BoxGroup("Boost Settings")] [SerializeField] private ParticleSystem boostPunchEffect; [BoxGroup("Boost Settings")] [SerializeField] private ParticleSystem windEffect; [BoxGroup("Boost Settings")] [SerializeField] private ParticleSystem shieldEffect; private bool _boostIsActive; private int _playerHealth = 3; private float _speed; private bool _isJumping; private bool _canJump; private Tween _jumpTween; private bool _inHitAnimation; private bool _vibrationsEnabled; private bool _isInitialized; private int _redOrbs; private int _blueOrbs; private CameraController _cameraController; private CameraController CameraController { get { if (_cameraController == null) _cameraController = Application.GetSystem(); return _cameraController; } } private HUDPanel _hudPanel; private HUDPanel HudPanel { get { if (_hudPanel == null) _hudPanel = Application.GetPanel(); return _hudPanel; } } private GameOverPanel _gameOverPanel; private GameOverPanel GameOverPanel { get { if (_gameOverPanel == null) _gameOverPanel = Application.GetPanel(); return _gameOverPanel; } } private PersistantDataController _dataController; private PersistantDataController DataController { get { if (_dataController == null) _dataController = Application.GetSystem(); return _dataController; } } private PoolSystem _pSystem; private PoolSystem PoolSystem { get { if (_pSystem == null) _pSystem = Application.GetSystem(); return _pSystem; } } private GameManager _manager; private GameManager GameManager { get { if (_manager == null) _manager = Application.GetSystem(); return _manager; } } protected override void ReleaseReferences() { playerTransform = null; jumpTransform = null; } public override void Initialize() { collisionListener.OnEnterTrigger += OnObjectHit; GameManager.OnBoostEnd += ExitBoost; } private void OnObjectHit(TriggerType inType, GameObject inObject) { Debug.Log($"Hit Object: {inType.ToString()}"); if (inType == TriggerType.HealthUp) { inObject.SetActive(false); if (_playerHealth >= 3) return; _playerHealth++; collectGreenEffect.Play(); AudioSystem.PlaySoundEffect(AudioList.HealthUp); var objPosition = inObject.transform.position; objPosition.y = .2f; var effect = PoolSystem.Spawn(ObjectList.HealEffect, objPosition, Quaternion.identity, null); effect.OnEffectComplete += tr => PoolSystem.Despawn(tr); effect.PlayEffect(); // var viewPosition = CameraController.GetViewPoint(objPosition); // var collectEffect = PoolSystem.Spawn(ObjectList.HealthIcon, HudPanel.transform); // // collectEffect.OnComplete += tr => // { // HudPanel.GainHealth(); // PoolSystem.Despawn(tr); // }; // // collectEffect.BindData(viewPosition, HudPanel.CurrentHeartPosition); // collectEffect.PlayAnimation(); HudPanel.GainHealth(); return; } if (inType == TriggerType.ForceField) { inObject.GetComponent() .PlayCollisionEffect(); return; } if (inType == TriggerType.Obstacle) { if (_boostIsActive) { var effect = PoolSystem.Spawn(ObjectList.DestroyEffect, inObject.transform.position, Quaternion.identity, null); effect.OnEffectComplete += tr => PoolSystem.Despawn(tr); effect.PlayEffect(); CameraController.PlayCameraShake(.06f); inObject.SetActive(false); AudioSystem.PlaySoundEffect(AudioList.DestroyObject); return; } _playerHealth--; CameraController.PlayCameraShake(); HudPanel.LoseHealth(); if (_vibrationsEnabled) Handheld.Vibrate(); PlayHitAnimation(); if (_playerHealth <= 0) { AudioSystem.PlaySoundEffect(AudioList.HitEffectB); DataController.UpdateBlueOrbs(_blueOrbs); GameOverPanel.OpenPanel(); } else AudioSystem.PlaySoundEffect(AudioList.HitEffectA); return; } if (inType == TriggerType.Collectible) { collectBlueEffect.Play(); AudioSystem.PlaySoundEffect(AudioList.CollectEffectA); inObject.SetActive(false); HudPanel.UpdateBlueOrbCount(++_blueOrbs); return; } if (inType == TriggerType.SpecialCollectible) { collectRedEffect.Play(); AudioSystem.PlaySoundEffect(AudioList.CollectEffectB); inObject.SetActive(false); if (_boostIsActive) return; var viewPosition = CameraController.GetViewPoint(inObject.transform.position); var collectEffect = PoolSystem.Spawn(ObjectList.RedOrbIcon, HudPanel.transform); collectEffect.OnComplete += tr => PoolSystem.Despawn(tr); collectEffect.BindData(viewPosition, HudPanel.PowerIconPosition); collectEffect.PlayAnimation(); var progress = ++_redOrbs / (float) boostRequirement; HudPanel.UpdateRedOrbProgress(progress); if (_redOrbs >= boostRequirement) { ActivateBoost(); _redOrbs = 0; } return; } } private void ActivateBoost() { if (_boostIsActive) return; Debug.Log("Boost mode active!"); _boostIsActive = true; var boostTime = GameManager.EnterBoostStage(); HudPanel.DepleteRedOrbs(boostTime); boostPunchEffect.Play(); windEffect.Play(); shieldEffect.Play(); trailEffect.transform.DOScaleZ(2f, 1f); playerTransform.DOLocalMoveZ(.85f, 1f) .SetEase(Ease.OutBack); AudioSystem.PlaySoundEffect(AudioList.EnterBoost); } private void ExitBoost() { _boostIsActive = false; windEffect.Stop(); shieldEffect.Stop(); trailEffect.transform.DOScaleZ(1f, .75f); playerTransform.DOLocalMoveZ(.35f, .75f) .SetEase(Ease.InQuad); } private void PlayHitAnimation() { if (_inHitAnimation) return; _inHitAnimation = true; playerTransform.DOScale(.92f, .2f) .SetEase(Ease.InBounce) .OnComplete(() => { playerTransform.DOScale(1f, .22f) .SetEase(Ease.OutBounce) .OnComplete(() => { _inHitAnimation = false; }); }); } public void BindSpeed(float inValue) { var factor = .03f * inValue; _speed = .02f + factor; } public void UpdateVibrations(bool inState) => _vibrationsEnabled = inState; public override void StartSystem() { if (!_isInitialized) { var data = DataController.PlayerData; _vibrationsEnabled = data.enableVibrations; BindSpeed(data.inputSensitivity); _isInitialized = true; } trailEffect.Play(); _jumpTween?.Play(); base.StartSystem(); } public override void StopSystem() { _jumpTween?.Pause(); _canJump = false; _isJumping = false; base.StopSystem(); } public void Tick() { if (!IsRun) return; #if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.Backspace)) ActivateBoost(); // if (Input.GetKeyDown(KeyCode.UpArrow)) Jump(); var input = (int) Input.GetAxisRaw("Horizontal"); if (input == 0) return; MovePlayer(input); #else TouchInputV2(); #endif } private void TouchInputV2() { // if (Input.touchCount <= 0) // { // if (_canJump) // { // Jump(); // _canJump = false; // } // // return; // } if (Input.touchCount <= 0) return; var touchInput = Input.GetTouch(0); var direction = Vector3.right * touchInput.deltaPosition.x; var currentPosition = playerTransform.localPosition; var newPosition = currentPosition + direction * _speed * Time.deltaTime; newPosition.x = Mathf.Clamp(newPosition.x, -limitUnit, limitUnit); playerTransform.localPosition = newPosition; // _canJump = true; } private void MovePlayer(int direction) { var currentPosition = playerTransform.localPosition; var newPosition = currentPosition + Vector3.right * (direction * editorSpeed * Time.deltaTime); newPosition.x = Mathf.Clamp(newPosition.x, -limitUnit, limitUnit); playerTransform.localPosition = newPosition; } private void Jump() { if (_isJumping) return; _isJumping = true; var currentPosition = jumpTransform.localPosition; _jumpTween = jumpTransform.DOLocalJump(currentPosition, jumpHeight, 1, jumpDuration) .SetEase(jumpEase) .OnComplete(() => { jumpEffect.Play(); AudioSystem.PlaySoundEffect(AudioList.JumpEffect); CameraController.PlayCameraShake(.025f); _jumpTween = null; _isJumping = false; }); } } }