diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity
index ba5b93a2aac0028e3da9ada1a607fdcf8916f5e6..22bcde1fc3db36367588a29c7bc1317795738df9 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 f937018cc7e1f800cfb427e43ed7d73ec9f4ed95..1f73fd45111cd78b0d86c7c232ac21171e920ccd 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 0000000000000000000000000000000000000000..20f5a33f8e0bea506a928f6616c3c06ea4d1c1a7
--- /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 0000000000000000000000000000000000000000..466ab62c41b9151c9901e84fdb51efaa44d90fff
--- /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 0000000000000000000000000000000000000000..90cfb63f028b297b1f93cfe0de28240ec97c25af
--- /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 0000000000000000000000000000000000000000..d8f32cc1352c73c4ad596843f6e0f82d9e4363f2
--- /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 becfee86a6852bf12175f5b3145d76ee33d5023f..a26906eb8f225f4a8f9de29754d9f74bd918b7d3 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 899e8b833e1c147f340f9be1c2781d1ad4515a96..b63e3fd103270c48956d045eeeae61ae4a1f8c8c 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 bbc9bd99f721efe3d2dac663c1bf46134d1f60b8..83ec7abf2ce6dea790fd5c9ceed0a74b7bcff564 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 fa9691f2259d289387bf32dc29494bc33c44bcd0..bb2c6850ddd819431f971e12d1ed5c886c395633 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 6bb318c3be943a4124554fbffa9c44bdb05332ed..0000000000000000000000000000000000000000
--- 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 0000000000000000000000000000000000000000..050a897ee05c1f38d714646645cdea1bb2b2644a
--- /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 19e883d38d1ebf719748cd401ceef2dbd3ba223d..c7fe2ab70397ef91a9dbc7cf67951daed3edf980 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 0da953d94ceddb2af9d135b17cb660c5da9edd58..fddc865c5e48e1cbce0349e21579d98a5fdd0f8e 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 0000000000000000000000000000000000000000..019dd11e946772121132bb2bc483cbf7578a42e9
--- /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 0000000000000000000000000000000000000000..5b21f934526b83240e0c1639abad60a9ecdea516
--- /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 0000000000000000000000000000000000000000..ca703d3142d66d9c205c03d1e4f23c188e00102b
--- /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 0000000000000000000000000000000000000000..145c562016a44e144791b1273f93b908eaf02a00
--- /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 0000000000000000000000000000000000000000..9546149719088ed3d75f66990ad88a489075490f
--- /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 0000000000000000000000000000000000000000..224c230671e6109e178fb5fe941be9d77fc52cd1
--- /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 0000000000000000000000000000000000000000..2ba9055d90d9cdf012f36b9f00d206d6e9b2a71a
--- /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 7881c05b7707587533d1244dcc0975a3b0f4c776..85c4660b42a108f1a70b17e7d70a33e2251e264c 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;
     }