From f79fda16e943988052b0cd91ebda161c4b60e307 Mon Sep 17 00:00:00 2001
From: Sara <sara@saragerretsen.nl>
Date: Fri, 27 Sep 2024 16:08:21 +0200
Subject: [PATCH] feat: added yaw keys

---
 src/main.c              |  4 ++-
 src/player_controller.c | 63 ++++++++++++++++++++++++++++-------------
 src/player_controller.h | 18 ++++++------
 3 files changed, 57 insertions(+), 28 deletions(-)

diff --git a/src/main.c b/src/main.c
index dc03fe6..bb19d00 100644
--- a/src/main.c
+++ b/src/main.c
@@ -56,7 +56,9 @@ void ConfigureInput() {
     AddAction("pitch_down", INPUT_LISTENER_KEY, 0, KEY_W);
     AddAction("roll_left", INPUT_LISTENER_KEY, 0, KEY_A);
     AddAction("roll_right", INPUT_LISTENER_KEY, 0, KEY_D);
-    AddAction("stop", INPUT_LISTENER_KEY, 0, KEY_SPACE);
+    AddAction("yaw_right", INPUT_LISTENER_KEY, 0, KEY_E);
+    AddAction("yaw_left", INPUT_LISTENER_KEY, 0, KEY_Q);
+    AddAction("brake", INPUT_LISTENER_KEY, 0, KEY_SPACE);
 }
 
 int main() {
diff --git a/src/player_controller.c b/src/player_controller.c
index 7253ac4..ac202dc 100644
--- a/src/player_controller.c
+++ b/src/player_controller.c
@@ -1,7 +1,8 @@
 #include "player_controller.h"
 #include "core/render.h"
-#include "utils/debug.h"
 #include "core/input.h"
+#include "utils/typeclass_helpers.h"
+#include "utils/debug.h"
 #include "raylib.h"
 
 START_REFLECT(PlayerController);
@@ -21,8 +22,14 @@ impl_SceneNodeEntity_for(PlayerController,
 
 SceneNode *CreatePlayerController() {
     PlayerController *self = new(PlayerController);
-    self->rotation = self->fly_input = Vector2Zero();
-    self->stopped = false;
+    *self = (PlayerController) {
+        .node = NULL,
+        .transform = tc_null(Transformable),
+        .rotation = Vector3Zero(),
+        .fly_input = Vector3Zero(),
+        .speed = 10.f,
+        .brake = false
+    };
     return CreateSceneNode(PlayerController_as_SceneNodeEntity(self));
 }
 
@@ -33,30 +40,39 @@ void DestroyPlayerController(PlayerController *self) {
 void PlayerControllerEnterTree(PlayerController *self) {
     self->transform = TC_CAST(self->node->parent->entity, Transformable);
     DisableCursor();
-    AddListener("pitch_up", ButtonInputListener(self, PlayerControllerUpInput));
-    AddListener("pitch_down", ButtonInputListener(self, PlayerControllerDownInput));
-    AddListener("roll_left", ButtonInputListener(self, PlayerControllerLeftInput));
-    AddListener("roll_right", ButtonInputListener(self, PlayerControllerRightInput));
-    AddListener("stop", ButtonInputListener(self, PlayerControllerStopInput));
+    AddListener("pitch_up", ButtonInputListener(self, PlayerControllerInputPitchUp));
+    AddListener("pitch_down", ButtonInputListener(self, PlayerControllerInputPitchDown));
+    AddListener("roll_left", ButtonInputListener(self, PlayerControllerInputRollLeft));
+    AddListener("roll_right", ButtonInputListener(self, PlayerControllerInputRollRight));
+    AddListener("yaw_left", ButtonInputListener(self, PlayerControllerInputYawLeft));
+    AddListener("yaw_right", ButtonInputListener(self, PlayerControllerInputYawRight));
+    AddListener("stop", ButtonInputListener(self, PlayerControllerInputBrake));
 }
 
 void PlayerControllerExitTree(PlayerController *self) {
     RemoveAllListeners(self);
 }
 
+static
+float MoveTowards(float from, float to, float delta) {
+    if(from == to) return to;
+    float const diff = to - from;
+    float const sign = signbit(diff) ? -1.f : 1.f;
+    return from + sign * fminf(delta, fabsf(diff));
+}
+
 //! angular acceleration limited to local X and Z axes
 static
 void PlayerControllerTickAngularAcceleration(PlayerController *self, double delta) {
-    Vector2 diff = Vector2Subtract(self->fly_input, self->rotation);
-    float const length = Vector2Length(diff);
-    if(length != 0.f)
-        self->rotation = Vector2Add(self->rotation, Vector2Scale(diff, 1.0f/length * fminf(4.f * delta, length)));
+    self->rotation.x = MoveTowards(self->rotation.x, self->fly_input.x, delta * 4.f);
+    self->rotation.y = MoveTowards(self->rotation.y, self->fly_input.y, delta * 4.f);
+    self->rotation.z = MoveTowards(self->rotation.z, self->fly_input.z, delta * 4.f);
 }
 
 //! linear acceleration limited to the local Z axis
 static
 void PlayerControllerTickLinearAcceleration(PlayerController *self, double delta) {
-    float const target = self->stopped ? 5.f : (self->rotation.y == 0.f ? 30.f : 10.f);
+    float const target = self->brake ? 5.f : (self->rotation.y == 0.f ? 30.f : 10.f);
     float const speed_diff = target - self->speed;
     self->speed = self->speed + copysignf(fminf(fabsf(speed_diff), 15.f * delta), speed_diff);
 }
@@ -69,6 +85,7 @@ void PlayerControllerTickTransform(PlayerController *self, double delta) {
     global_transform.translation = Vector3Add(global_transform.translation, Vector3Scale(MATRIX_FORWARD(global_matrix), self->speed * delta));
     global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_FORWARD(global_matrix), self->rotation.x * 2.f * delta), global_transform.rotation);
     global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_RIGHT(global_matrix), self->rotation.y * 2.5f * delta), global_transform.rotation);
+    global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_UP(global_matrix), self->rotation.z * 1.f * delta), global_transform.rotation);
     self->transform.tc->set_global_transform(self->transform.data, global_transform);
 }
 
@@ -78,22 +95,30 @@ void PlayerControllerTick(PlayerController *self, double delta) {
     PlayerControllerTickTransform(self, delta);
 }
 
-void PlayerControllerLeftInput(PlayerController *self, bool value) {
+void PlayerControllerInputRollLeft(PlayerController *self, bool value) {
     self->fly_input.x += value ? -1 : +1;
 }
 
-void PlayerControllerRightInput(PlayerController *self, bool value) {
+void PlayerControllerInputRollRight(PlayerController *self, bool value) {
     self->fly_input.x += value ? +1 : -1;
 }
 
-void PlayerControllerUpInput(PlayerController *self, bool value) {
+void PlayerControllerInputPitchUp(PlayerController *self, bool value) {
     self->fly_input.y += value ? -1 : +1;
 }
 
-void PlayerControllerDownInput(PlayerController *self, bool value) {
+void PlayerControllerInputPitchDown(PlayerController *self, bool value) {
     self->fly_input.y += value ? +1 : -1;
 }
 
-void PlayerControllerStopInput(PlayerController *self, bool value) {
-    self->stopped = value;
+void PlayerControllerInputYawRight(PlayerController *self, bool value) {
+    self->fly_input.z += value ? -1 : +1;
+}
+
+void PlayerControllerInputYawLeft(PlayerController *self, bool value) {
+    self->fly_input.z += value ? +1 : -1;
+}
+
+void PlayerControllerInputBrake(PlayerController *self, bool value) {
+    self->brake = value;
 }
diff --git a/src/player_controller.h b/src/player_controller.h
index e20a724..08d3cf9 100644
--- a/src/player_controller.h
+++ b/src/player_controller.h
@@ -12,10 +12,10 @@
 typedef struct PlayerController {
     SceneNode *node;
     Transformable transform;
-    Vector2 fly_input;
-    Vector2 rotation;
+    Vector3 fly_input;
+    Vector3 rotation;
     float speed;
-    bool stopped;
+    bool brake;
 } PlayerController;
 
 SceneNode *CreatePlayerController();
@@ -25,11 +25,13 @@ extern void PlayerControllerEnterTree(PlayerController *self);
 extern void PlayerControllerExitTree(PlayerController *self);
 extern void PlayerControllerTick(PlayerController *self, double delta);
 
-extern void PlayerControllerLeftInput(PlayerController *self, bool value);
-extern void PlayerControllerRightInput(PlayerController *self, bool value);
-extern void PlayerControllerUpInput(PlayerController *self, bool value);
-extern void PlayerControllerDownInput(PlayerController *self, bool value);
-extern void PlayerControllerStopInput(PlayerController *self, bool value);
+extern void PlayerControllerInputRollLeft(PlayerController *self, bool value);
+extern void PlayerControllerInputRollRight(PlayerController *self, bool value);
+extern void PlayerControllerInputPitchUp(PlayerController *self, bool value);
+extern void PlayerControllerInputPitchDown(PlayerController *self, bool value);
+extern void PlayerControllerInputYawRight(PlayerController *self, bool value);
+extern void PlayerControllerInputYawLeft(PlayerController *self, bool value);
+extern void PlayerControllerInputBrake(PlayerController *self, bool value);
 
 DECL_REFLECT(PlayerController);
 decl_typeclass_impl(SceneNodeEntity, PlayerController);