Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for controllers + default bindings #374

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions include/engine_sim_application.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "delta.h"
#include "dtv.h"

#include "joystick.h"

#include <vector>

class EngineSimApplication {
Expand Down Expand Up @@ -151,6 +153,8 @@ class EngineSimApplication {

bool m_paused;

Joystick j_Controller;

protected:
void startRecording();
void updateScreenSizeStability();
Expand Down
73 changes: 73 additions & 0 deletions include/joystick.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

#ifndef ATG_ENGINE_SIM_JOYSTICK_H
#define ATG_ENGINE_SIM_JOYSTICK_H

#include <Xinput.h>

class Joystick
{
public:
XINPUT_STATE GetState();
int GetIndex();
bool Alive();

void Update();
void RefreshState();
void Rumble(float a_fLM, float a_fRM);

float LT();
float RT();

bool buttonPressed(int j_iButton);
bool buttonDown(int j_iButton);
Joystick();
Joystick(int j_iIndex);

private:
XINPUT_STATE j_State;
int j_JoystickIndex;

static const int button_count = 14;
bool bStates_prev[button_count];
bool bStates[button_count];

bool b_ButtonsDown[button_count];
};



static const WORD XINPUT_Buttons[] = {
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT,
XINPUT_GAMEPAD_DPAD_RIGHT,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_BACK
};

struct button_id
{
button_id();

int A, B, X, Y;

int d_up, d_down, d_left , d_right;

int l_s, r_s;

int l_th, r_th;

int start;
int back;
};
#endif /* ATG_ENGINE_SIM_JOYSTICK_H */

extern button_id j_Buttons;
26 changes: 20 additions & 6 deletions src/engine_sim_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ EngineSimApplication::EngineSimApplication() {
m_viewParameters.Layer1 = 0;

m_displayAngle = 0.0f;

j_Controller = Joystick(1);
}

EngineSimApplication::~EngineSimApplication() {
Expand Down Expand Up @@ -671,6 +673,7 @@ void EngineSimApplication::processEngineInput() {
return;
}

j_Controller.Update();
const float dt = m_engine.GetFrameLength();
const bool fineControlMode = m_engine.IsKeyDown(ysKey::Code::Space);

Expand Down Expand Up @@ -789,6 +792,9 @@ void EngineSimApplication::processEngineInput() {
else if (fineControlMode && !fineControlInUse) {
m_targetSpeedSetting = clamp(m_targetSpeedSetting + mouseWheelDelta * 0.0001);
}
else if (j_Controller.Alive()) {
m_targetSpeedSetting = j_Controller.RT();
}

if (prevTargetThrottle != m_targetSpeedSetting) {
m_infoCluster->setLogMessage("Speed control set to " + std::to_string(m_targetSpeedSetting));
Expand All @@ -813,7 +819,7 @@ void EngineSimApplication::processEngineInput() {
m_infoCluster->setLogMessage("[,] - Set render layer to " + std::to_string(getViewParameters().Layer0));
}

if (m_engine.ProcessKeyDown(ysKey::Code::D)) {
if (m_engine.ProcessKeyDown(ysKey::Code::D) || j_Controller.buttonDown(j_Buttons.B)) {
m_simulator.m_dyno.m_enabled = !m_simulator.m_dyno.m_enabled;

const std::string msg = m_simulator.m_dyno.m_enabled
Expand All @@ -822,7 +828,7 @@ void EngineSimApplication::processEngineInput() {
m_infoCluster->setLogMessage(msg);
}

if (m_engine.ProcessKeyDown(ysKey::Code::H)) {
if (m_engine.ProcessKeyDown(ysKey::Code::H) || j_Controller.buttonDown(j_Buttons.A)) {
m_simulator.m_dyno.m_hold = !m_simulator.m_dyno.m_hold;

const std::string msg = m_simulator.m_dyno.m_hold
Expand Down Expand Up @@ -859,7 +865,9 @@ void EngineSimApplication::processEngineInput() {
if (m_engine.IsKeyDown(ysKey::Code::S)) {
m_simulator.m_starterMotor.m_enabled = true;
}
else {
else if (j_Controller.Alive() && j_Controller.buttonPressed(j_Buttons.X)) {
m_simulator.m_starterMotor.m_enabled = true;
} else {
m_simulator.m_starterMotor.m_enabled = false;
}

Expand All @@ -870,7 +878,7 @@ void EngineSimApplication::processEngineInput() {
m_infoCluster->setLogMessage(msg);
}

if (m_engine.ProcessKeyDown(ysKey::Code::A)) {
if (m_engine.ProcessKeyDown(ysKey::Code::A) || j_Controller.buttonDown(j_Buttons.Y)) {
m_simulator.getEngine()->getIgnitionModule()->m_enabled =
!m_simulator.getEngine()->getIgnitionModule()->m_enabled;

Expand All @@ -880,13 +888,13 @@ void EngineSimApplication::processEngineInput() {
m_infoCluster->setLogMessage(msg);
}

if (m_engine.ProcessKeyDown(ysKey::Code::Up)) {
if (m_engine.ProcessKeyDown(ysKey::Code::Up) || j_Controller.buttonDown(j_Buttons.r_s)) {
m_simulator.getTransmission()->changeGear(m_simulator.getTransmission()->getGear() + 1);

m_infoCluster->setLogMessage(
"UPSHIFTED TO " + std::to_string(m_simulator.getTransmission()->getGear() + 1));
}
else if (m_engine.ProcessKeyDown(ysKey::Code::Down)) {
else if (m_engine.ProcessKeyDown(ysKey::Code::Down) || j_Controller.buttonDown(j_Buttons.l_s)) {
m_simulator.getTransmission()->changeGear(m_simulator.getTransmission()->getGear() - 1);

if (m_simulator.getTransmission()->getGear() != -1) {
Expand All @@ -908,10 +916,14 @@ void EngineSimApplication::processEngineInput() {
m_targetClutchPressure = 0.0;
m_infoCluster->setLogMessage("CLUTCH DEPRESSED");
}
else if (j_Controller.Alive()) {
m_targetClutchPressure = 1-j_Controller.LT();
}
else if (!m_engine.IsKeyDown(ysKey::Code::Y)) {
m_targetClutchPressure = 1.0;
}


m_targetClutchPressure = clamp(m_targetClutchPressure);

double clutchRC = 0.001;
Expand All @@ -922,6 +934,8 @@ void EngineSimApplication::processEngineInput() {
const double clutch_s = dt / (dt + clutchRC);
m_clutchPressure = m_clutchPressure * (1 - clutch_s) + m_targetClutchPressure * clutch_s;
m_simulator.getTransmission()->setClutchPressure(m_clutchPressure);

j_Controller.RefreshState();
}

void EngineSimApplication::renderScene() {
Expand Down
140 changes: 140 additions & 0 deletions src/joystick.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include <windows.h>
#include "../include/joystick.h"

#pragma comment(lib, "Xinput.lib")

button_id j_Buttons;

Joystick::Joystick() {};

Joystick::Joystick(int j_iIndex) {
j_JoystickIndex = j_iIndex - 1;

for (int i = 0; i < button_count; i++)
{
bStates_prev[i] = false;
bStates[i] = false;
b_ButtonsDown[i] = false;
}
}

XINPUT_STATE Joystick::GetState() {

XINPUT_STATE js;

memset(&js, 0, sizeof(XINPUT_STATE));

XInputGetState(j_JoystickIndex, &js);

return js;
}

int Joystick::GetIndex() { return j_JoystickIndex; }

//Check if joystick is connected and working
bool Joystick::Alive() {

memset(&j_State, 0, sizeof(XINPUT_STATE));

DWORD r = XInputGetState(j_JoystickIndex, &j_State);

if (r == 0)
return true;
else
return false;
}

//updates state of controller
//needs to be called before using any functions of controller
void Joystick::Update() {
j_State = GetState();

for (int i = 0; i < button_count; i++)
{
// Set button state for current frame
bStates[i] = (j_State.Gamepad.wButtons &
XINPUT_Buttons[i]) == XINPUT_Buttons[i];

// Set 'DOWN' state for current frame
b_ButtonsDown[i] = !bStates_prev[i] &&
bStates[i];
}
}

//refreshes states of buttons. needs to be called at the end of use of controller
void Joystick::RefreshState()
{
memcpy(bStates_prev, bStates,
sizeof(bStates_prev));
}

//get left trigger pull
float Joystick::LT() {
BYTE T = j_State.Gamepad.bLeftTrigger;

if (T > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) {
return T / 255.0f;
}
return 0.0;
}

//get right trigger pull
float Joystick::RT() {
BYTE T = j_State.Gamepad.bRightTrigger;

if (T > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) {
return T / 255.0f;
}
return 0.0;
}

//vibrate controller, use 0,0 to cancel rumble
void Joystick::Rumble(float a_fLM, float a_fRM) {
XINPUT_VIBRATION VS;

memset(&VS, 0, sizeof(XINPUT_VIBRATION));

int LM = int(a_fLM * 65535.0f);
int RM = int(a_fRM * 65535.0f);

VS.wLeftMotorSpeed = LM;
VS.wRightMotorSpeed = RM;

XInputSetState(j_JoystickIndex, &VS);
}

//check if button is pressed. use this for single button checks
bool Joystick::buttonPressed(int j_iButton) {
if (j_State.Gamepad.wButtons & XINPUT_Buttons[j_iButton]) {
return true;
}
return false;

}

//check if button is down every frame
bool Joystick::buttonDown(int j_iButton)
{
return b_ButtonsDown[j_iButton];
}

button_id::button_id() {
A = 0;
B = 1;
X = 2;
Y = 3;

d_up = 4;
d_down = 5;
d_left = 6;
d_right = 7;

l_s = 8;
r_s = 9;

l_th = 10;
r_th = 11;

start = 12;
back = 13;
}