Add support for game controllers

This commit is contained in:
Jakub Skokan 2016-07-13 09:22:21 +02:00
parent 187776ed69
commit e9ea95d3b9
7 changed files with 187 additions and 8 deletions

View file

@ -284,6 +284,50 @@ int Game::gameLoop()
{ {
// handle player controls // handle player controls
updateControls(event.key.keysym.sym, false); updateControls(event.key.keysym.sym, false);
} else if (event.type == SDL_CONTROLLERBUTTONUP) {
switch (event.cbutton.button) {
case SDL_CONTROLLER_BUTTON_A:
if (state == WAITFORSTART) {
state = START;
stateTimer = 0;
stateVal = 0;
}
break;
case SDL_CONTROLLER_BUTTON_B:
case SDL_CONTROLLER_BUTTON_BACK:
case SDL_CONTROLLER_BUTTON_START:
loop = false;
break;
}
} else if (event.type == SDL_CONTROLLERAXISMOTION) {
switch (event.caxis.axis) {
case SDL_CONTROLLER_AXIS_LEFTX:
updateControls(
mapControllerAxis(
event.caxis.which,
event.caxis.axis,
event.caxis.value
),
event.caxis.value < -12000 || event.caxis.value > 12000
);
break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
updateControls(
mapControllerAxis(
event.caxis.which,
event.caxis.axis,
event.caxis.value
),
event.caxis.value > 500
);
break;
}
} }
} }
@ -435,6 +479,43 @@ void Game::updateWorld(float t)
} }
SDL_Keycode Game::mapControllerAxis(SDL_JoystickID joy, Uint8 axis, Sint16 value)
{
int ctrl;
for(int i = 0; i < MAX_PLAYERS; i++) {
if (!players[i].hasController(joy))
continue;
// Controls in order: right, left, thrust
switch(axis) {
case SDL_CONTROLLER_AXIS_LEFTX:
ctrl = value > 0 ? 0 : 1;
break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
ctrl = 2;
break;
default:
return SDLK_ESCAPE;
}
return CONTROLS[i][ctrl];
}
return SDLK_ESCAPE;
}
int Game::getPlayerForController(SDL_JoystickID id)
{
for(int p = 0; p < MAX_LOCAL_PLAYERS; p++)
if (players[p].hasController(id))
return p;
return -1;
}
void Game::initViewports(int num) void Game::initViewports(int num)
{ {
numViewports = num; numViewports = num;

View file

@ -38,6 +38,8 @@ public:
Level &getLevel(); Level &getLevel();
static Game &getInstance(); static Game &getInstance();
int getPlayerForController(SDL_JoystickID id);
void initViewports(int num); void initViewports(int num);
Player &getPlayer(int n); Player &getPlayer(int n);
@ -60,6 +62,8 @@ private:
bool updateControls(int keysym, bool down); bool updateControls(int keysym, bool down);
void updateWorld(float t); void updateWorld(float t);
SDL_Keycode mapControllerAxis(SDL_JoystickID joy, Uint8 axis, Sint16 value);
void resetListener(); void resetListener();
void updateListener(); void updateListener();

View file

@ -2,6 +2,7 @@
#include "SDL.h" #include "SDL.h"
#include "SDL_opengl.h" #include "SDL_opengl.h"
//#include "SDL_gamecontroller.h"
#include <AL/alut.h> #include <AL/alut.h>
#include <AL/al.h> #include <AL/al.h>
#include <unistd.h> #include <unistd.h>
@ -93,7 +94,7 @@ int main(int argc, char *argv[])
atexit(cleanup); atexit(cleanup);
if(SDL_Init(SDL_INIT_VIDEO) != 0) if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0)
{ {
fprintf(stderr, "Can't initialize SDL: %s\n", SDL_GetError()); fprintf(stderr, "Can't initialize SDL: %s\n", SDL_GetError());
return -1; return -1;
@ -160,15 +161,40 @@ int main(int argc, char *argv[])
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
Game &game = Game::getInstance(); Game &game = Game::getInstance();
if(game.init(screen)) return 1; if(game.init(screen)) return 1;
if(Menu::init()) return 1; if(Menu::init()) return 1;
SDL_GameController *controllers[8] = {NULL};
SDL_GameController *controller = NULL;
for (int i = 0, j = 0; i < SDL_NumJoysticks(); i++) {
if (!SDL_IsGameController(i))
continue;
controller = SDL_GameControllerOpen(i);
if (controller) {
controllers[j++] = controller;
} else {
fprintf(stderr, "Could not open gamecontroller %i: %s\n", i, SDL_GetError());
}
}
Menu menu(screen); Menu menu(screen);
while(1) { while(1) {
if(menu.show()) if(menu.show())
return 0; break;
if(game.gameLoop()) if(game.gameLoop())
return 0; break;
}
for (int i = 0; i < 8; i++) {
if (!controllers[i])
break;
SDL_GameControllerClose(controllers[i]);
} }
SDL_GL_DeleteContext(glcontext); SDL_GL_DeleteContext(glcontext);

View file

@ -101,6 +101,51 @@ int Menu::show()
} }
} }
} }
else if (event.type == SDL_CONTROLLERBUTTONUP) {
Game &game = Game::getInstance();
if (event.cbutton.button == SDL_CONTROLLER_BUTTON_A ) {
int p;
if ((p = game.getPlayerForController(event.cbutton.which)) == -1) {
// Activate the first available player
for(int p = 0; p < Game::MAX_LOCAL_PLAYERS; p++) {
Player &plr = Game::getInstance().getPlayer(p);
if (plr.isActive())
continue;
togglePlayer(plr);
plr.setController(event.cbutton.which);
break;
}
} else {
// Player is already active, start the game
if (canstart)
rval = 0;
}
} else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_B) {
// Find out if this joystick already belongs to a player
for(int p = 0; p < Game::MAX_LOCAL_PLAYERS; p++) {
Player &plr = game.getPlayer(p);
if (plr.hasController(event.cbutton.which)) {
togglePlayer(plr);
break;
}
}
} else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_START) {
if (canstart)
rval = 0;
} else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) {
rval = 1;
}
}
} }
} }
@ -109,12 +154,15 @@ int Menu::show()
void Menu::togglePlayer(int p) void Menu::togglePlayer(int p)
{ {
Game &game = Game::getInstance(); togglePlayer(Game::getInstance().getPlayer(p));
Player &plr = game.getPlayer(p); }
void Menu::togglePlayer(Player &plr)
{
plr.setActive(!plr.isActive()); plr.setActive(!plr.isActive());
int act=0; int act=0;
for(int plr=0;plr<4;plr++) { for(int p=0;p<4;p++) {
if(game.getPlayer(plr).isActive()) if(plr.isActive())
++act; ++act;
} }
canstart = act>0; canstart = act>0;

View file

@ -11,6 +11,7 @@ class Menu {
int show(); int show();
private: private:
void togglePlayer(int p); void togglePlayer(int p);
void togglePlayer(Player &plr);
void drawPlayer(int p); void drawPlayer(int p);
void update(); void update();

View file

@ -15,7 +15,8 @@ ALuint Player::buffer;
float Player::engineVolume = 1.0; float Player::engineVolume = 1.0;
Player::Player() Player::Player()
: finished(false) : joyid(-1),
finished(false)
{ {
} }
@ -69,6 +70,9 @@ void Player::setTexture(m3dTexture *tex)
void Player::setActive(bool a) void Player::setActive(bool a)
{ {
active = a; active = a;
if (!active)
joyid = -1;
} }
void Player::setLocal(bool l) void Player::setLocal(bool l)
@ -76,10 +80,17 @@ void Player::setLocal(bool l)
local = l; local = l;
} }
void Player::setController(SDL_JoystickID id)
{
joyid = id;
}
Craft &Player::getCraft() { return craft; } Craft &Player::getCraft() { return craft; }
bool Player::isActive() const { return active; } bool Player::isActive() const { return active; }
bool Player::isLocal() const { return local; } bool Player::isLocal() const { return local; }
const char *Player::getName() const { return name; } const char *Player::getName() const { return name; }
bool Player::hasController() const { return joyid != -1; }
bool Player::hasController(SDL_JoystickID id) const { return joyid == id; }
bool Player::isFinished() const { return finished; } bool Player::isFinished() const { return finished; }

View file

@ -1,6 +1,8 @@
#ifndef _PLAYER_H_ #ifndef _PLAYER_H_
#define _PLAYER_H_ #define _PLAYER_H_
#include "SDL_gamecontroller.h"
class Player class Player
{ {
public: public:
@ -13,6 +15,8 @@ public:
void setTexture(m3dTexture *texture); void setTexture(m3dTexture *texture);
void setActive(bool active); void setActive(bool active);
void setLocal(bool l); void setLocal(bool l);
void setController(SDL_JoystickID id);
void unsetController();
void setColor(float r, float g, float b); void setColor(float r, float g, float b);
void setColor(const float *col); void setColor(const float *col);
@ -29,6 +33,8 @@ public:
bool isActive() const; bool isActive() const;
bool isLocal() const; bool isLocal() const;
bool isFinished() const; bool isFinished() const;
bool hasController() const;
bool hasController(SDL_JoystickID id) const;
const char *getName() const; const char *getName() const;
void drawHud(const GLint *viewport, int activePlayers, int num); void drawHud(const GLint *viewport, int activePlayers, int num);
@ -46,6 +52,8 @@ private:
Craft craft; Craft craft;
SDL_JoystickID joyid;
bool active; bool active;
bool local; bool local;
bool finished; bool finished;