commit 3ec6cf25a28526d27b19a21dd5c08fc89c3350c5
Author: Michael Day <contact@michaelcday.com>
AuthorDate: Mon Oct 16 07:50:01 2023 -0400
Commit: Michael Day <contact@michaelcday.com>
CommitDate: Wed Oct 25 22:28:54 2023 -0400
Introduce gamepad analog control
---
src/doom/g_game.c | 78 ++++++++++++++++++++++++++++++++++++++++------------
src/i_joystick.c | 15 +++++++++-
src/i_joystick.h | 5 ++++
src/m_config.c | 24 ++++++++++++++++
src/setup/joystick.c | 54 ++++++++++++++++++++++++++++++------
5 files changed, 150 insertions(+), 26 deletions(-)
diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 91e97d73..b07ff570 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -35,6 +35,7 @@
#include "m_misc.h"
#include "m_menu.h"
#include "m_random.h"
+#include "i_joystick.h"
#include "i_system.h"
#include "i_timer.h"
#include "i_input.h"
@@ -380,11 +381,20 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
// fprintf(stderr, "strafe left\n");
side -= sidemove[speed];
}
- if (joyxmove > 0)
- side += sidemove[speed];
- if (joyxmove < 0)
- side -= sidemove[speed];
-
+ if (use_analog && joyxmove)
+ {
+ joyxmove = joyxmove * joystick_move_sensitivity / 10;
+ joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove;
+ joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove;
+ side += FixedMul(sidemove[speed], joyxmove);
+ }
+ else
+ {
+ if (joyxmove > 0)
+ side += sidemove[speed];
+ if (joyxmove < 0)
+ side -= sidemove[speed];
+ }
}
else
{
@@ -392,10 +402,21 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
cmd->angleturn -= angleturn[tspeed];
if (gamekeydown[key_left] || mousebuttons[mousebturnleft])
cmd->angleturn += angleturn[tspeed];
- if (joyxmove > 0)
- cmd->angleturn -= angleturn[tspeed];
- if (joyxmove < 0)
- cmd->angleturn += angleturn[tspeed];
+ if (use_analog && joyxmove)
+ {
+ // Cubic response curve allows for finer control when stick
+ // deflection is small.
+ joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove);
+ joyxmove = joyxmove * joystick_turn_sensitivity / 10;
+ cmd->angleturn -= FixedMul(angleturn[1], joyxmove);
+ }
+ else
+ {
+ if (joyxmove > 0)
+ cmd->angleturn -= angleturn[tspeed];
+ if (joyxmove < 0)
+ cmd->angleturn += angleturn[tspeed];
+ }
}
if (gamekeydown[key_up])
@@ -409,27 +430,50 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)
forward -= forwardmove[speed];
}
- if (joyymove < 0)
- forward += forwardmove[speed];
- if (joyymove > 0)
- forward -= forwardmove[speed];
+ if (use_analog && joyymove)
+ {
+ joyymove = joyymove * joystick_move_sensitivity / 10;
+ joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove;
+ joyymove = (joyymove < -FRACUNIT) ? -FRACUNIT : joyymove;
+ forward -= FixedMul(forwardmove[speed], joyymove);
+ }
+ else
+ {
+ if (joyymove < 0)
+ forward += forwardmove[speed];
+ if (joyymove > 0)
+ forward -= forwardmove[speed];
+ }
if (gamekeydown[key_strafeleft]
|| joybuttons[joybstrafeleft]
- || mousebuttons[mousebstrafeleft]
- || joystrafemove < 0)
+ || mousebuttons[mousebstrafeleft])
{
side -= sidemove[speed];
}
if (gamekeydown[key_straferight]
|| joybuttons[joybstraferight]
- || mousebuttons[mousebstraferight]
- || joystrafemove > 0)
+ || mousebuttons[mousebstraferight])
{
side += sidemove[speed];
}
+ if (use_analog && joystrafemove)
+ {
+ joystrafemove = joystrafemove * joystick_move_sensitivity / 10;
+ joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove;
+ joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove;
+ side += FixedMul(sidemove[speed], joystrafemove);
+ }
+ else
+ {
+ if (joystrafemove < 0)
+ side -= sidemove[speed];
+ if (joystrafemove > 0)
+ side += sidemove[speed];
+ }
+
// buttons
cmd->chatchar = HU_dequeueChatChar();
diff --git a/src/i_joystick.c b/src/i_joystick.c
index abf2177c..403e5e9b 100644
--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -30,6 +30,7 @@
#include "i_system.h"
#include "m_config.h"
+#include "m_fixed.h"
#include "m_misc.h"
static SDL_GameController *gamepad = NULL;
@@ -80,6 +81,12 @@ static int joystick_y_dead_zone = 33;
static int joystick_strafe_dead_zone = 33;
static int joystick_look_dead_zone = 33;
+int use_analog = 0;
+
+int joystick_turn_sensitivity = 10;
+int joystick_move_sensitivity = 10;
+int joystick_look_sensitivity = 10;
+
// Virtual to physical button joystick button mapping. By default this
// is a straight mapping.
static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
@@ -294,7 +301,7 @@ static int GetAxisStateGamepad(int axis, int invert, int dead_zone)
if (result < dead_zone && result > -dead_zone)
{
- result = 0;
+ return 0;
}
if (invert)
@@ -302,6 +309,8 @@ static int GetAxisStateGamepad(int axis, int invert, int dead_zone)
result = -result;
}
+ result *= FRACUNIT / 32768; // Want FXP number between -1 and 1
+
return result;
}
@@ -667,6 +676,10 @@ void I_BindJoystickVariables(void)
M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone);
M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone);
M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone);
+ M_BindIntVariable("use_analog", &use_analog);
+ M_BindIntVariable("joystick_turn_sensitivity", &joystick_turn_sensitivity);
+ M_BindIntVariable("joystick_move_sensitivity", &joystick_move_sensitivity);
+ M_BindIntVariable("joystick_look_sensitivity", &joystick_look_sensitivity);
for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i)
{
diff --git a/src/i_joystick.h b/src/i_joystick.h
index b99b8d24..9831ee1c 100644
--- a/src/i_joystick.h
+++ b/src/i_joystick.h
@@ -82,6 +82,11 @@ enum
GAMEPAD_BUTTON_MAX
};
+extern int use_analog;
+extern int joystick_turn_sensitivity;
+extern int joystick_move_sensitivity;
+extern int joystick_look_sensitivity;
+
void I_InitJoystick(void);
void I_ShutdownJoystick(void);
void I_UpdateJoystick(void);
diff --git a/src/m_config.c b/src/m_config.c
index 7c3e0e8a..57024b0f 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -1242,6 +1242,12 @@ static default_t extra_defaults_list[] =
CONFIG_VARIABLE_INT(joystick_index),
+ //!
+ // If non-zero, use analog movement when playing with a gamepad.
+ //
+
+ CONFIG_VARIABLE_INT(use_analog),
+
//!
// Joystick axis to use to for horizontal (X) movement.
//
@@ -1254,6 +1260,12 @@ static default_t extra_defaults_list[] =
CONFIG_VARIABLE_INT(joystick_x_invert),
+ //!
+ // Joystick turn analog sensitivity, specified as a value between 0 and 20.
+ //
+
+ CONFIG_VARIABLE_INT(joystick_turn_sensitivity),
+
//!
// Joystick axis to use to for vertical (Y) movement.
//
@@ -1279,6 +1291,12 @@ static default_t extra_defaults_list[] =
CONFIG_VARIABLE_INT(joystick_strafe_invert),
+ //!
+ // Joystick move and strafe analog sensitivity, specified as a value
+ // between 0 and 20.
+ //
+
+ CONFIG_VARIABLE_INT(joystick_move_sensitivity),
//!
// Joystick axis to use to for looking up and down.
//
@@ -1292,6 +1310,12 @@ static default_t extra_defaults_list[] =
CONFIG_VARIABLE_INT(joystick_look_invert),
+ //!
+ // Joystick look analog sensitivity, specified as a value between 0 and 20.
+ //
+
+ CONFIG_VARIABLE_INT(joystick_look_sensitivity),
+
//!
// The physical joystick button that corresponds to joystick
// virtual button #0.
diff --git a/src/setup/joystick.c b/src/setup/joystick.c
index 25bb0bdd..abb007f7 100644
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -92,6 +92,12 @@ static int joystick_y_dead_zone = 33;
static int joystick_strafe_dead_zone = 33;
static int joystick_look_dead_zone = 33;
+int use_analog = 0;
+
+int joystick_turn_sensitivity = 10;
+int joystick_move_sensitivity = 10;
+int joystick_look_sensitivity = 10;
+
// Virtual to physical mapping.
int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
@@ -1002,6 +1008,7 @@ static int CalibrationEventCallback(SDL_Event *event, void *user_data)
// joystick is being configured and which button the user is pressing.
usejoystick = 1;
use_gamepad = 0;
+ use_analog = 0;
gamepad_type = SDL_CONTROLLER_TYPE_UNKNOWN;
calibrate_button = event->jbutton.button;
@@ -1133,6 +1140,34 @@ static void SwapLRSticks(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused))
}
}
+static void AdjustAnalog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused))
+{
+ txt_window_t *window;
+
+ window = TXT_NewWindow("Analog Settings");
+ TXT_SetTableColumns(window, 2);
+ TXT_SetColumnWidths(window, 10, 6);
+ TXT_AddWidgets(window,
+ TXT_NewCheckBox("Use analog controls", &use_analog),
+ TXT_NewSeparator("Sensitivity"),
+ TXT_NewLabel("Movement"),
+ TXT_NewSpinControl(&joystick_move_sensitivity, 0, 20),
+ TXT_NewLabel("Turn"),
+ TXT_NewSpinControl(&joystick_turn_sensitivity, 0, 20),
+ NULL);
+ if (gamemission == heretic || gamemission == hexen || gamemission == strife)
+ {
+ TXT_AddWidgets(window,
+ TXT_NewLabel("Look"),
+ TXT_NewSpinControl(&joystick_look_sensitivity, 0, 20), NULL);
+ }
+ TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
+ TXT_SetWindowAction(window, TXT_HORIZ_CENTER,
+ TXT_NewWindowEscapeAction(window));
+ TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
+ TXT_SetWidgetAlign(window, TXT_HORIZ_CENTER);
+}
+
void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data)
{
txt_window_t *window;
@@ -1197,14 +1232,13 @@ void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data)
TXT_AddWidget(window,
TXT_NewConditional(&use_gamepad, 1,
- TXT_MakeTable(6,
- TXT_NewButton2("Swap L and R sticks", SwapLRSticks, NULL),
- TXT_TABLE_OVERFLOW_RIGHT,
- TXT_TABLE_OVERFLOW_RIGHT,
- TXT_TABLE_EMPTY,
- TXT_TABLE_EMPTY,
- TXT_TABLE_EMPTY,
- NULL)));
+ TXT_NewButton2("Swap L and R sticks", SwapLRSticks, NULL)));
+ TXT_AddWidget(window, TXT_TABLE_EOL);
+
+ TXT_AddWidget(window,
+ TXT_NewConditional(&use_gamepad, 1,
+ TXT_NewButton2("Analog settings", AdjustAnalog, NULL)));
+ TXT_AddWidget(window, TXT_TABLE_EOL);
TXT_AddWidget(window, TXT_NewSeparator("Buttons"));
@@ -1267,6 +1301,10 @@ void BindJoystickVariables(void)
M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone);
M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone);
M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone);
+ M_BindIntVariable("use_analog", &use_analog);
+ M_BindIntVariable("joystick_turn_sensitivity", &joystick_turn_sensitivity);
+ M_BindIntVariable("joystick_move_sensitivity", &joystick_move_sensitivity);
+ M_BindIntVariable("joystick_look_sensitivity", &joystick_look_sensitivity);
for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i)
{