mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Initial Gamepad support
Adds initial ingame gamepad support to minetest. Full Formspec support is not implemented yet and can be added by a later change.
This commit is contained in:
parent
1e86c89f36
commit
2060fd9cbe
17 changed files with 577 additions and 80 deletions
167
src/game.cpp
167
src/game.cpp
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "client.h"
|
||||
#include "client/tile.h" // For TextureSource
|
||||
#include "client/keys.h"
|
||||
#include "client/joystick_controller.h"
|
||||
#include "clientmap.h"
|
||||
#include "clouds.h"
|
||||
#include "config.h"
|
||||
|
@ -1108,12 +1109,14 @@ bool nodePlacementPrediction(Client &client,
|
|||
static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
|
||||
InventoryManager *invmgr, IGameDef *gamedef,
|
||||
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
||||
JoystickController *joystick,
|
||||
IFormSource *fs_src, TextDest *txt_dest, Client *client)
|
||||
{
|
||||
|
||||
if (*cur_formspec == 0) {
|
||||
*cur_formspec = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr,
|
||||
invmgr, gamedef, tsrc, fs_src, txt_dest, client);
|
||||
*cur_formspec = new GUIFormSpecMenu(device, joystick,
|
||||
guiroot, -1, &g_menumgr, invmgr, gamedef, tsrc,
|
||||
fs_src, txt_dest, client);
|
||||
(*cur_formspec)->doPause = false;
|
||||
|
||||
/*
|
||||
|
@ -1138,7 +1141,8 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
|
|||
|
||||
static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
|
||||
InventoryManager *invmgr, IGameDef *gamedef,
|
||||
IWritableTextureSource *tsrc, IrrlichtDevice *device, Client *client)
|
||||
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
||||
JoystickController *joystick, Client *client)
|
||||
{
|
||||
std::string formspec =
|
||||
std::string(FORMSPEC_VERSION_STRING) +
|
||||
|
@ -1154,14 +1158,15 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
|
|||
FormspecFormSource *fs_src = new FormspecFormSource(formspec);
|
||||
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client);
|
||||
|
||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
|
||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device,
|
||||
joystick, fs_src, txt_dst, NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
|
||||
InventoryManager *invmgr, IGameDef *gamedef,
|
||||
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
||||
bool singleplayermode)
|
||||
JoystickController *joystick, bool singleplayermode)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
std::string control_text = strgettext("Default Controls:\n"
|
||||
|
@ -1226,7 +1231,8 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
|
|||
FormspecFormSource *fs_src = new FormspecFormSource(os.str());
|
||||
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
|
||||
|
||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
|
||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device,
|
||||
joystick, fs_src, txt_dst, NULL);
|
||||
std::string con("btn_continue");
|
||||
(*cur_formspec)->setFocus(con);
|
||||
(*cur_formspec)->doPause = true;
|
||||
|
@ -1574,9 +1580,10 @@ protected:
|
|||
void decreaseViewRange(float *statustext_time);
|
||||
void toggleFullViewRange(float *statustext_time);
|
||||
|
||||
void updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags);
|
||||
void updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags,
|
||||
float dtime);
|
||||
void updateCameraOrientation(CameraOrientation *cam,
|
||||
const VolatileRunFlags &flags);
|
||||
const VolatileRunFlags &flags, float dtime);
|
||||
void updatePlayerControl(const CameraOrientation &cam);
|
||||
void step(f32 *dtime);
|
||||
void processClientEvents(CameraOrientation *cam, float *damage_flash);
|
||||
|
@ -1611,34 +1618,39 @@ protected:
|
|||
static void settingChangedCallback(const std::string &setting_name, void *data);
|
||||
void readSettings();
|
||||
|
||||
bool getLeftClicked()
|
||||
inline bool getLeftClicked()
|
||||
{
|
||||
return input->getLeftClicked();
|
||||
return input->getLeftClicked() ||
|
||||
input->joystick.getWasKeyDown(KeyType::MOUSE_L);
|
||||
}
|
||||
bool getRightClicked()
|
||||
inline bool getRightClicked()
|
||||
{
|
||||
return input->getRightClicked();
|
||||
return input->getRightClicked() ||
|
||||
input->joystick.getWasKeyDown(KeyType::MOUSE_R);
|
||||
}
|
||||
bool isLeftPressed()
|
||||
inline bool isLeftPressed()
|
||||
{
|
||||
return input->getLeftState();
|
||||
return input->getLeftState() ||
|
||||
input->joystick.isKeyDown(KeyType::MOUSE_L);
|
||||
}
|
||||
bool isRightPressed()
|
||||
inline bool isRightPressed()
|
||||
{
|
||||
return input->getRightState();
|
||||
return input->getRightState() ||
|
||||
input->joystick.isKeyDown(KeyType::MOUSE_R);
|
||||
}
|
||||
bool getLeftReleased()
|
||||
inline bool getLeftReleased()
|
||||
{
|
||||
return input->getLeftReleased();
|
||||
return input->getLeftReleased() ||
|
||||
input->joystick.wasKeyReleased(KeyType::MOUSE_L);
|
||||
}
|
||||
|
||||
bool isKeyDown(GameKeyType k)
|
||||
inline bool isKeyDown(GameKeyType k)
|
||||
{
|
||||
return input->isKeyDown(keycache.key[k]);
|
||||
return input->isKeyDown(keycache.key[k]) || input->joystick.isKeyDown(k);
|
||||
}
|
||||
bool wasKeyDown(GameKeyType k)
|
||||
inline bool wasKeyDown(GameKeyType k)
|
||||
{
|
||||
return input->wasKeyDown(keycache.key[k]);
|
||||
return input->wasKeyDown(keycache.key[k]) || input->joystick.wasKeyDown(k);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
@ -1724,9 +1736,11 @@ private:
|
|||
*/
|
||||
bool m_cache_doubletap_jump;
|
||||
bool m_cache_enable_clouds;
|
||||
bool m_cache_enable_joysticks;
|
||||
bool m_cache_enable_particles;
|
||||
bool m_cache_enable_fog;
|
||||
f32 m_cache_mouse_sensitivity;
|
||||
f32 m_cache_joystick_frustum_sensitivity;
|
||||
f32 m_repeat_right_click_time;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
@ -1762,12 +1776,16 @@ Game::Game() :
|
|||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("enable_clouds",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("doubletap_joysticks",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("enable_particles",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("enable_fog",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("mouse_sensitivity",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("joystick_frustum_sensitivity",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("repeat_rightclick_time",
|
||||
&settingChangedCallback, this);
|
||||
|
||||
|
@ -1930,7 +1948,7 @@ void Game::run()
|
|||
updateProfilers(runData, stats, draw_times, dtime);
|
||||
processUserInput(&flags, &runData, dtime);
|
||||
// Update camera before player movement to avoid camera lag of one frame
|
||||
updateCameraDirection(&cam_view_target, &flags);
|
||||
updateCameraDirection(&cam_view_target, &flags, dtime);
|
||||
float cam_smoothing = 0;
|
||||
if (g_settings->getBool("cinematic"))
|
||||
cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing");
|
||||
|
@ -2727,7 +2745,8 @@ void Game::processKeyInput(VolatileRunFlags *flags,
|
|||
} else if (wasKeyDown(KeyType::ESC) || input->wasKeyDown(CancelKey)) {
|
||||
if (!gui_chat_console->isOpenInhibited()) {
|
||||
show_pause_menu(¤t_formspec, client, gamedef,
|
||||
texture_src, device, simple_singleplayer_mode);
|
||||
texture_src, device, &input->joystick,
|
||||
simple_singleplayer_mode);
|
||||
}
|
||||
} else if (wasKeyDown(KeyType::CHAT)) {
|
||||
openConsole(0.2, L"");
|
||||
|
@ -2813,12 +2832,21 @@ void Game::processItemSelection(u16 *new_playeritem)
|
|||
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
|
||||
player->hud_hotbar_itemcount - 1);
|
||||
|
||||
if (wheel < 0)
|
||||
*new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0;
|
||||
else if (wheel > 0)
|
||||
*new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item;
|
||||
// else wheel == 0
|
||||
s32 dir = wheel;
|
||||
|
||||
if (input->joystick.wasKeyDown(KeyType::SCROLL_DOWN)) {
|
||||
dir = -1;
|
||||
}
|
||||
|
||||
if (input->joystick.wasKeyDown(KeyType::SCROLL_UP)) {
|
||||
dir = 1;
|
||||
}
|
||||
|
||||
if (dir < 0)
|
||||
*new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0;
|
||||
else if (dir > 0)
|
||||
*new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item;
|
||||
// else dir == 0
|
||||
|
||||
/* Item selection using keyboard
|
||||
*/
|
||||
|
@ -2868,7 +2896,7 @@ void Game::openInventory()
|
|||
TextDest *txt_dst = new TextDestPlayerInventory(client);
|
||||
|
||||
create_formspec_menu(¤t_formspec, client, gamedef, texture_src,
|
||||
device, fs_src, txt_dst, client);
|
||||
device, &input->joystick, fs_src, txt_dst, client);
|
||||
|
||||
InventoryLocation inventoryloc;
|
||||
inventoryloc.setCurrentPlayer();
|
||||
|
@ -3154,7 +3182,7 @@ void Game::toggleFullViewRange(float *statustext_time)
|
|||
|
||||
|
||||
void Game::updateCameraDirection(CameraOrientation *cam,
|
||||
VolatileRunFlags *flags)
|
||||
VolatileRunFlags *flags, float dtime)
|
||||
{
|
||||
if ((device->isWindowActive() && noMenuActive()) || random_input) {
|
||||
|
||||
|
@ -3169,7 +3197,7 @@ void Game::updateCameraDirection(CameraOrientation *cam,
|
|||
if (flags->first_loop_after_window_activation)
|
||||
flags->first_loop_after_window_activation = false;
|
||||
else
|
||||
updateCameraOrientation(cam, *flags);
|
||||
updateCameraOrientation(cam, *flags, dtime);
|
||||
|
||||
input->setMousePos((driver->getScreenSize().Width / 2),
|
||||
(driver->getScreenSize().Height / 2));
|
||||
|
@ -3187,9 +3215,8 @@ void Game::updateCameraDirection(CameraOrientation *cam,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Game::updateCameraOrientation(CameraOrientation *cam,
|
||||
const VolatileRunFlags &flags)
|
||||
const VolatileRunFlags &flags, float dtime)
|
||||
{
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
if (g_touchscreengui) {
|
||||
|
@ -3197,6 +3224,7 @@ void Game::updateCameraOrientation(CameraOrientation *cam,
|
|||
cam->camera_pitch = g_touchscreengui->getPitch();
|
||||
} else {
|
||||
#endif
|
||||
|
||||
s32 dx = input->getMousePos().X - (driver->getScreenSize().Width / 2);
|
||||
s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height / 2);
|
||||
|
||||
|
@ -3212,6 +3240,14 @@ void Game::updateCameraOrientation(CameraOrientation *cam,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (m_cache_enable_joysticks) {
|
||||
f32 c = m_cache_joystick_frustum_sensitivity * (1.f / 32767.f) * dtime;
|
||||
cam->camera_yaw -= input->joystick.getAxisWithoutDead(JA_FRUSTUM_HORIZONTAL) *
|
||||
c;
|
||||
cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) *
|
||||
c;
|
||||
}
|
||||
|
||||
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5);
|
||||
}
|
||||
|
||||
|
@ -3220,30 +3256,36 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
|
|||
{
|
||||
//TimeTaker tt("update player control", NULL, PRECISION_NANO);
|
||||
|
||||
// DO NOT use the isKeyDown method for the forward, backward, left, right
|
||||
// buttons, as the code that uses the controls needs to be able to
|
||||
// distinguish between the two in order to know when to use joysticks.
|
||||
|
||||
PlayerControl control(
|
||||
input->isKeyDown(keycache.key[KeyType::FORWARD]),
|
||||
input->isKeyDown(keycache.key[KeyType::BACKWARD]),
|
||||
input->isKeyDown(keycache.key[KeyType::LEFT]),
|
||||
input->isKeyDown(keycache.key[KeyType::RIGHT]),
|
||||
input->isKeyDown(keycache.key[KeyType::JUMP]),
|
||||
input->isKeyDown(keycache.key[KeyType::SPECIAL1]),
|
||||
input->isKeyDown(keycache.key[KeyType::SNEAK]),
|
||||
input->getLeftState(),
|
||||
input->getRightState(),
|
||||
isKeyDown(KeyType::JUMP),
|
||||
isKeyDown(KeyType::SPECIAL1),
|
||||
isKeyDown(KeyType::SNEAK),
|
||||
isLeftPressed(),
|
||||
isRightPressed(),
|
||||
cam.camera_pitch,
|
||||
cam.camera_yaw
|
||||
cam.camera_yaw,
|
||||
input->joystick.getAxisWithoutDead(JA_SIDEWARD_MOVE),
|
||||
input->joystick.getAxisWithoutDead(JA_FORWARD_MOVE)
|
||||
);
|
||||
|
||||
u32 keypress_bits =
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::FORWARD]) & 0x1) << 0) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::BACKWARD]) & 0x1) << 1) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::LEFT]) & 0x1) << 2) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::RIGHT]) & 0x1) << 3) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::JUMP]) & 0x1) << 4) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::SPECIAL1]) & 0x1) << 5) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyType::SNEAK]) & 0x1) << 6) |
|
||||
( (u32)(input->getLeftState() & 0x1) << 7) |
|
||||
( (u32)(input->getRightState() & 0x1) << 8
|
||||
( (u32)(isKeyDown(KeyType::FORWARD) & 0x1) << 0) |
|
||||
( (u32)(isKeyDown(KeyType::BACKWARD) & 0x1) << 1) |
|
||||
( (u32)(isKeyDown(KeyType::LEFT) & 0x1) << 2) |
|
||||
( (u32)(isKeyDown(KeyType::RIGHT) & 0x1) << 3) |
|
||||
( (u32)(isKeyDown(KeyType::JUMP) & 0x1) << 4) |
|
||||
( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) |
|
||||
( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) |
|
||||
( (u32)(isLeftPressed() & 0x1) << 7) |
|
||||
( (u32)(isRightPressed() & 0x1) << 8
|
||||
);
|
||||
|
||||
#ifdef ANDROID
|
||||
|
@ -3312,7 +3354,7 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash)
|
|||
cam->camera_pitch = event.player_force_move.pitch;
|
||||
} else if (event.type == CE_DEATHSCREEN) {
|
||||
show_deathscreen(¤t_formspec, client, gamedef, texture_src,
|
||||
device, client);
|
||||
device, &input->joystick, client);
|
||||
|
||||
chat_backend->addMessage(L"", L"You died.");
|
||||
|
||||
|
@ -3328,7 +3370,8 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash)
|
|||
new TextDestPlayerInventory(client, *(event.show_formspec.formname));
|
||||
|
||||
create_formspec_menu(¤t_formspec, client, gamedef,
|
||||
texture_src, device, fs_src, txt_dst, client);
|
||||
texture_src, device, &input->joystick,
|
||||
fs_src, txt_dst, client);
|
||||
|
||||
delete(event.show_formspec.formspec);
|
||||
delete(event.show_formspec.formname);
|
||||
|
@ -3723,8 +3766,14 @@ void Game::processPlayerInteraction(GameRunData *runData,
|
|||
input->resetLeftClicked();
|
||||
input->resetRightClicked();
|
||||
|
||||
input->joystick.clearWasKeyDown(KeyType::MOUSE_L);
|
||||
input->joystick.clearWasKeyDown(KeyType::MOUSE_R);
|
||||
|
||||
input->resetLeftReleased();
|
||||
input->resetRightReleased();
|
||||
|
||||
input->joystick.clearWasKeyReleased(KeyType::MOUSE_L);
|
||||
input->joystick.clearWasKeyReleased(KeyType::MOUSE_R);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3785,7 +3834,7 @@ void Game::handlePointingAtNode(GameRunData *runData,
|
|||
TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
|
||||
|
||||
create_formspec_menu(¤t_formspec, client, gamedef,
|
||||
texture_src, device, fs_src, txt_dst, client);
|
||||
texture_src, device, &input->joystick, fs_src, txt_dst, client);
|
||||
|
||||
current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
|
||||
} else {
|
||||
|
@ -4468,12 +4517,14 @@ void Game::settingChangedCallback(const std::string &setting_name, void *data)
|
|||
|
||||
void Game::readSettings()
|
||||
{
|
||||
m_cache_doubletap_jump = g_settings->getBool("doubletap_jump");
|
||||
m_cache_enable_clouds = g_settings->getBool("enable_clouds");
|
||||
m_cache_enable_particles = g_settings->getBool("enable_particles");
|
||||
m_cache_enable_fog = g_settings->getBool("enable_fog");
|
||||
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity");
|
||||
m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time");
|
||||
m_cache_doubletap_jump = g_settings->getBool("doubletap_jump");
|
||||
m_cache_enable_clouds = g_settings->getBool("enable_clouds");
|
||||
m_cache_enable_joysticks = g_settings->getBool("enable_joysticks");
|
||||
m_cache_enable_particles = g_settings->getBool("enable_particles");
|
||||
m_cache_enable_fog = g_settings->getBool("enable_fog");
|
||||
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity");
|
||||
m_cache_joystick_frustum_sensitivity = g_settings->getFloat("joystick_frustum_sensitivity");
|
||||
m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time");
|
||||
|
||||
m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue