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
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)
{
numViewports = num;

View file

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

View file

@ -2,6 +2,7 @@
#include "SDL.h"
#include "SDL_opengl.h"
//#include "SDL_gamecontroller.h"
#include <AL/alut.h>
#include <AL/al.h>
#include <unistd.h>
@ -93,7 +94,7 @@ int main(int argc, char *argv[])
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());
return -1;
@ -160,15 +161,40 @@ int main(int argc, char *argv[])
SDL_ShowCursor(SDL_DISABLE);
Game &game = Game::getInstance();
if(game.init(screen)) 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);
while(1) {
if(menu.show())
return 0;
break;
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);

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)
{
Game &game = Game::getInstance();
Player &plr = game.getPlayer(p);
togglePlayer(Game::getInstance().getPlayer(p));
}
void Menu::togglePlayer(Player &plr)
{
plr.setActive(!plr.isActive());
int act=0;
for(int plr=0;plr<4;plr++) {
if(game.getPlayer(plr).isActive())
for(int p=0;p<4;p++) {
if(plr.isActive())
++act;
}
canstart = act>0;

View file

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

View file

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

View file

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