Compare commits
No commits in common. "1b7b915548da503993ceebdadd8d5c2784c7fcbf" and "62c36b96600ea90eb32d9618844306a835fc4240" have entirely different histories.
1b7b915548
...
62c36b9660
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,4 @@
|
||||||
#include "camera_controller.h"
|
#include "camera_controller.h"
|
||||||
#include "core/camera_node.h"
|
|
||||||
#include "utils/mirror.h"
|
#include "utils/mirror.h"
|
||||||
|
|
||||||
START_REFLECT(CameraController);
|
START_REFLECT(CameraController);
|
||||||
|
@ -19,11 +18,10 @@ SceneNode *CreateCameraController(Transformable target) {
|
||||||
CameraController *self = new(CameraController);
|
CameraController *self = new(CameraController);
|
||||||
*self = (CameraController){
|
*self = (CameraController){
|
||||||
.transform = tc_null(Transformable),
|
.transform = tc_null(Transformable),
|
||||||
.rotation_speed = 2.f,
|
.rotation_speed = 5.f,
|
||||||
.max_speed_time = 4.f,
|
.max_speed_time = 4.f,
|
||||||
.target = target,
|
.target = target,
|
||||||
.time_rotated = 0.f,
|
.time_rotated = 0.f
|
||||||
.camera = NULL,
|
|
||||||
};
|
};
|
||||||
SceneNode *node = CreateSceneNode(CameraController_as_SceneNodeEntity(self));
|
SceneNode *node = CreateSceneNode(CameraController_as_SceneNodeEntity(self));
|
||||||
return node;
|
return node;
|
||||||
|
@ -36,9 +34,6 @@ void DestroyCameraController(CameraController *self) {
|
||||||
void CameraControllerEnterTree(CameraController *self) {
|
void CameraControllerEnterTree(CameraController *self) {
|
||||||
self->transform = TC_CAST(self->node->parent->entity, Transformable);
|
self->transform = TC_CAST(self->node->parent->entity, Transformable);
|
||||||
self->global = self->transform.tc->get_global_transform(self->transform.data);
|
self->global = self->transform.tc->get_global_transform(self->transform.data);
|
||||||
SceneNode *camera_node = SceneNodeGetChildByTypeid(self->node->parent, GET_TYPEID(CameraNode), true);
|
|
||||||
self->camera = camera_node->entity.data;
|
|
||||||
self->camera->fov = 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraControllerExitTree(CameraController *self) {}
|
void CameraControllerExitTree(CameraController *self) {}
|
||||||
|
@ -54,10 +49,11 @@ void CameraControllerTick(CameraController *self, double delta) {
|
||||||
// ... and maximum frame step size
|
// ... and maximum frame step size
|
||||||
float const step = self->rotation_speed * time_mul * delta;
|
float const step = self->rotation_speed * time_mul * delta;
|
||||||
if(angle > 0.f)
|
if(angle > 0.f)
|
||||||
target.rotation = QuaternionSlerp(current.rotation, target.rotation, step);
|
target.rotation = QuaternionSlerp(current.rotation, target.rotation, fminf(fminf(step, angle) / angle, 0.99f));
|
||||||
if(step > angle && self->time_rotated > delta)
|
if(step > angle && self->time_rotated > delta)
|
||||||
self->time_rotated -= delta;
|
self->time_rotated -= 3.f * delta;
|
||||||
else
|
else if(step > angle)
|
||||||
self->time_rotated += delta;
|
self->time_rotated = 0.f;
|
||||||
|
self->time_rotated += delta;
|
||||||
self->transform.tc->set_global_transform(self->transform.data, target);
|
self->transform.tc->set_global_transform(self->transform.data, target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ typedef struct CameraController {
|
||||||
float max_speed_time;
|
float max_speed_time;
|
||||||
Transformable target;
|
Transformable target;
|
||||||
float time_rotated;
|
float time_rotated;
|
||||||
CameraNode *camera;
|
|
||||||
} CameraController;
|
} CameraController;
|
||||||
|
|
||||||
extern SceneNode *CreateCameraController(Transformable target);
|
extern SceneNode *CreateCameraController(Transformable target);
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
#include "city_generator.h"
|
|
||||||
#include "core/mesh_render_entity.h"
|
|
||||||
#include "core/transform_node.h"
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
size_t x, y;
|
|
||||||
} const CITY_SIZE = {20, 20};
|
|
||||||
|
|
||||||
#define MODELS_LENGTH 4
|
|
||||||
static ModelResource models[MODELS_LENGTH] = {
|
|
||||||
ResourceEmpty(Model),
|
|
||||||
ResourceEmpty(Model),
|
|
||||||
ResourceEmpty(Model),
|
|
||||||
ResourceEmpty(Model)
|
|
||||||
};
|
|
||||||
|
|
||||||
static void Internal_LoadModelsIfRequired() {
|
|
||||||
for(size_t i = 0; i < MODELS_LENGTH; ++i)
|
|
||||||
if(models[i].handle == NULL && GetModelResource(TextFormat("building_%c", 'a' + i), &models[i]))
|
|
||||||
LoadResource(models[i].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SceneNode *Internal_CreateBuilding(size_t x, size_t y) {
|
|
||||||
size_t building_index = (3 * (x + y + GetRandomValue(0, 50))) % MODELS_LENGTH; // semi-random number based on the x,y coordinate
|
|
||||||
SceneNode *mesh_render_node = CreateMeshRenderEntity(TextFormat("building_%c", 'a' + building_index));
|
|
||||||
SceneNode *transform_node = CreateTransformNode();
|
|
||||||
SceneNodeAddChild(transform_node, mesh_render_node);
|
|
||||||
Transformable transform = TC_CAST(transform_node->entity, Transformable);
|
|
||||||
Transform local = transform.tc->get_transform(transform.data);
|
|
||||||
local.translation.x = (float)(x * 40);
|
|
||||||
local.translation.z = (float)(y * 40);
|
|
||||||
transform.tc->set_transform(transform.data, local);
|
|
||||||
return transform_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneNode *GenerateCity() {
|
|
||||||
Internal_LoadModelsIfRequired();
|
|
||||||
SceneNode *root = CreateTransformNode();
|
|
||||||
for(size_t x = 0; x < CITY_SIZE.x; ++x) {
|
|
||||||
for(size_t y = 0; y < CITY_SIZE.y; ++y) {
|
|
||||||
SceneNodeAddChild(root, Internal_CreateBuilding(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return root;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
#ifndef CITY_GENERATOR_H
|
|
||||||
#define CITY_GENERATOR_H
|
|
||||||
|
|
||||||
#include "core/scene.h"
|
|
||||||
|
|
||||||
extern SceneNode *GenerateCity();
|
|
||||||
|
|
||||||
#endif // !CITY_GENERATOR_H
|
|
|
@ -20,11 +20,6 @@ impl_SceneNodeEntity_for(CameraNode,
|
||||||
|
|
||||||
SceneNode *CreateCameraNode() {
|
SceneNode *CreateCameraNode() {
|
||||||
CameraNode *self = new(CameraNode);
|
CameraNode *self = new(CameraNode);
|
||||||
*self = (CameraNode){
|
|
||||||
.fov = 60,
|
|
||||||
.node = NULL,
|
|
||||||
.transform = tc_null(Transformable)
|
|
||||||
};
|
|
||||||
return CreateSceneNode(CameraNode_as_SceneNodeEntity(self));
|
return CreateSceneNode(CameraNode_as_SceneNodeEntity(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +51,7 @@ Camera3D CameraNodeGetCamera(CameraNode *self) {
|
||||||
Vector3 forward = MATRIX_FORWARD(mat);
|
Vector3 forward = MATRIX_FORWARD(mat);
|
||||||
// construct a new camera at the global transform location and facing the forward vector
|
// construct a new camera at the global transform location and facing the forward vector
|
||||||
return (Camera3D){
|
return (Camera3D){
|
||||||
.fovy = self->fov,
|
.fovy = 90,
|
||||||
.position = global_transform.translation,
|
.position = global_transform.translation,
|
||||||
.projection = CAMERA_PERSPECTIVE,
|
.projection = CAMERA_PERSPECTIVE,
|
||||||
.target = Vector3Add(global_transform.translation, forward),
|
.target = Vector3Add(global_transform.translation, forward),
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
typedef struct CameraNode {
|
typedef struct CameraNode {
|
||||||
SceneNode *node;
|
SceneNode *node;
|
||||||
Transformable transform;
|
Transformable transform;
|
||||||
float fov;
|
|
||||||
} CameraNode;
|
} CameraNode;
|
||||||
|
|
||||||
//! Instantiate new camera node
|
//! Instantiate new camera node
|
||||||
|
|
|
@ -54,6 +54,7 @@ void RenderNextFrame() {
|
||||||
BeginMode3D(CameraNodeGetCamera(camera));
|
BeginMode3D(CameraNodeGetCamera(camera));
|
||||||
list_foreach(Renderable *,object, &g_render_objects)
|
list_foreach(Renderable *,object, &g_render_objects)
|
||||||
object->tc->draw(object->data);
|
object->tc->draw(object->data);
|
||||||
|
DrawGrid(500, 1.f); // TODO Remove this (or make it a scene node entity)
|
||||||
EndMode3D();
|
EndMode3D();
|
||||||
}
|
}
|
||||||
DrawFPS(20, 20);
|
DrawFPS(20, 20);
|
||||||
|
|
|
@ -132,9 +132,9 @@ bool GetModelResource(char const *path, ModelResource *out) {
|
||||||
ResourceContainer *container = hash_map_get_as(ResourceContainer, &g_resource_map, &path);
|
ResourceContainer *container = hash_map_get_as(ResourceContainer, &g_resource_map, &path);
|
||||||
*out = ResourceEmpty(Model);
|
*out = ResourceEmpty(Model);
|
||||||
// assert some assumptions about the found resource
|
// assert some assumptions about the found resource
|
||||||
ASSERT_RETURN(container != NULL, false, "GetModelResource: Resource %s not in index.", path);
|
ASSERT_RETURN(container != NULL, false, "GetTextureResource: Resource %s not in index.", path);
|
||||||
ASSERT_RETURN(container->type == RESOURCE_MODEL, false, "GetModelResource: Resource %s is not a Texture.", path);
|
ASSERT_RETURN(container->type == RESOURCE_MODEL, false, "GetTextureResource: Resource %s is not a Texture.", path);
|
||||||
ASSERT_RETURN(strcmp(container->name, path) == 0, false, "GetModelResource: Resource %s was loaded for path %s", container->name, path);
|
++container->use_counter;
|
||||||
*out = (ModelResource) {
|
*out = (ModelResource) {
|
||||||
.handle = container,
|
.handle = container,
|
||||||
.resource = &container->model
|
.resource = &container->model
|
||||||
|
@ -174,20 +174,16 @@ bool IsResourceLoaded(ResourceHandle handle) {
|
||||||
|
|
||||||
void LoadResource(ResourceHandle handle) {
|
void LoadResource(ResourceHandle handle) {
|
||||||
ASSERT_RETURN(handle != NULL,, "LoadResource: Resource handle invalid");
|
ASSERT_RETURN(handle != NULL,, "LoadResource: Resource handle invalid");
|
||||||
if(!handle->is_loaded) {
|
g_load_functions[handle->type](handle);
|
||||||
g_load_functions[handle->type](handle);
|
handle->is_loaded = true;
|
||||||
handle->is_loaded = true;
|
|
||||||
}
|
|
||||||
++handle->use_counter;
|
++handle->use_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseResource(ResourceHandle handle) {
|
void ReleaseResource(ResourceHandle handle) {
|
||||||
ASSERT_RETURN(handle != NULL,, "ReleaseResource: Resource handle invalid");
|
ASSERT_RETURN(handle != NULL,, "ReleaseResource: Resource handle invalid");
|
||||||
ASSERT_RETURN_WARN(handle->is_loaded,, "ReleaseResource: Resource %s is not loaded.", handle->path);
|
ASSERT_RETURN_WARN(handle->is_loaded,, "ReleaseResource: Resource %s is not loaded.", handle->path);
|
||||||
if(handle->use_counter == 1) {
|
g_unload_functions[handle->type](handle);
|
||||||
g_unload_functions[handle->type](handle);
|
handle->is_loaded = false;
|
||||||
handle->is_loaded = false;
|
|
||||||
}
|
|
||||||
--handle->use_counter;
|
--handle->use_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,23 +170,8 @@ SceneNode *SceneNodeGetChildByTypeclass(SceneNode *self, char const *typeclass,
|
||||||
SceneNodeEntity entity = (*child)->entity;
|
SceneNodeEntity entity = (*child)->entity;
|
||||||
if(mirror_get_function(entity.data, entity.mirror, typeclass))
|
if(mirror_get_function(entity.data, entity.mirror, typeclass))
|
||||||
return *child;
|
return *child;
|
||||||
if(recurse) {
|
if(recurse)
|
||||||
SceneNode *recursed = SceneNodeGetChildByTypeclass(*child, typeclass, recurse);
|
SceneNodeGetChildByTypeclass(*child, typeclass, recurse);
|
||||||
if(recursed != NULL) return recursed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneNode *SceneNodeGetChildByTypeid(SceneNode *self, typeid id, bool recurse) {
|
|
||||||
list_foreach(SceneNode **,child, &self->children) {
|
|
||||||
SceneNodeEntity entity = (*child)->entity;
|
|
||||||
if(entity.mirror->get_typeid() == id)
|
|
||||||
return *child;
|
|
||||||
if(recurse) {
|
|
||||||
SceneNode *recursed = SceneNodeGetChildByTypeid(*child, id, recurse);
|
|
||||||
if(recursed != NULL) return recursed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,10 @@ extern void SceneNodeRemoveChild(SceneNode *self, SceneNode *child);
|
||||||
extern void SceneNodeAttachEntity(SceneNode *self, SceneNodeEntity entity);
|
extern void SceneNodeAttachEntity(SceneNode *self, SceneNodeEntity entity);
|
||||||
//! Detach an entity from a scene node
|
//! Detach an entity from a scene node
|
||||||
extern SceneNodeEntity SceneNodeDetachEntity(SceneNode *self);
|
extern SceneNodeEntity SceneNodeDetachEntity(SceneNode *self);
|
||||||
//! Returns the first child node with an entity that implements a specific typeclass.
|
//! Returns the first child node that implements a specific typeclass.
|
||||||
//! Optionally recurses through the entire branch
|
//! Optionally recurses through the entire branch
|
||||||
extern SceneNode *SceneNodeGetChildByTypeclass(SceneNode *self, char const *typeclass, bool recurse);
|
extern SceneNode *SceneNodeGetChildByTypeclass(SceneNode *self, char const *typeclass, bool recurse);
|
||||||
//! Returns the first child node with an entity that matches the given typeid.
|
|
||||||
//! Optionally recurses through the entire branch.
|
|
||||||
extern SceneNode *SceneNodeGetChildByTypeid(SceneNode *self, typeid id, bool recurse);
|
|
||||||
//! Instantiate a new scene with a root node.
|
//! Instantiate a new scene with a root node.
|
||||||
extern Scene *CreateScene(SceneNode *root);
|
extern Scene *CreateScene(SceneNode *root);
|
||||||
//! Destroy a node and it's scene tree.
|
//! Destroy a node and it's scene tree.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "player_controller.h"
|
#include "player_controller.h"
|
||||||
#include "camera_controller.h"
|
#include "camera_controller.h"
|
||||||
#include "city_generator.h"
|
|
||||||
#include "core/input.h"
|
#include "core/input.h"
|
||||||
#include "core/camera_node.h"
|
#include "core/camera_node.h"
|
||||||
#include "core/engine_global.h"
|
#include "core/engine_global.h"
|
||||||
|
@ -49,7 +48,6 @@ Scene *CreateInitialScene() {
|
||||||
SceneNodeAddChild(root, model);
|
SceneNodeAddChild(root, model);
|
||||||
SceneNodeAddChild(root, camera_scene);
|
SceneNodeAddChild(root, camera_scene);
|
||||||
SceneNodeAddChild(camera_scene, CreateCameraController(TC_CAST(model->entity, Transformable)));
|
SceneNodeAddChild(camera_scene, CreateCameraController(TC_CAST(model->entity, Transformable)));
|
||||||
SceneNodeAddChild(root, GenerateCity());
|
|
||||||
return CreateScene(root);
|
return CreateScene(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +56,7 @@ void ConfigureInput() {
|
||||||
AddAction("pitch_down", INPUT_LISTENER_KEY, 0, KEY_W);
|
AddAction("pitch_down", INPUT_LISTENER_KEY, 0, KEY_W);
|
||||||
AddAction("roll_left", INPUT_LISTENER_KEY, 0, KEY_A);
|
AddAction("roll_left", INPUT_LISTENER_KEY, 0, KEY_A);
|
||||||
AddAction("roll_right", INPUT_LISTENER_KEY, 0, KEY_D);
|
AddAction("roll_right", INPUT_LISTENER_KEY, 0, KEY_D);
|
||||||
AddAction("yaw_right", INPUT_LISTENER_KEY, 0, KEY_E);
|
AddAction("stop", INPUT_LISTENER_KEY, 0, KEY_SPACE);
|
||||||
AddAction("yaw_left", INPUT_LISTENER_KEY, 0, KEY_Q);
|
|
||||||
AddAction("brake", INPUT_LISTENER_KEY, 0, KEY_SPACE);
|
|
||||||
AddAction("boost", INPUT_LISTENER_KEY, 0, KEY_LEFT_SHIFT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include "player_controller.h"
|
#include "player_controller.h"
|
||||||
#include "core/render.h"
|
#include "core/render.h"
|
||||||
#include "core/input.h"
|
|
||||||
#include "utils/typeclass_helpers.h"
|
|
||||||
#include "utils/debug.h"
|
#include "utils/debug.h"
|
||||||
|
#include "core/input.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
START_REFLECT(PlayerController);
|
START_REFLECT(PlayerController);
|
||||||
|
@ -20,25 +19,10 @@ impl_SceneNodeEntity_for(PlayerController,
|
||||||
PlayerControllerTick
|
PlayerControllerTick
|
||||||
)
|
)
|
||||||
|
|
||||||
static float const PLAYER_BASE_SPEED = 10.f;
|
|
||||||
static float const PLAYER_BASE_ACCELERATION = 10.f;
|
|
||||||
static float const PLAYER_BOOST_SPEED = 30.f;
|
|
||||||
static float const PLAYER_BOOST_ACCELERATION = 60.f;
|
|
||||||
static float const PLAYER_BRAKE_SPEED = 0.5f;
|
|
||||||
static float const PLAYER_BRAKE_DECELERATION = 10.f;
|
|
||||||
static float const PLAYER_FALL_SPEED = 10.f;
|
|
||||||
static float const PLAYER_FALL_ACCELERATION = 10.f;
|
|
||||||
|
|
||||||
SceneNode *CreatePlayerController() {
|
SceneNode *CreatePlayerController() {
|
||||||
PlayerController *self = new(PlayerController);
|
PlayerController *self = new(PlayerController);
|
||||||
*self = (PlayerController) {
|
self->rotation = self->fly_input = Vector2Zero();
|
||||||
.node = NULL,
|
self->stopped = false;
|
||||||
.transform = tc_null(Transformable),
|
|
||||||
.rotation = Vector3Zero(),
|
|
||||||
.fly_input = Vector3Zero(),
|
|
||||||
.speed = 10.f,
|
|
||||||
.brake = false
|
|
||||||
};
|
|
||||||
return CreateSceneNode(PlayerController_as_SceneNodeEntity(self));
|
return CreateSceneNode(PlayerController_as_SceneNodeEntity(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,42 +33,32 @@ void DestroyPlayerController(PlayerController *self) {
|
||||||
void PlayerControllerEnterTree(PlayerController *self) {
|
void PlayerControllerEnterTree(PlayerController *self) {
|
||||||
self->transform = TC_CAST(self->node->parent->entity, Transformable);
|
self->transform = TC_CAST(self->node->parent->entity, Transformable);
|
||||||
DisableCursor();
|
DisableCursor();
|
||||||
AddListener("pitch_up", ButtonInputListener(self, PlayerControllerInputPitchUp));
|
AddListener("pitch_up", ButtonInputListener(self, PlayerControllerUpInput));
|
||||||
AddListener("pitch_down", ButtonInputListener(self, PlayerControllerInputPitchDown));
|
AddListener("pitch_down", ButtonInputListener(self, PlayerControllerDownInput));
|
||||||
AddListener("roll_left", ButtonInputListener(self, PlayerControllerInputRollLeft));
|
AddListener("roll_left", ButtonInputListener(self, PlayerControllerLeftInput));
|
||||||
AddListener("roll_right", ButtonInputListener(self, PlayerControllerInputRollRight));
|
AddListener("roll_right", ButtonInputListener(self, PlayerControllerRightInput));
|
||||||
AddListener("yaw_left", ButtonInputListener(self, PlayerControllerInputYawLeft));
|
AddListener("stop", ButtonInputListener(self, PlayerControllerStopInput));
|
||||||
AddListener("yaw_right", ButtonInputListener(self, PlayerControllerInputYawRight));
|
|
||||||
AddListener("brake", ButtonInputListener(self, PlayerControllerInputBrake));
|
|
||||||
AddListener("boost", ButtonInputListener(self, PlayerControllerInputBoost));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControllerExitTree(PlayerController *self) {
|
void PlayerControllerExitTree(PlayerController *self) {
|
||||||
RemoveAllListeners(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
|
//! angular acceleration limited to local X and Z axes
|
||||||
static
|
static
|
||||||
void PlayerControllerTickAngularAcceleration(PlayerController *self, double delta) {
|
void PlayerControllerTickAngularAcceleration(PlayerController *self, double delta) {
|
||||||
self->rotation.x = MoveTowards(self->rotation.x, self->fly_input.x, delta * 4.f);
|
Vector2 diff = Vector2Subtract(self->fly_input, self->rotation);
|
||||||
self->rotation.y = MoveTowards(self->rotation.y, self->fly_input.y, delta * 4.f);
|
float const length = Vector2Length(diff);
|
||||||
self->rotation.z = MoveTowards(self->rotation.z, self->fly_input.z, delta * 4.f);
|
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
|
//! linear acceleration limited to the local Z axis
|
||||||
static
|
static
|
||||||
void PlayerControllerTickLinearAcceleration(PlayerController *self, double delta) {
|
void PlayerControllerTickLinearAcceleration(PlayerController *self, double delta) {
|
||||||
float const target = self->brake ? PLAYER_BRAKE_SPEED : (self->boost ? PLAYER_BOOST_SPEED : PLAYER_BASE_SPEED);
|
float const target = self->stopped ? 10.f : (self->rotation.y == 0.f ? 30.f : 20.f);
|
||||||
float const acceleration = target < self->speed ? PLAYER_BRAKE_DECELERATION : (self->boost ? PLAYER_BOOST_ACCELERATION : PLAYER_BASE_ACCELERATION);
|
float const speed_diff = target - self->speed;
|
||||||
self->speed = MoveTowards(self->speed, target, delta * acceleration);
|
self->speed = self->speed + copysignf(fminf(fabsf(speed_diff), 10.f * delta), speed_diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Update linear transform based on velocities
|
//! Update linear transform based on velocities
|
||||||
|
@ -92,11 +66,9 @@ static
|
||||||
void PlayerControllerTickTransform(PlayerController *self, double delta) {
|
void PlayerControllerTickTransform(PlayerController *self, double delta) {
|
||||||
Transform global_transform = self->transform.tc->get_global_transform(self->transform.data);
|
Transform global_transform = self->transform.tc->get_global_transform(self->transform.data);
|
||||||
Matrix global_matrix = TransformGetMatrix(global_transform);
|
Matrix global_matrix = TransformGetMatrix(global_transform);
|
||||||
float const rotate_speed = 1.f - 0.9f * self->speed / PLAYER_BOOST_SPEED;
|
|
||||||
global_transform.translation = Vector3Add(global_transform.translation, Vector3Scale(MATRIX_FORWARD(global_matrix), self->speed * 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 * 1.25f * delta), global_transform.rotation);
|
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 * rotate_speed * 3.75f * 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 * rotate_speed * 1.f * delta), global_transform.rotation);
|
|
||||||
self->transform.tc->set_global_transform(self->transform.data, global_transform);
|
self->transform.tc->set_global_transform(self->transform.data, global_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,34 +78,22 @@ void PlayerControllerTick(PlayerController *self, double delta) {
|
||||||
PlayerControllerTickTransform(self, delta);
|
PlayerControllerTickTransform(self, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControllerInputRollLeft(PlayerController *self, bool value) {
|
void PlayerControllerLeftInput(PlayerController *self, bool value) {
|
||||||
self->fly_input.x += value ? -1 : +1;
|
self->fly_input.x += value ? -1 : +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControllerInputRollRight(PlayerController *self, bool value) {
|
void PlayerControllerRightInput(PlayerController *self, bool value) {
|
||||||
self->fly_input.x += value ? +1 : -1;
|
self->fly_input.x += value ? +1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControllerInputPitchUp(PlayerController *self, bool value) {
|
void PlayerControllerUpInput(PlayerController *self, bool value) {
|
||||||
self->fly_input.y += value ? -1 : +1;
|
self->fly_input.y += value ? -1 : +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControllerInputPitchDown(PlayerController *self, bool value) {
|
void PlayerControllerDownInput(PlayerController *self, bool value) {
|
||||||
self->fly_input.y += value ? +1 : -1;
|
self->fly_input.y += value ? +1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerControllerInputYawRight(PlayerController *self, bool value) {
|
void PlayerControllerStopInput(PlayerController *self, bool value) {
|
||||||
self->fly_input.z += value ? -1 : +1;
|
self->stopped = value;
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerControllerInputYawLeft(PlayerController *self, bool value) {
|
|
||||||
self->fly_input.z += value ? +1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerControllerInputBrake(PlayerController *self, bool value) {
|
|
||||||
self->brake = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerControllerInputBoost(PlayerController *self, bool value) {
|
|
||||||
self->boost = value;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,10 @@
|
||||||
typedef struct PlayerController {
|
typedef struct PlayerController {
|
||||||
SceneNode *node;
|
SceneNode *node;
|
||||||
Transformable transform;
|
Transformable transform;
|
||||||
Vector3 fly_input;
|
Vector2 fly_input;
|
||||||
Vector3 rotation;
|
Vector2 rotation;
|
||||||
float speed;
|
float speed;
|
||||||
bool brake;
|
bool stopped;
|
||||||
bool boost;
|
|
||||||
} PlayerController;
|
} PlayerController;
|
||||||
|
|
||||||
SceneNode *CreatePlayerController();
|
SceneNode *CreatePlayerController();
|
||||||
|
@ -26,14 +25,11 @@ extern void PlayerControllerEnterTree(PlayerController *self);
|
||||||
extern void PlayerControllerExitTree(PlayerController *self);
|
extern void PlayerControllerExitTree(PlayerController *self);
|
||||||
extern void PlayerControllerTick(PlayerController *self, double delta);
|
extern void PlayerControllerTick(PlayerController *self, double delta);
|
||||||
|
|
||||||
extern void PlayerControllerInputRollLeft(PlayerController *self, bool value);
|
extern void PlayerControllerLeftInput(PlayerController *self, bool value);
|
||||||
extern void PlayerControllerInputRollRight(PlayerController *self, bool value);
|
extern void PlayerControllerRightInput(PlayerController *self, bool value);
|
||||||
extern void PlayerControllerInputPitchUp(PlayerController *self, bool value);
|
extern void PlayerControllerUpInput(PlayerController *self, bool value);
|
||||||
extern void PlayerControllerInputPitchDown(PlayerController *self, bool value);
|
extern void PlayerControllerDownInput(PlayerController *self, bool value);
|
||||||
extern void PlayerControllerInputYawRight(PlayerController *self, bool value);
|
extern void PlayerControllerStopInput(PlayerController *self, bool value);
|
||||||
extern void PlayerControllerInputYawLeft(PlayerController *self, bool value);
|
|
||||||
extern void PlayerControllerInputBrake(PlayerController *self, bool value);
|
|
||||||
extern void PlayerControllerInputBoost(PlayerController *self, bool value);
|
|
||||||
|
|
||||||
DECL_REFLECT(PlayerController);
|
DECL_REFLECT(PlayerController);
|
||||||
decl_typeclass_impl(SceneNodeEntity, PlayerController);
|
decl_typeclass_impl(SceneNodeEntity, PlayerController);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit bb201d5085cfb2e54ebad9a0bf22347a5251f7a2
|
Subproject commit faf0463e3791ee97dfc370282ecad4cd3b4ca475
|
Loading…
Reference in a new issue