From 5f07b1af8d55b4c3ca4b0325c40c280edb8a0c99 Mon Sep 17 00:00:00 2001
From: MuhamadAjiW <16521119@mahasiswa.itb.ac.id>
Date: Wed, 17 Apr 2024 15:52:30 +0700
Subject: [PATCH] feat: movement, camera

---
 Assets/Scenes/SampleScene.unity               | 14 +++---
 Assets/Scripts/Config/CameraConfig.cs         |  6 ++-
 Assets/Scripts/Config/EnvironmentConfig.cs    |  4 ++
 .../Scripts/Config/EnvironmentConfig.cs.meta  | 11 +++++
 Assets/Scripts/Config/GameConfig.cs           |  5 ++
 Assets/Scripts/Config/GameConfig.cs.meta      | 11 +++++
 Assets/Scripts/Core/Game/GameController.cs    |  1 +
 .../Scripts/Core/Game/GameStateController.cs  |  6 +++
 Assets/Scripts/Core/Player/Player.cs          | 29 ++++++++----
 .../Core/Player/PlayerAnimationController.cs  |  9 +++-
 .../Core/Player/PlayerInputController.cs      |  4 --
 .../Core/Player/PlayerMovementController.cs   | 32 +++++++++++++
 ....meta => PlayerMovementController.cs.meta} |  0
 Assets/Scripts/Core/Player/PlayerState.cs     |  5 +-
 .../Core/Player/PlayerStateController.cs      | 47 ++++++++++++++++++-
 Assets/Scripts/Core/Player/PlayerStats.cs     | 21 +++++++++
 .../Scripts/Core/Player/PlayerStats.cs.meta   | 11 +++++
 Assets/Scripts/Library/BaseClasses.meta       |  8 ++++
 .../Library/BaseClasses/RigidObject.cs        | 42 +++++++++++++++++
 .../Library/BaseClasses/RigidObject.cs.meta   | 11 +++++
 .../Library/BaseClasses/StateController.cs    | 14 ++++++
 .../BaseClasses/StateController.cs.meta       | 11 +++++
 .../CameraBehaviour/CameraFollowObject.cs     |  5 +-
 23 files changed, 276 insertions(+), 31 deletions(-)
 create mode 100644 Assets/Scripts/Config/EnvironmentConfig.cs
 create mode 100644 Assets/Scripts/Config/EnvironmentConfig.cs.meta
 create mode 100644 Assets/Scripts/Config/GameConfig.cs
 create mode 100644 Assets/Scripts/Config/GameConfig.cs.meta
 delete mode 100644 Assets/Scripts/Core/Player/PlayerInputController.cs
 create mode 100644 Assets/Scripts/Core/Player/PlayerMovementController.cs
 rename Assets/Scripts/Core/Player/{PlayerInputController.cs.meta => PlayerMovementController.cs.meta} (100%)
 create mode 100644 Assets/Scripts/Core/Player/PlayerStats.cs
 create mode 100644 Assets/Scripts/Core/Player/PlayerStats.cs.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/RigidObject.cs
 create mode 100644 Assets/Scripts/Library/BaseClasses/RigidObject.cs.meta
 create mode 100644 Assets/Scripts/Library/BaseClasses/StateController.cs
 create mode 100644 Assets/Scripts/Library/BaseClasses/StateController.cs.meta

diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity
index ba5b93a2..22bcde1f 100644
--- a/Assets/Scenes/SampleScene.unity
+++ b/Assets/Scenes/SampleScene.unity
@@ -167,7 +167,7 @@ Rigidbody:
   m_UseGravity: 1
   m_IsKinematic: 0
   m_Interpolate: 0
-  m_Constraints: 0
+  m_Constraints: 80
   m_CollisionDetection: 0
 --- !u!65 &117855956
 BoxCollider:
@@ -6385,13 +6385,13 @@ Transform:
   m_PrefabAsset: {fileID: 0}
   m_GameObject: {fileID: 963194225}
   serializedVersion: 2
-  m_LocalRotation: {x: -0, y: -0.9615153, z: -0, w: 0.2747516}
-  m_LocalPosition: {x: 0.9690373, y: 0.12998158, z: 1.2722077}
+  m_LocalRotation: {x: 0.15573853, y: 0.0017222604, z: 0.00027153606, w: 0.9877968}
+  m_LocalPosition: {x: 0.17, y: 1.52, z: -3.42}
   m_LocalScale: {x: 1, y: 1, z: 1}
   m_ConstrainProportionsScale: 0
   m_Children: []
   m_Father: {fileID: 239523007}
-  m_LocalEulerAnglesHint: {x: 0, y: -148.106, z: 0}
+  m_LocalEulerAnglesHint: {x: 17.919, y: 0.21, z: 0.065}
 --- !u!114 &963194229
 MonoBehaviour:
   m_ObjectHideFlags: 0
@@ -6401,10 +6401,12 @@ MonoBehaviour:
   m_GameObject: {fileID: 963194225}
   m_Enabled: 1
   m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 32c6112126e80bb4daac9689eecd8a06, type: 3}
+  m_Script: {fileID: 11500000, guid: e879762b280218e4ea3042376813400a, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
-  behaviourType: 1
+  target: {fileID: 117855957}
+  followingTime: 0.2
+  offset: {x: 0, y: 2.52, z: -3.42}
 --- !u!1660057539 &9223372036854775807
 SceneRoots:
   m_ObjectHideFlags: 0
diff --git a/Assets/Scripts/Config/CameraConfig.cs b/Assets/Scripts/Config/CameraConfig.cs
index f937018c..1f73fd45 100644
--- a/Assets/Scripts/Config/CameraConfig.cs
+++ b/Assets/Scripts/Config/CameraConfig.cs
@@ -1,3 +1,7 @@
+
+using UnityEngine;
+
 public static class CameraConfig{
-    public static float DEFAULT_FOLLOWING_SPEED = 0.2f;
+    public static float DEFAULT_FOLLOWING_SPEED = 0.1f;
+    public static Vector3 DEFAULT_CAMERA_OFFSET = new(0f, 0.2f, -2f);
 }
\ No newline at end of file
diff --git a/Assets/Scripts/Config/EnvironmentConfig.cs b/Assets/Scripts/Config/EnvironmentConfig.cs
new file mode 100644
index 00000000..20f5a33f
--- /dev/null
+++ b/Assets/Scripts/Config/EnvironmentConfig.cs
@@ -0,0 +1,4 @@
+public static class EnvironmentConfig{
+    // Tags
+    public static string GROUND_TAG = "Ground";
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Config/EnvironmentConfig.cs.meta b/Assets/Scripts/Config/EnvironmentConfig.cs.meta
new file mode 100644
index 00000000..466ab62c
--- /dev/null
+++ b/Assets/Scripts/Config/EnvironmentConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6ba3c797aa74d1b4db532cc5b0fe43e1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Config/GameConfig.cs b/Assets/Scripts/Config/GameConfig.cs
new file mode 100644
index 00000000..90cfb63f
--- /dev/null
+++ b/Assets/Scripts/Config/GameConfig.cs
@@ -0,0 +1,5 @@
+public static class GameConfig{
+    // Config
+    public static float MOVEMENT_SMOOTHING = 0.2f;
+    public static float ROTATION_SMOOTHING = 720;
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Config/GameConfig.cs.meta b/Assets/Scripts/Config/GameConfig.cs.meta
new file mode 100644
index 00000000..d8f32cc1
--- /dev/null
+++ b/Assets/Scripts/Config/GameConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 991576383d30d4a4d9c37f68c33c9cc2
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Core/Game/GameController.cs b/Assets/Scripts/Core/Game/GameController.cs
index becfee86..a26906eb 100644
--- a/Assets/Scripts/Core/Game/GameController.cs
+++ b/Assets/Scripts/Core/Game/GameController.cs
@@ -6,6 +6,7 @@ public class GameController : MonoBehaviour {
     public static GameController instance;
     public static GameCameraController mainCamera;
     public static GameStateController stateController;
+    public bool IsPaused => Time.timeScale == 0;
 
     // Constructor
     private void Awake(){
diff --git a/Assets/Scripts/Core/Game/GameStateController.cs b/Assets/Scripts/Core/Game/GameStateController.cs
index 899e8b83..b63e3fd1 100644
--- a/Assets/Scripts/Core/Game/GameStateController.cs
+++ b/Assets/Scripts/Core/Game/GameStateController.cs
@@ -23,9 +23,12 @@ public class GameStateController {
             case GameState.RUNNING:
                 Time.timeScale = 1;
                 break;
+            //TODO: Review cutscenes behaviour
             case GameState.CUTSCENE:
+                Time.timeScale = 0;
                 break;
             case GameState.MENU:
+                Time.timeScale = 0;
                 break;
             default:
                 throw new Exception("Invalid gameState pushed to GameStateController, please refer to enum GameState for valid states");
@@ -48,9 +51,12 @@ public class GameStateController {
             case GameState.RUNNING:
                 Time.timeScale = 1;
                 break;
+            //TODO: Review cutscenes behaviour
             case GameState.CUTSCENE:
+                Time.timeScale = 0;
                 break;
             case GameState.MENU:
+                Time.timeScale = 0;
                 break;
         }
         OnGameStateChange.Invoke(new StackChangeEventArgs<GameState>(
diff --git a/Assets/Scripts/Core/Player/Player.cs b/Assets/Scripts/Core/Player/Player.cs
index bbc9bd99..83ec7abf 100644
--- a/Assets/Scripts/Core/Player/Player.cs
+++ b/Assets/Scripts/Core/Player/Player.cs
@@ -2,20 +2,29 @@ using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
-public class Player : MonoBehaviour
-{
+public class Player : RigidObject{
     private PlayerAnimationController animationController;
-    private PlayerInputController inputController;
+    private PlayerMovementController movementController;
     private PlayerStateController stateController;
-    private PlayerState state;
+    public PlayerStats stats;
+    public int State => stateController.state;
 
-    void Start()
-    {
-        
+    new void Start(){
+        base.Start();
+        animationController = new PlayerAnimationController(this);
+        movementController = new PlayerMovementController(this);
+        stateController = new PlayerStateController(this);
+        stats = new PlayerStats(this);
     }
 
-    void Update()
-    {
-        
+    new void Update(){
+        base.Update();
+    }
+
+    new void FixedUpdate(){
+        base.FixedUpdate();
+
+        stateController.DetectState();
+        movementController.HandleMovement();
     }
 }
diff --git a/Assets/Scripts/Core/Player/PlayerAnimationController.cs b/Assets/Scripts/Core/Player/PlayerAnimationController.cs
index fa9691f2..bb2c6850 100644
--- a/Assets/Scripts/Core/Player/PlayerAnimationController.cs
+++ b/Assets/Scripts/Core/Player/PlayerAnimationController.cs
@@ -1,4 +1,9 @@
-public class PlayerAnimationController
-{
+public class PlayerAnimationController{
+    // Attributes
+    private Player player;
 
+    // Constructor
+    public PlayerAnimationController(Player player){
+        this.player = player;
+    }
 }
diff --git a/Assets/Scripts/Core/Player/PlayerInputController.cs b/Assets/Scripts/Core/Player/PlayerInputController.cs
deleted file mode 100644
index 6bb318c3..00000000
--- a/Assets/Scripts/Core/Player/PlayerInputController.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-public class PlayerInputController
-{
-
-}
diff --git a/Assets/Scripts/Core/Player/PlayerMovementController.cs b/Assets/Scripts/Core/Player/PlayerMovementController.cs
new file mode 100644
index 00000000..050a897e
--- /dev/null
+++ b/Assets/Scripts/Core/Player/PlayerMovementController.cs
@@ -0,0 +1,32 @@
+using Unity.VisualScripting;
+using UnityEngine;
+
+public class PlayerMovementController{
+    private Player player;
+
+    public PlayerMovementController(Player player){
+        this.player = player;
+    }
+
+    private void HandleRotation(Vector3 moveDirection){
+        Quaternion target = Quaternion.LookRotation(moveDirection, Vector3.up);
+
+        // Note: this can be smoothened, for better or for worse
+        player.transform.rotation = Quaternion.RotateTowards(player.transform.rotation, target, GameConfig.ROTATION_SMOOTHING * Time.deltaTime);
+    }
+
+    public void HandleMovement(){
+        float keyPressAD = Input.GetAxisRaw("Horizontal");
+        float keyPressWS = Input.GetAxisRaw("Vertical");
+        Vector3 velocity = new(player.Rigidbody.velocity.x, player.Rigidbody.velocity.y, player.Rigidbody.velocity.z);
+        Vector3 dampVelocity = Vector3.zero;
+
+        Vector3 inputVector = new(keyPressAD, 0, keyPressWS);
+        Vector3 modifierVector = inputVector.normalized * player.stats.MaxSpeed;
+        velocity.x = modifierVector.x;
+        velocity.z = modifierVector.z;
+
+        player.Rigidbody.velocity = Vector3.SmoothDamp(player.Rigidbody.velocity, velocity, ref dampVelocity, GameConfig.MOVEMENT_SMOOTHING);
+        if(inputVector != Vector3.zero) HandleRotation(inputVector);
+    }
+}
diff --git a/Assets/Scripts/Core/Player/PlayerInputController.cs.meta b/Assets/Scripts/Core/Player/PlayerMovementController.cs.meta
similarity index 100%
rename from Assets/Scripts/Core/Player/PlayerInputController.cs.meta
rename to Assets/Scripts/Core/Player/PlayerMovementController.cs.meta
diff --git a/Assets/Scripts/Core/Player/PlayerState.cs b/Assets/Scripts/Core/Player/PlayerState.cs
index 19e883d3..c7fe2ab7 100644
--- a/Assets/Scripts/Core/Player/PlayerState.cs
+++ b/Assets/Scripts/Core/Player/PlayerState.cs
@@ -1,4 +1 @@
-public class PlayerState : EntityState
-{
-
-}
+public class PlayerState : EntityState {}
diff --git a/Assets/Scripts/Core/Player/PlayerStateController.cs b/Assets/Scripts/Core/Player/PlayerStateController.cs
index 0da953d9..fddc865c 100644
--- a/Assets/Scripts/Core/Player/PlayerStateController.cs
+++ b/Assets/Scripts/Core/Player/PlayerStateController.cs
@@ -1,4 +1,47 @@
-public class PlayerStateController
-{
+using UnityEngine;
 
+public class PlayerStateController : StateController{
+    // Attributes
+    private Player player;
+
+    // Contstructor
+    public PlayerStateController(Player player){
+        this.player = player;
+    }
+
+    private bool DetectJumping(){
+        return !player.Grounded && player.Rigidbody.velocity.y > 0;
+    }
+    private bool DetectFalling(){
+        return !player.Grounded && player.Rigidbody.velocity.y < 0;
+    }
+    private bool DetectWalking(){
+        return Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0;
+    }
+    // TODO: Implement
+    private bool DetectSprinting(){
+        return false;        
+    }
+
+    public override int DetectState(){
+        int initialState = state;
+
+        if(DetectJumping()){
+            state = PlayerState.JUMPING;
+        }
+        else if(DetectFalling()){
+            state = PlayerState.FALLING;
+        }
+        else if(DetectSprinting()){
+            state = PlayerState.SPRINTING;
+        }
+        else if(DetectWalking()){
+            state = PlayerState.WALKING;
+        } else{
+            state = PlayerState.IDLE;
+        }
+
+        if(initialState != state) InvokeOnStateChanged();
+        return state;
+    }
 }
diff --git a/Assets/Scripts/Core/Player/PlayerStats.cs b/Assets/Scripts/Core/Player/PlayerStats.cs
new file mode 100644
index 00000000..019dd11e
--- /dev/null
+++ b/Assets/Scripts/Core/Player/PlayerStats.cs
@@ -0,0 +1,21 @@
+public class PlayerStats {
+    // Attributes
+    private Player player;
+    public float walkSpeed = 10;
+    public float sprintSpeed = 25;
+    public float jumpForce = 600;
+    public float snapshotSpeed = 25;
+
+    public float MaxSpeed => player.State switch{
+        PlayerState.WALKING => walkSpeed,
+        PlayerState.SPRINTING => sprintSpeed,
+        PlayerState.JUMPING => snapshotSpeed,
+        PlayerState.FALLING => snapshotSpeed,
+        _ => 0
+    };
+
+    // Constructor
+    public PlayerStats(Player player){
+        this.player = player;
+    }
+}
diff --git a/Assets/Scripts/Core/Player/PlayerStats.cs.meta b/Assets/Scripts/Core/Player/PlayerStats.cs.meta
new file mode 100644
index 00000000..5b21f934
--- /dev/null
+++ b/Assets/Scripts/Core/Player/PlayerStats.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0c339b96888d9974d9c0635081cd56fa
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses.meta b/Assets/Scripts/Library/BaseClasses.meta
new file mode 100644
index 00000000..ca703d31
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 633f395f0bcb47345a3160c5dfb1cd02
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses/RigidObject.cs b/Assets/Scripts/Library/BaseClasses/RigidObject.cs
new file mode 100644
index 00000000..145c5620
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/RigidObject.cs
@@ -0,0 +1,42 @@
+using UnityEngine;
+
+public class RigidObject : MonoBehaviour {
+    // Attributes
+
+    // Readonly by others
+    private new Rigidbody rigidbody;
+    private new Collider collider;
+    private bool grounded;
+
+
+    public Rigidbody Rigidbody => rigidbody;
+    public Collider Collider => collider;
+    public Vector3 Position => transform.position;
+    public bool Grounded => grounded;
+
+    // Constructor
+    protected void Start(){
+        rigidbody = GetComponent<Rigidbody>();
+        collider = GetComponent<Collider>();
+    }
+
+    protected void Refresh(){
+        Rigidbody.AddForce(Vector2.zero);
+    }
+
+    protected void Smoothen(){
+        Vector3 dampVelocity = Vector3.zero;
+        Vector3 velocity = Rigidbody.velocity;
+        velocity.x = 0;
+        velocity.z = 0;
+        Rigidbody.velocity = Vector3.SmoothDamp(Rigidbody.velocity, velocity, ref dampVelocity, GameConfig.MOVEMENT_SMOOTHING);
+    }
+
+    protected void Update(){
+        if(GameController.instance.IsPaused) return;
+    }
+
+    protected void FixedUpdate(){
+        if(GameController.instance.IsPaused) return;
+    }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Library/BaseClasses/RigidObject.cs.meta b/Assets/Scripts/Library/BaseClasses/RigidObject.cs.meta
new file mode 100644
index 00000000..95461497
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/RigidObject.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e296ba033c1cc7c499c1615f6fad1247
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/BaseClasses/StateController.cs b/Assets/Scripts/Library/BaseClasses/StateController.cs
new file mode 100644
index 00000000..224c2306
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/StateController.cs
@@ -0,0 +1,14 @@
+using System;
+
+public abstract class StateController{
+    // Attributes
+    public int state;
+    public event Action OnStateChange;
+
+    // Functions
+    protected void InvokeOnStateChanged(){
+        OnStateChange?.Invoke();
+    }
+
+    public abstract int DetectState();
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Library/BaseClasses/StateController.cs.meta b/Assets/Scripts/Library/BaseClasses/StateController.cs.meta
new file mode 100644
index 00000000..2ba9055d
--- /dev/null
+++ b/Assets/Scripts/Library/BaseClasses/StateController.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a8c960774714bc441b8d14610ed47145
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs b/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs
index 7881c05b..85c4660b 100644
--- a/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs
+++ b/Assets/Scripts/Library/CameraBehaviour/CameraFollowObject.cs
@@ -4,11 +4,12 @@ public class CameraFollowObject : CameraBehaviour {
     // Attributes
     [SerializeField] public Transform target;
     [SerializeField] public float followingTime = CameraConfig.DEFAULT_FOLLOWING_SPEED;
+    [SerializeField] public Vector3 offset = CameraConfig.DEFAULT_CAMERA_OFFSET;
     private Vector3 velocity = Vector3.zero;
     
     // Functions
-    void LateUpdate(){
-        Vector3 targetPosition = new(target.position.x, target.position.y, transform.position.z);
+    void FixedUpdate(){
+        Vector3 targetPosition = target.position + offset;
         Vector3 newPosition = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, followingTime);
         transform.position = newPosition;
     }
-- 
GitLab