Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/player/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <Arduino.h>

#include "player/controller-properties.h"
#include "player/rumble.h"

namespace Player
{
Expand Down Expand Up @@ -33,6 +34,8 @@ namespace Player
virtual AnalogStick leftAnalog() = 0;
virtual AnalogStick rightAnalog() = 0;

virtual void rumble(RumbleOptions option) = 0;

virtual const uint8_t rawButtonState(const ControllerButton button) const = 0;
virtual const bool wasPressed(const ControllerButton button) const = 0;
virtual const bool wasPressedAndReleased(const ControllerButton button) const = 0;
Expand Down
11 changes: 11 additions & 0 deletions include/player/ps3-controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <Ps3Controller.h>
#include "player/controller.h"
#include "player/rumble.h"

namespace Player
{
Expand Down Expand Up @@ -34,6 +35,8 @@ namespace Player
AnalogStick leftAnalog() override;
AnalogStick rightAnalog() override;

void rumble(RumbleOptions option) override;

const uint8_t rawButtonState(const ControllerButton button) const;
const bool wasPressed(const ControllerButton button) const;
const bool wasPressedAndReleased(const ControllerButton button) const;
Expand All @@ -45,12 +48,20 @@ namespace Player
::Ps3Controller *controller;
static Ps3Controller *instance;

static void playRumblePattern(RumblePattern pattern);
static void rumbleTask(void *pvParameters);
void triggerRumble(const RumblePattern &pattern);
void handleOnConnect();
static void onConnect()
{
if (instance)
instance->handleOnConnect();
}
struct RumbleTaskParams
{
Ps3Controller *instance;
const RumblePattern *pattern;
};
};
}
#endif
54 changes: 54 additions & 0 deletions include/player/rumble.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once

#include <cstddef>

#include "common.h"

namespace Player
{
enum class RumbleOptions
{
SingleQuickPulse,
DoubleQuickPulse,
DeathPulse
};

struct RumbleStep
{
int intensity;
int duration;
};

class RumblePattern
{
public:
template <uint16_t N>
RumblePattern(const RumbleStep (&steps)[N]) : steps(steps), count(N) {}

const RumbleStep *getSteps() const { return steps; }
size_t getCount() const { return count; }

private:
const RumbleStep *steps;
size_t count;
};

static const RumbleStep singleQuickSteps[] = {
{200, 100}};
static const RumbleStep doubleQuickSteps[] = {
{255, 100},
{0, 100},
{200, 100}};
static const RumbleStep deathSteps[] = {
{255, 100},
{0, 100},
{255, 400},
{0, 100},
{255, 100},
{0, 100},
{255, 400}};
static const RumblePattern singleQuickRumbleSeq{singleQuickSteps};
static const RumblePattern doubleQuickRumbleSeq{doubleQuickSteps};
static const RumblePattern deathRumbleSeq{deathSteps};

}
1 change: 1 addition & 0 deletions src/games/demo/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Games::Demo
{
incrementCurrentScore();
contextManager->stateManager.displayShouldUpdate = true;
contextManager->controller.rumble(::Player::RumbleOptions::SingleQuickPulse);
logf("Current score: %d", getCurrentScore());
}
auto leftInput = contextManager->controller.leftAnalog();
Expand Down
2 changes: 2 additions & 0 deletions src/games/phase-evasion/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace Games::PhaseEvasion
flare.impacted = true;
state.current = Actions::MuzzleFlash;
gameOverPhaseShift = static_cast<float>(((SystemCore::Configuration::numLeds() / 2) + player.getPosition()) % SystemCore::Configuration::numLeds());
contextManager->controller.rumble(::Player::RumbleOptions::DeathPulse);
wait(20);
}
}
Expand Down Expand Up @@ -158,6 +159,7 @@ namespace Games::PhaseEvasion
gem.capture();
contextManager->stateManager.getPhaseEvasionGameState().gemsCaptured++;
contextManager->stateManager.displayShouldUpdate = true;
contextManager->controller.rumble(::Player::RumbleOptions::DoubleQuickPulse);
gem.wait(gemRespawnDelay);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/games/phase-evasion/flare-manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Games::PhaseEvasion
{
contextManager->stateManager.getPhaseEvasionGameState().flaresEvaded++;
contextManager->stateManager.displayShouldUpdate = true;
contextManager->controller.rumble(Player::RumbleOptions::SingleQuickPulse);
flare.completedCycle = false;
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/games/recall/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ namespace Games::Recall
state.current = Actions::PlayerResponseEvaluation;
sequenceIndex = 0;
contextManager->controller.reset();
contextManager->controller.rumble(::Player::RumbleOptions::SingleQuickPulse);
successFadeawayAnimation = 1;
log("Ready for User playback");
return;
Expand All @@ -136,6 +137,7 @@ namespace Games::Recall
state.incrementScore();

contextManager->controller.reset();
contextManager->controller.rumble(::Player::RumbleOptions::DoubleQuickPulse);
wait(gameplaySpeedIlluminated * 2);
return;
}
Expand All @@ -160,6 +162,7 @@ namespace Games::Recall
}

logf("User provided the incorrect answer. Entering game over sequence.");
contextManager->controller.rumble(::Player::RumbleOptions::DeathPulse);
state.current = Actions::GameOver;
}
}
Expand Down
61 changes: 61 additions & 0 deletions src/player/ps3-controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ namespace Player
return joystick;
}

void Ps3Controller::rumble(RumbleOptions option)
{
const RumblePattern *pattern = nullptr;

switch (option)
{
case RumbleOptions::DoubleQuickPulse:
pattern = &doubleQuickRumbleSeq;
break;
case RumbleOptions::SingleQuickPulse:
pattern = &singleQuickRumbleSeq;
break;
case RumbleOptions::DeathPulse:
pattern = &deathRumbleSeq;
break;
default:
break;
}

triggerRumble(*pattern);
}

const uint8_t Ps3Controller::rawButtonState(const ControllerButton button) const
{
if (!instance->connection)
Expand Down Expand Up @@ -160,5 +182,44 @@ namespace Player
instance->reset();
instance->poll();
}

void Ps3Controller::playRumblePattern(RumblePattern pattern)
{
const RumbleStep *steps = pattern.getSteps();
size_t count = pattern.getCount();

for (size_t i = 0; i < count; i++)
{
Ps3.setRumble(steps[i].intensity, steps[i].duration);
vTaskDelay(pdMS_TO_TICKS(steps[i].duration));
}
}

void Ps3Controller::rumbleTask(void *pvParameters)
{
auto *params = (RumbleTaskParams *)pvParameters;

Ps3Controller *self = params->instance;
const RumblePattern *pattern = params->pattern;

self->playRumblePattern(*pattern);

delete params;
vTaskDelete(NULL);
}
void Ps3Controller::triggerRumble(const RumblePattern &pattern)
{
auto *params = new RumbleTaskParams{
this,
&pattern};
xTaskCreatePinnedToCore(
Ps3Controller::rumbleTask,
"RumbleTask",
2048,
(void *)params,
1,
NULL,
0);
}
}
#endif
Loading