Rumble on collisions (#4532)
This commit is contained in:
parent
10da6285fc
commit
7bf9a0a4a8
@ -118,6 +118,14 @@ InputManager::InputManager() : m_mode(BOOTSTRAP),
|
||||
Log::error("InputManager", "Failed to init SDL game controller: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) != 0)
|
||||
{
|
||||
Log::error("InputManager", "Failed to init SDL haptics: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
#endif
|
||||
#endif // SERVER_ONLY
|
||||
}
|
||||
|
||||
@ -217,6 +225,14 @@ void InputManager::handleJoystick(SDL_Event& event)
|
||||
Log::error("SDLController", "Error in handleJoystick() %s", e.what());
|
||||
}
|
||||
} // handleJoystick
|
||||
|
||||
SDLController* InputManager::getSDLController(unsigned i) {
|
||||
assert(i < m_sdl_controller.size());
|
||||
auto it = m_sdl_controller.begin();
|
||||
for(unsigned j = 0; j < i; ++j)
|
||||
it++;
|
||||
return it->second.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -120,6 +120,8 @@ public:
|
||||
const irr::SEvent& getEventForGamePad(unsigned i) const;
|
||||
|
||||
void handleJoystick(SDL_Event& event);
|
||||
|
||||
SDLController* getSDLController(unsigned i);
|
||||
#endif
|
||||
|
||||
void dispatchInput(Input::InputType, int deviceID, int btnID,
|
||||
|
@ -43,6 +43,7 @@ SDLController::SDLController(int device_id)
|
||||
irr::SEvent::SJoystickEvent::NUMBER_OF_AXES * sizeof(int16_t));
|
||||
m_game_controller = NULL;
|
||||
m_joystick = NULL;
|
||||
m_haptic = NULL;
|
||||
m_id = -1;
|
||||
|
||||
if (SDL_IsGameController(device_id))
|
||||
@ -177,6 +178,13 @@ SDLController::SDLController(int device_id)
|
||||
if (created)
|
||||
cfg->initSDLMapping();
|
||||
cfg->setPlugged();
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
m_haptic = SDL_HapticOpenFromJoystick(m_joystick);
|
||||
if (m_haptic)
|
||||
SDL_HapticRumbleInit(m_haptic);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < dm->getGamePadAmount(); i++)
|
||||
{
|
||||
GamePadDevice* d = dm->getGamePad(i);
|
||||
@ -206,6 +214,10 @@ SDLController::~SDLController()
|
||||
SDL_GameControllerClose(m_game_controller);
|
||||
else
|
||||
SDL_JoystickClose(m_joystick);
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
if (m_haptic)
|
||||
SDL_HapticClose(m_haptic);
|
||||
#endif
|
||||
m_gamepad->getConfiguration()->unPlugged();
|
||||
m_gamepad->setIrrIndex(-1);
|
||||
m_gamepad->setConnected(false);
|
||||
@ -247,6 +259,22 @@ void SDLController::checkPowerLevel()
|
||||
#endif
|
||||
} // checkPowerLevel
|
||||
|
||||
void SDLController::doRumble(float strength_low, float strength_high, uint32_t duration_ms)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
if (m_haptic)
|
||||
{
|
||||
SDL_HapticRumblePlay(m_haptic, (strength_low + strength_high) / 2, duration_ms);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint16_t scaled_low = strength_low * pow(2, 16);
|
||||
uint16_t scaled_high = strength_high * pow(2, 16);
|
||||
SDL_GameControllerRumble(m_game_controller, scaled_low, scaled_high, duration_ms);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifdef ANDROID
|
||||
void SDLController::handleDirectScanCode(const SDL_Event& event)
|
||||
|
@ -27,6 +27,11 @@
|
||||
#include <bitset>
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <SDL_version.h>
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
#include <SDL_haptic.h>
|
||||
#endif
|
||||
|
||||
class GamePadDevice;
|
||||
|
||||
class SDLController
|
||||
@ -38,6 +43,10 @@ private:
|
||||
|
||||
GamePadDevice* m_gamepad;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
SDL_Haptic* m_haptic;
|
||||
#endif
|
||||
|
||||
int m_buttons;
|
||||
|
||||
int m_axes;
|
||||
@ -152,6 +161,9 @@ public:
|
||||
SDL_GameController* getGameController() const { return m_game_controller; }
|
||||
// ------------------------------------------------------------------------
|
||||
void checkPowerLevel();
|
||||
// ------------------------------------------------------------------------
|
||||
void doRumble(float strength_low, float strength_high, uint32_t duration_ms);
|
||||
GamePadDevice* getGamePadDevice() const { return m_gamepad; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -309,6 +309,12 @@ void Attachment::hitBanana(ItemState *item_state)
|
||||
{
|
||||
HitEffect* he = new Explosion(m_kart->getXYZ(), "explosion",
|
||||
"explosion_bomb.xml");
|
||||
// Rumble!
|
||||
Controller* controller = m_kart->getController();
|
||||
if (controller && controller->isLocalPlayerController())
|
||||
{
|
||||
controller->rumble(0, 0.8f, 500);
|
||||
}
|
||||
if (m_kart->getController()->isLocalPlayerController())
|
||||
he->setLocalPlayerKartHit();
|
||||
ProjectileManager::get()->addHitEffect(he);
|
||||
@ -520,6 +526,12 @@ void Attachment::update(int ticks)
|
||||
{
|
||||
HitEffect* he = new Explosion(m_kart->getXYZ(), "explosion",
|
||||
"explosion_bomb.xml");
|
||||
// Rumble!
|
||||
Controller* controller = m_kart->getController();
|
||||
if (controller && controller->isLocalPlayerController())
|
||||
{
|
||||
controller->rumble(0, 0.8f, 500);
|
||||
}
|
||||
if (m_kart->getController()->isLocalPlayerController())
|
||||
he->setLocalPlayerKartHit();
|
||||
ProjectileManager::get()->addHitEffect(he);
|
||||
|
@ -612,6 +612,13 @@ void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object,
|
||||
if (RaceManager::get()->isLinearRaceMode())
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ALL_HITS_1RACE, 1);
|
||||
}
|
||||
|
||||
// Rumble!
|
||||
Controller* controller = kart->getController();
|
||||
if (controller && controller->isLocalPlayerController())
|
||||
{
|
||||
controller->rumble(0, 0.8f, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
virtual bool disableSlipstreamBonus() const = 0;
|
||||
virtual bool saveState(BareNetworkString *buffer) const = 0;
|
||||
virtual void rewindTo(BareNetworkString *buffer) = 0;
|
||||
|
||||
virtual void rumble(float strength_low, float strength_high, uint16_t duration) {}
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Sets the controller name for this controller. */
|
||||
virtual void setControllerName(const std::string &name)
|
||||
|
@ -50,6 +50,10 @@
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/gamepad_device.hpp"
|
||||
#include "input/sdl_controller.hpp"
|
||||
|
||||
/** The constructor for a loca player kart, i.e. a player that is playing
|
||||
* on this machine (non-local player would be network clients).
|
||||
* \param kart_name Name of the kart.
|
||||
@ -62,6 +66,7 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart,
|
||||
HandicapLevel h)
|
||||
: PlayerController(kart)
|
||||
{
|
||||
m_last_crash = 0;
|
||||
m_has_started = false;
|
||||
m_handicap = h;
|
||||
m_player = StateManager::get()->getActivePlayer(local_player_id);
|
||||
@ -128,6 +133,7 @@ void LocalPlayerController::initParticleEmitter()
|
||||
void LocalPlayerController::reset()
|
||||
{
|
||||
PlayerController::reset();
|
||||
m_last_crash = 0;
|
||||
m_sound_schedule = false;
|
||||
m_has_started = false;
|
||||
} // reset
|
||||
@ -225,7 +231,7 @@ void LocalPlayerController::steer(int ticks, int steer_val)
|
||||
video::SColor(255, 255, 0, 255), false);
|
||||
}
|
||||
PlayerController::steer(ticks, steer_val);
|
||||
|
||||
|
||||
if(UserConfigParams::m_gamepad_debug)
|
||||
{
|
||||
Log::debug("LocalPlayerController", " set to: %f\n",
|
||||
@ -414,7 +420,7 @@ void LocalPlayerController::collectedItem(const ItemState &item_state,
|
||||
} // collectedItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** If the nitro level has gone under the nitro goal, play a bad effect sound
|
||||
/** If the nitro level has gone under the nitro goal, play a bad effect sound
|
||||
*/
|
||||
void LocalPlayerController::nitroNotFullSound()
|
||||
{
|
||||
@ -429,7 +435,7 @@ void LocalPlayerController::nitroNotFullSound()
|
||||
* collect achievements - synching to online account will happen
|
||||
* next time the account gets online.
|
||||
*/
|
||||
bool LocalPlayerController::canGetAchievements() const
|
||||
bool LocalPlayerController::canGetAchievements() const
|
||||
{
|
||||
return !RewindManager::get()->isRewinding() &&
|
||||
m_player->getConstProfile() == PlayerManager::getCurrentPlayer();
|
||||
@ -447,3 +453,48 @@ core::stringw LocalPlayerController::getName(bool include_handicap_string) const
|
||||
|
||||
return name;
|
||||
} // getName
|
||||
|
||||
void LocalPlayerController::doCrashHaptics() {
|
||||
#ifndef SERVER_ONLY
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return;
|
||||
int now = World::getWorld()->getTicksSinceStart();
|
||||
int lastCrash = m_last_crash;
|
||||
m_last_crash = now;
|
||||
if ((now - lastCrash) < stk_config->time2Ticks(0.2f))
|
||||
return;
|
||||
|
||||
float strength =
|
||||
pow(2, (abs(m_player->getKart()->getVelocity().length())) / 15.0f) - 1.0f;
|
||||
rumble(strength, strength, 200);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayerController::rumble(float strength_low, float strength_high, uint16_t duration) {
|
||||
#ifndef SERVER_ONLY
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return;
|
||||
int count = input_manager->getGamepadCount();
|
||||
while(count--)
|
||||
{
|
||||
SDLController* controller = input_manager->getSDLController(count);
|
||||
if (controller && controller->getGamePadDevice()->getPlayer() == m_player)
|
||||
{
|
||||
controller->doRumble(strength_low, strength_high, duration);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlayerController::crashed(const AbstractKart* k) {
|
||||
doCrashHaptics();
|
||||
|
||||
PlayerController::crashed(k);
|
||||
}
|
||||
|
||||
void LocalPlayerController::crashed(const Material *m) {
|
||||
doCrashHaptics();
|
||||
|
||||
PlayerController::crashed(m);
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ private:
|
||||
* camera object is managed in the Camera class, so no need to free it. */
|
||||
int m_camera_index;
|
||||
|
||||
int m_last_crash;
|
||||
|
||||
HandicapLevel m_handicap;
|
||||
|
||||
SFXBase *m_wee_sound;
|
||||
@ -65,6 +67,8 @@ private:
|
||||
virtual void displayPenaltyWarning() OVERRIDE;
|
||||
void nitroNotFullSound();
|
||||
|
||||
void doCrashHaptics();
|
||||
|
||||
public:
|
||||
LocalPlayerController(AbstractKart *kart,
|
||||
const int local_player_id,
|
||||
@ -83,6 +87,11 @@ public:
|
||||
virtual void resetInputState () OVERRIDE;
|
||||
virtual bool canGetAchievements() const OVERRIDE;
|
||||
|
||||
virtual void crashed(const AbstractKart *k) OVERRIDE;
|
||||
virtual void crashed(const Material *m) OVERRIDE;
|
||||
|
||||
virtual void rumble(float strength_low, float strength_high, uint16_t duration) OVERRIDE;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isPlayerController() const OVERRIDE {return true;}
|
||||
// ------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user