Skip to content

Commit

Permalink
Rumble effects (fixes #172)
Browse files Browse the repository at this point in the history
  • Loading branch information
cxong committed Oct 30, 2015
1 parent 58f4a69 commit 9fb60b7
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/cdogs.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,9 @@ int main(int argc, char *argv[])
}

debug(D_NORMAL, "Initialising SDL...\n");
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | controllerFlag) != 0)
const int sdlFlags =
SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_HAPTIC;
if (SDL_Init(sdlFlags | controllerFlag) != 0)
{
fprintf(stderr, "Could not initialise SDL: %s\n", SDL_GetError());
err = EXIT_FAILURE;
Expand Down
16 changes: 16 additions & 0 deletions src/cdogs/handle_game_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
#include "actor_placement.h"
#include "ai_utils.h"
#include "damage.h"
#include "events.h"
#include "game_events.h"
#include "joystick.h"
#include "net_server.h"
#include "objs.h"
#include "particle.h"
Expand Down Expand Up @@ -110,6 +112,10 @@ static void HandleGameEvent(
camera->shake = ScreenShakeAdd(
camera->shake, e.u.ShakeAmount,
ConfigGetInt(&gConfig, "Graphics.ShakeMultiplier"));
// Weak rumble for all joysticks
CA_FOREACH(Joystick, j, gEventHandlers.joysticks)
JoyRumble(j->id, 0.3f, 500);
CA_FOREACH_END()
break;
case GAME_EVENT_SET_MESSAGE:
HUDDisplayMessage(
Expand Down Expand Up @@ -446,6 +452,16 @@ static void HandleGameEvent(
AddBloodSplatter(
a->Pos, e.u.ActorHit.Power,
Net2Vec2i(e.u.ActorHit.Vel));

// Rumble if taking hit
if (a->PlayerUID >= 0)
{
const PlayerData *p = PlayerDataGetByUID(a->PlayerUID);
if (p->inputDevice == INPUT_DEVICE_JOYSTICK)
{
JoyImpact(p->deviceIndex);
}
}
}
}
break;
Expand Down
72 changes: 68 additions & 4 deletions src/cdogs/joystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,16 @@ void JoyReset(CArray *joys)
CA_FOREACH_END()
}

static void JoyTerminateOne(Joystick *j)
{
SDL_GameControllerClose(j->gc);
SDL_HapticClose(j->haptic);
}

void JoyTerminate(CArray *joys)
{
CA_FOREACH(Joystick, j, *joys)
SDL_GameControllerClose(j->gc);
JoyTerminateOne(j);
CA_FOREACH_END()
CArrayTerminate(joys);
}
Expand Down Expand Up @@ -119,6 +125,7 @@ void JoyAdded(const Sint32 which)

Joystick j;
memset(&j, 0, sizeof j);
j.hapticEffectId = -1;
j.gc = SDL_GameControllerOpen(which);
if (j.gc == NULL)
{
Expand All @@ -140,6 +147,44 @@ void JoyAdded(const Sint32 which)
SDL_GetError());
return;
}
const int isHaptic = SDL_JoystickIsHaptic(j.j);
if (isHaptic > 0)
{
j.haptic = SDL_HapticOpenFromJoystick(j.j);
if (j.haptic == NULL)
{
LOG(LM_INPUT, LL_ERROR, "Failed to open haptic: %s",
SDL_GetError());
}
else
{
if (SDL_HapticRumbleInit(j.haptic) != 0)
{
LOG(LM_INPUT, LL_ERROR, "Failed to init rumble: %s",
SDL_GetError());
}
const int hapticQuery = SDL_HapticQuery(j.haptic);
LOG(LM_INPUT, LL_INFO, "Haptic support: %x", hapticQuery);
if (hapticQuery & SDL_HAPTIC_CONSTANT)
{
SDL_HapticEffect he;
memset(&he, 0, sizeof he);
he.type = SDL_HAPTIC_CONSTANT;
he.constant.length = 100;
he.constant.level = 20000; // 20000/32767 strength
j.hapticEffectId = SDL_HapticNewEffect(j.haptic, &he);
if (j.hapticEffectId == -1)
{
LOG(LM_INPUT, LL_ERROR,
"Failed to create haptic effect: %s", SDL_GetError());
}
}
}
}
else if (isHaptic < 0)
{
LOG(LM_INPUT, LL_ERROR, "Failed to query haptic: %s", SDL_GetError());
}
CArrayPushBack(&gEventHandlers.joysticks, &j);
LOG(LM_INPUT, LL_INFO, "Added joystick index %d id %d", which, j.id);
}
Expand All @@ -149,7 +194,7 @@ void JoyRemoved(const Sint32 which)
CA_FOREACH(Joystick, j, gEventHandlers.joysticks)
if (j->id == which)
{
SDL_GameControllerClose(j->gc);
JoyTerminateOne(j);
CArrayDelete(&gEventHandlers.joysticks, i);
return;
}
Expand Down Expand Up @@ -184,7 +229,6 @@ int ControllerButtonToCmd(const Uint8 button)
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: return CMD_RIGHT;
default: return 0;
}
// TODO: check button mappings
}
#define DEADZONE 16384
void JoyOnAxis(const SDL_ControllerAxisEvent e)
Expand All @@ -210,7 +254,6 @@ void JoyOnAxis(const SDL_ControllerAxisEvent e)
// Ignore axis
break;
}
// TODO: check other controllers
}

static void JoyOnCmd(Joystick *j, const int cmd, const bool isDown)
Expand All @@ -229,6 +272,27 @@ static void JoyOnCmd(Joystick *j, const int cmd, const bool isDown)
}
}

void JoyRumble(
const SDL_JoystickID id, const float strength, const Uint32 length)
{
Joystick *j = GetJoystick(id);
if (j->haptic == NULL) return;
if (SDL_HapticRumblePlay(j->haptic, strength, length) < 0)
{
LOG(LM_INPUT, LL_ERROR, "Failed to rumble: %s", SDL_GetError());
}
}
void JoyImpact(const SDL_JoystickID id)
{
Joystick *j = GetJoystick(id);
if (j->hapticEffectId != -1 &&
SDL_HapticRunEffect(j->haptic, j->hapticEffectId, 1) != 0)
{
LOG(LM_INPUT, LL_ERROR, "Failed to run haptic effect: %s",
SDL_GetError());
}
}

const char *JoyName(const SDL_JoystickID id)
{
const Joystick *j = GetJoystick(id);
Expand Down
7 changes: 7 additions & 0 deletions src/cdogs/joystick.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include <SDL_events.h>
#include <SDL_gamecontroller.h>
#include <SDL_haptic.h>

#include "c_array.h"
#include "color.h"
Expand All @@ -42,6 +43,8 @@ typedef struct
SDL_GameController *gc;
SDL_Joystick *j;
SDL_JoystickID id;
SDL_Haptic *haptic;
int hapticEffectId;
int currentCmd;
int previousCmd;
int pressedCmd;
Expand All @@ -63,6 +66,10 @@ void JoyOnButtonDown(const SDL_ControllerButtonEvent e);
void JoyOnButtonUp(const SDL_ControllerButtonEvent e);
void JoyOnAxis(const SDL_ControllerAxisEvent e);

void JoyRumble(
const SDL_JoystickID id, const float strength, const Uint32 length);
void JoyImpact(const SDL_JoystickID id);

const char *JoyName(const SDL_JoystickID id);
const char *JoyButtonNameColor(
const SDL_JoystickID id, const int cmd, color_t *color);

0 comments on commit 9fb60b7

Please sign in to comment.