From 998a727e6ed8dc2c3ab081b866518ea16d692628 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Thu, 14 Sep 2023 19:16:56 +0300 Subject: [PATCH 1/2] PC: implement joystick support Use glfw to get the joystick position. Add a new global variable `joystick` which is set to the active joystick ID (or to -1, if no joysticks are detected). For simplicity, for now we pick the first available joystick, but later we could make it configurable. --- source/platform/input.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/source/platform/input.c b/source/platform/input.c index cc3de78e..98b242e7 100644 --- a/source/platform/input.c +++ b/source/platform/input.c @@ -32,6 +32,7 @@ extern GLFWwindow* window; static bool input_pointer_enabled; static double input_old_pointer_x, input_old_pointer_y; static bool input_key_held[1024]; +static int joystick = -1; void input_init() { for(int k = 0; k < 1024; k++) @@ -40,6 +41,27 @@ void input_init() { input_pointer_enabled = false; input_old_pointer_x = 0; input_old_pointer_y = 0; + + // Find joystick + glfwInit(); + for(int joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) { + int num_axes = 0; + const float *axes = glfwGetJoystickAxes(joy, &num_axes); + if(num_axes < 2) continue; + + /* Workaround some buggy motherboard which reports the LED controller + * as a joystick; in such cases the controller is reported as having a + * ridiculously high number of axes. See for example: + * https://bbs.archlinux.org/viewtopic.php?id=261161 + */ + if (num_axes >= 10) { + fprintf(stderr, "Skipping controller '%s' with %d axes\n", + glfwGetJoystickName(joy), num_axes); + continue; + } + joystick = joy; + break; + } } void input_poll() { } @@ -103,6 +125,8 @@ bool input_pointer(float* x, float* y, float* angle) { } void input_native_joystick(float dt, float* dx, float* dy) { + *dx = 0.0F; + *dy = 0.0F; if(!input_pointer_enabled) { double x2, y2; glfwGetCursorPos(window, &x2, &y2); @@ -110,9 +134,13 @@ void input_native_joystick(float dt, float* dx, float* dy) { *dy = -(y2 - input_old_pointer_y) * 0.001F; input_old_pointer_x = x2; input_old_pointer_y = y2; - } else { - *dx = 0.0F; - *dy = 0.0F; + } else if(joystick >= 0) { + int num_axes = 0; + const float *axes = glfwGetJoystickAxes(joystick, &num_axes); + if(axes && num_axes >= 2) { + *dx = axes[0] * dt; + *dy = -axes[1] * dt; + } } } From 11f6381d406c3cce54ea97aaa6198912594c2b1c Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Thu, 14 Sep 2023 19:20:22 +0300 Subject: [PATCH 2/2] input: use joystick for moving, pointer for rotation Implement a control style a la "The Conduit", where the pointer is used to rotate the camera, and the joystick is used for moving. This still needs some work (we probably want to show a small pointer on the Wii screen, because currently it's hard to know where exactly you are pointing at), but should give an idea. Having playing "The COnduit" for a while, this feels much more natural to me. This depends on #17 in order to be tested on the PC. Addresses issue #1. --- source/game/camera.c | 19 +++++++++++++++---- source/game/gui/screen_ingame.c | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/source/game/camera.c b/source/game/camera.c index fbd53d3a..903c4873 100644 --- a/source/game/camera.c +++ b/source/game/camera.c @@ -104,14 +104,25 @@ void camera_ray_pick(struct world* w, float gx0, float gy0, float gz0, void camera_physics(struct camera* c, float dt) { assert(c); - float jdx, jdy; - if(input_joystick(dt, &jdx, &jdy)) { - c->rx -= jdx * 2.0F; - c->ry -= jdy * 2.0F; + float px, py, pangle; + const float rotation_c = 20.0F; + if(input_pointer(&px, &py, &pangle)) { + c->rx -= (px - gfx_width() / 2) / (gfx_width() * rotation_c); + c->ry += (py - gfx_height() / 2) / (gfx_height() * rotation_c); + // pangle could be used for rz, but that would be veeery weird :-) } float acc_x = 0, acc_y = 0, acc_z = 0; float speed_c = 40.0F; + + float jdx, jdy; + if(input_joystick(dt, &jdx, &jdy)) { + float joy_speed_c = 40.0F * speed_c; + acc_x += (cos(c->rx) * -jdx + sin(c->rx) * sin(c->ry) * jdy) * joy_speed_c; + acc_y += cos(c->ry) * jdy * speed_c; + acc_z += (sin(c->rx) * jdx + cos(c->rx) * sin(c->ry) * jdy) * joy_speed_c; + } + float air_friction = 0.05F; if(input_held(IB_LEFT)) { diff --git a/source/game/gui/screen_ingame.c b/source/game/gui/screen_ingame.c index 33458896..c8bf189d 100644 --- a/source/game/gui/screen_ingame.c +++ b/source/game/gui/screen_ingame.c @@ -30,7 +30,7 @@ #include static void screen_ingame_reset(struct screen* s, int width, int height) { - input_pointer_enable(false); + input_pointer_enable(true); } void screen_ingame_render3D(struct screen* s, mat4 view) {