100 lines
3.8 KiB
C
100 lines
3.8 KiB
C
#include "player_controller.h"
|
|
#include "core/render.h"
|
|
#include "utils/debug.h"
|
|
#include "core/input.h"
|
|
#include "raylib.h"
|
|
|
|
START_REFLECT(PlayerController);
|
|
REFLECT_TYPECLASS(PlayerController, Drop);
|
|
REFLECT_TYPECLASS(PlayerController, SceneNodeEntity);
|
|
END_REFLECT(PlayerController);
|
|
|
|
impl_Drop_for(PlayerController,
|
|
DestroyPlayerController
|
|
)
|
|
|
|
impl_SceneNodeEntity_for(PlayerController,
|
|
PlayerControllerEnterTree,
|
|
PlayerControllerExitTree,
|
|
PlayerControllerTick
|
|
)
|
|
|
|
SceneNode *CreatePlayerController() {
|
|
PlayerController *self = new(PlayerController);
|
|
self->rotation = self->fly_input = Vector2Zero();
|
|
self->stopped = false;
|
|
return CreateSceneNode(PlayerController_as_SceneNodeEntity(self));
|
|
}
|
|
|
|
void DestroyPlayerController(PlayerController *self) {
|
|
free(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));
|
|
}
|
|
|
|
void PlayerControllerExitTree(PlayerController *self) {
|
|
RemoveAllListeners(self);
|
|
}
|
|
|
|
//! 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)));
|
|
}
|
|
|
|
//! linear acceleration limited to the local Z axis
|
|
static
|
|
void PlayerControllerTickLinearAcceleration(PlayerController *self, double delta) {
|
|
float const target = self->stopped ? 10.f : (self->rotation.y == 0.f ? 30.f : 20.f);
|
|
float const speed_diff = target - self->speed;
|
|
self->speed = self->speed + copysignf(fminf(fabsf(speed_diff), 10.f * delta), speed_diff);
|
|
}
|
|
|
|
//! Update linear transform based on velocities
|
|
static
|
|
void PlayerControllerTickTransform(PlayerController *self, double delta) {
|
|
Transform global_transform = self->transform.tc->get_global_transform(self->transform.data);
|
|
Matrix global_matrix = TransformGetMatrix(global_transform);
|
|
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);
|
|
self->transform.tc->set_global_transform(self->transform.data, global_transform);
|
|
}
|
|
|
|
void PlayerControllerTick(PlayerController *self, double delta) {
|
|
PlayerControllerTickAngularAcceleration(self, delta);
|
|
PlayerControllerTickLinearAcceleration(self, delta);
|
|
PlayerControllerTickTransform(self, delta);
|
|
}
|
|
|
|
void PlayerControllerLeftInput(PlayerController *self, bool value) {
|
|
self->fly_input.x += value ? -1 : +1;
|
|
}
|
|
|
|
void PlayerControllerRightInput(PlayerController *self, bool value) {
|
|
self->fly_input.x += value ? +1 : -1;
|
|
}
|
|
|
|
void PlayerControllerUpInput(PlayerController *self, bool value) {
|
|
self->fly_input.y += value ? -1 : +1;
|
|
}
|
|
|
|
void PlayerControllerDownInput(PlayerController *self, bool value) {
|
|
self->fly_input.y += value ? +1 : -1;
|
|
}
|
|
|
|
void PlayerControllerStopInput(PlayerController *self, bool value) {
|
|
self->stopped = value;
|
|
}
|