git repos / blockattack-game

blame: source/code/gamecontroller.cpp

normal view · raw

826cf176 sago007 2016-03-12 10:53 1
/*
826cf176 sago007 2016-03-12 10:53 2
===========================================================================
826cf176 sago007 2016-03-12 10:53 3
blockattack - Block Attack - Rise of the Blocks
826cf176 sago007 2016-03-12 10:53 4
Copyright (C) 2005-2016 Poul Sander
826cf176 sago007 2016-03-12 10:53 5
826cf176 sago007 2016-03-12 10:53 6
This program is free software: you can redistribute it and/or modify
826cf176 sago007 2016-03-12 10:53 7
it under the terms of the GNU General Public License as published by
826cf176 sago007 2016-03-12 10:53 8
the Free Software Foundation, either version 2 of the License, or
826cf176 sago007 2016-03-12 10:53 9
(at your option) any later version.
826cf176 sago007 2016-03-12 10:53 10
826cf176 sago007 2016-03-12 10:53 11
This program is distributed in the hope that it will be useful,
826cf176 sago007 2016-03-12 10:53 12
but WITHOUT ANY WARRANTY; without even the implied warranty of
826cf176 sago007 2016-03-12 10:53 13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
826cf176 sago007 2016-03-12 10:53 14
GNU General Public License for more details.
826cf176 sago007 2016-03-12 10:53 15
826cf176 sago007 2016-03-12 10:53 16
You should have received a copy of the GNU General Public License
826cf176 sago007 2016-03-12 10:53 17
along with this program.  If not, see http://www.gnu.org/licenses/
826cf176 sago007 2016-03-12 10:53 18
826cf176 sago007 2016-03-12 10:53 19
Source information and contacts persons can be found at
826cf176 sago007 2016-03-12 10:53 20
http://www.blockattack.net
826cf176 sago007 2016-03-12 10:53 21
===========================================================================
826cf176 sago007 2016-03-12 10:53 22
*/
826cf176 sago007 2016-03-12 10:53 23
826cf176 sago007 2016-03-12 10:53 24
#include "gamecontroller.h"
826cf176 sago007 2016-03-12 10:53 25
#include "SDL_gamecontroller.h"
2cb68251 sago007 2016-03-14 18:01 26
#include "sago/platform_folders.h"
75ea368b sago007 2016-04-16 14:37 27
#include "common.h"
826cf176 sago007 2016-03-12 10:53 28
#include <iostream>
a077dceb sago007 2016-03-19 19:19 29
#include <map>
75ea368b sago007 2016-04-16 14:37 30
#include <SDL2/SDL_joystick.h>
826cf176 sago007 2016-03-12 10:53 31
2cb68251 sago007 2016-03-14 18:01 32
static bool verbose = false;
2cb68251 sago007 2016-03-14 18:01 33
a077dceb sago007 2016-03-19 19:19 34
struct ControllerStatus {
a077dceb sago007 2016-03-19 19:19 35
	std::map<int, bool> AxisInDeadZone;
f2dac7e4 sago007 2016-04-09 19:24 36
	int player = 1;
a077dceb sago007 2016-03-19 19:19 37
};
a077dceb sago007 2016-03-19 19:19 38
a077dceb sago007 2016-03-19 19:19 39
static std::map<SDL_JoystickID, ControllerStatus> controllerStatusMap;
a077dceb sago007 2016-03-19 19:19 40
a077dceb sago007 2016-03-19 19:19 41
2cb68251 sago007 2016-03-14 18:01 42
void GameControllerSetVerbose(bool value) {
2cb68251 sago007 2016-03-14 18:01 43
	verbose = value;
2cb68251 sago007 2016-03-14 18:01 44
}
2cb68251 sago007 2016-03-14 18:01 45
a35ab74b sago007 2016-04-02 10:26 46
static const char* GameControllerGetName(SDL_GameController* gamecontroller) {
2cb68251 sago007 2016-03-14 18:01 47
	const char* result = SDL_GameControllerName(gamecontroller);
2cb68251 sago007 2016-03-14 18:01 48
	if (!result) {
2cb68251 sago007 2016-03-14 18:01 49
		result = "Unnamed";
2cb68251 sago007 2016-03-14 18:01 50
	}
2cb68251 sago007 2016-03-14 18:01 51
	return result;
2cb68251 sago007 2016-03-14 18:01 52
}
2cb68251 sago007 2016-03-14 18:01 53
75ea368b sago007 2016-04-16 14:37 54
static std::string GetGuidAsHex(const SDL_JoystickGUID& guid) {
75ea368b sago007 2016-04-16 14:37 55
	std::string ret;
75ea368b sago007 2016-04-16 14:37 56
	char buffer[3];
75ea368b sago007 2016-04-16 14:37 57
	for(size_t j = 0; j < 16; j++) {
75ea368b sago007 2016-04-16 14:37 58
		snprintf(buffer, sizeof(buffer), "%02X", guid.data[j]);
75ea368b sago007 2016-04-16 14:37 59
		ret += buffer;
75ea368b sago007 2016-04-16 14:37 60
	}
75ea368b sago007 2016-04-16 14:37 61
	return ret;
75ea368b sago007 2016-04-16 14:37 62
}
75ea368b sago007 2016-04-16 14:37 63
75ea368b sago007 2016-04-16 14:37 64
static std::map<std::string, int> gamecontrollers_assigned; 
75ea368b sago007 2016-04-16 14:37 65
75ea368b sago007 2016-04-16 14:37 66
static int GetNextPlayerByGui(const SDL_JoystickGUID& guid) {
75ea368b sago007 2016-04-16 14:37 67
	Config::getInstance()->setDefault("gc_AllToOnePlayer", "0");
75ea368b sago007 2016-04-16 14:37 68
	int fixedPlayer = Config::getInstance()->getInt("gc_AllToOnePlayer");
75ea368b sago007 2016-04-16 14:37 69
	if (fixedPlayer > 0 && fixedPlayer <= 2) {
75ea368b sago007 2016-04-16 14:37 70
		return fixedPlayer;
75ea368b sago007 2016-04-16 14:37 71
	}
75ea368b sago007 2016-04-16 14:37 72
	std::string guidAsHex= GetGuidAsHex(guid);
75ea368b sago007 2016-04-16 14:37 73
	std::string configName = "gc_assign_"+guidAsHex;
75ea368b sago007 2016-04-16 14:37 74
	Config::getInstance()->setDefault(configName, "1");
75ea368b sago007 2016-04-16 14:37 75
	int player = Config::getInstance()->getInt(configName) + gamecontrollers_assigned[guidAsHex];
75ea368b sago007 2016-04-16 14:37 76
	gamecontrollers_assigned[guidAsHex]++; //Next controller with same guid should be assigned to different player.
161a010c sago007 2016-05-06 14:00 77
	//std::cout << "Guid: " << guidAsHex << "\n";
75ea368b sago007 2016-04-16 14:37 78
	
75ea368b sago007 2016-04-16 14:37 79
	if (player%2==0) {
75ea368b sago007 2016-04-16 14:37 80
		return 2;  //Even number means player 2
75ea368b sago007 2016-04-16 14:37 81
	}
75ea368b sago007 2016-04-16 14:37 82
	return 1;
75ea368b sago007 2016-04-16 14:37 83
}
75ea368b sago007 2016-04-16 14:37 84
826cf176 sago007 2016-03-12 10:53 85
void InitGameControllers() {
2cb68251 sago007 2016-03-14 18:01 86
	std::string configFile = sago::getConfigHome()+"/blockattack/gamecontrollerdb.txt";
2cb68251 sago007 2016-03-14 18:01 87
	int errorCode = SDL_GameControllerAddMappingsFromFile(configFile.c_str());
2cb68251 sago007 2016-03-14 18:01 88
	if (errorCode == -1 && verbose) {
161a010c sago007 2016-05-06 14:00 89
		std::cerr << "Could not load mapping file: " << configFile << "\n";
2cb68251 sago007 2016-03-14 18:01 90
	}
2cb68251 sago007 2016-03-14 18:01 91
	if (verbose) {
161a010c sago007 2016-05-06 14:00 92
		std::cout << "Number of Game controllers: " << SDL_NumJoysticks() << "\n";
2cb68251 sago007 2016-03-14 18:01 93
	}
c7f2082f sago007 2016-03-13 11:48 94
	SDL_GameController* controller = nullptr;
826cf176 sago007 2016-03-12 10:53 95
	for (int i = 0; i < SDL_NumJoysticks(); ++i) {
826cf176 sago007 2016-03-12 10:53 96
		if (SDL_IsGameController(i)) {
826cf176 sago007 2016-03-12 10:53 97
			controller = SDL_GameControllerOpen(i);
f2dac7e4 sago007 2016-04-09 19:24 98
			SDL_Joystick *j = SDL_GameControllerGetJoystick(controller);
f2dac7e4 sago007 2016-04-09 19:24 99
			SDL_JoystickID instanceId = SDL_JoystickInstanceID(j);
75ea368b sago007 2016-04-16 14:37 100
			SDL_JoystickGUID guid = SDL_JoystickGetGUID(j);
75ea368b sago007 2016-04-16 14:37 101
			int assingToPlayer = GetNextPlayerByGui(guid);
75ea368b sago007 2016-04-16 14:37 102
			controllerStatusMap[instanceId].player = assingToPlayer;
2cb68251 sago007 2016-03-14 18:01 103
			if (verbose) {
161a010c sago007 2016-05-06 14:00 104
				std::cout << "Supported game controller detected: " << GameControllerGetName(controller) << ", mapping: " << SDL_GameControllerMapping(controller) <<  "\n";
161a010c sago007 2016-05-06 14:00 105
				std::cout << "Assigned to player: " << controllerStatusMap[instanceId].player << "\n";
2cb68251 sago007 2016-03-14 18:01 106
			}
826cf176 sago007 2016-03-12 10:53 107
		}
826cf176 sago007 2016-03-12 10:53 108
	}
826cf176 sago007 2016-03-12 10:53 109
}
ce5aa7d3 sago007 2016-03-13 11:44 110
a077dceb sago007 2016-03-19 19:19 111
void checkDeadZone(const SDL_Event& event) {
a077dceb sago007 2016-03-19 19:19 112
	if (event.type != SDL_CONTROLLERAXISMOTION) {
a077dceb sago007 2016-03-19 19:19 113
		return;  //assert?
a077dceb sago007 2016-03-19 19:19 114
	}
a077dceb sago007 2016-03-19 19:19 115
	int value = event.caxis.value;
a077dceb sago007 2016-03-19 19:19 116
	if (value > -deadZoneLimit && value < deadZoneLimit) {
a077dceb sago007 2016-03-19 19:19 117
		controllerStatusMap[event.caxis.which].AxisInDeadZone[event.caxis.axis] = true;
a077dceb sago007 2016-03-19 19:19 118
	}
a077dceb sago007 2016-03-19 19:19 119
}
a077dceb sago007 2016-03-19 19:19 120
a077dceb sago007 2016-03-19 19:19 121
bool getDeadZone(SDL_JoystickID id, int axis) {
a077dceb sago007 2016-03-19 19:19 122
	return controllerStatusMap[id].AxisInDeadZone[axis];
a077dceb sago007 2016-03-19 19:19 123
}
a077dceb sago007 2016-03-19 19:19 124
a077dceb sago007 2016-03-19 19:19 125
void setDeadZone(SDL_JoystickID id, int axis, bool value) {
a077dceb sago007 2016-03-19 19:19 126
	controllerStatusMap[id].AxisInDeadZone[axis] = value;
a077dceb sago007 2016-03-19 19:19 127
}
a077dceb sago007 2016-03-19 19:19 128
f2dac7e4 sago007 2016-04-09 19:24 129
static bool skipThisPlayer(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 130
f2dac7e4 sago007 2016-04-09 19:24 131
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
f2dac7e4 sago007 2016-04-09 19:24 132
		ControllerStatus& cs = controllerStatusMap[event.cbutton.which];
f2dac7e4 sago007 2016-04-09 19:24 133
		if (cs.player == playerNumber) {
f2dac7e4 sago007 2016-04-09 19:24 134
			return false;
f2dac7e4 sago007 2016-04-09 19:24 135
		}
f2dac7e4 sago007 2016-04-09 19:24 136
	}
f2dac7e4 sago007 2016-04-09 19:24 137
	if (event.type == SDL_CONTROLLERAXISMOTION ) {
f2dac7e4 sago007 2016-04-09 19:24 138
		ControllerStatus& cs = controllerStatusMap[event.caxis.which];
f2dac7e4 sago007 2016-04-09 19:24 139
		if (cs.player == playerNumber) {
f2dac7e4 sago007 2016-04-09 19:24 140
			return false;
f2dac7e4 sago007 2016-04-09 19:24 141
		}
f2dac7e4 sago007 2016-04-09 19:24 142
	}
f2dac7e4 sago007 2016-04-09 19:24 143
	return true;
f2dac7e4 sago007 2016-04-09 19:24 144
}
f2dac7e4 sago007 2016-04-09 19:24 145
ce5aa7d3 sago007 2016-03-13 11:44 146
bool isPlayerDownEvent(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 147
	if (skipThisPlayer(playerNumber, event)) {
ce5aa7d3 sago007 2016-03-13 11:44 148
		return false;
ce5aa7d3 sago007 2016-03-13 11:44 149
	}
ce5aa7d3 sago007 2016-03-13 11:44 150
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
ce5aa7d3 sago007 2016-03-13 11:44 151
		if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN ) {
ce5aa7d3 sago007 2016-03-13 11:44 152
			return true;
ce5aa7d3 sago007 2016-03-13 11:44 153
		}
ce5aa7d3 sago007 2016-03-13 11:44 154
	}
a077dceb sago007 2016-03-19 19:19 155
	if (event.type == SDL_CONTROLLERAXISMOTION  && event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ) {
a35ab74b sago007 2016-04-02 10:26 156
		const SDL_ControllerAxisEvent& a = event.caxis;
f2dac7e4 sago007 2016-04-09 19:24 157
		checkDeadZone(event);
a077dceb sago007 2016-03-19 19:19 158
		if (getDeadZone(a.which, a.axis)) {
a077dceb sago007 2016-03-19 19:19 159
			if (event.caxis.value > deadZoneLimit) {
a077dceb sago007 2016-03-19 19:19 160
				setDeadZone(a.which,a.axis,false);
a077dceb sago007 2016-03-19 19:19 161
				return true;
a077dceb sago007 2016-03-19 19:19 162
			}
a077dceb sago007 2016-03-19 19:19 163
		}
a077dceb sago007 2016-03-19 19:19 164
	}
ce5aa7d3 sago007 2016-03-13 11:44 165
	return false;
ce5aa7d3 sago007 2016-03-13 11:44 166
}
ce5aa7d3 sago007 2016-03-13 11:44 167
ce5aa7d3 sago007 2016-03-13 11:44 168
bool isPlayerUpEvent(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 169
	if (skipThisPlayer(playerNumber, event)) {
ce5aa7d3 sago007 2016-03-13 11:44 170
		return false;
ce5aa7d3 sago007 2016-03-13 11:44 171
	}
ce5aa7d3 sago007 2016-03-13 11:44 172
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
ce5aa7d3 sago007 2016-03-13 11:44 173
		if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_UP ) {
ce5aa7d3 sago007 2016-03-13 11:44 174
			return true;
ce5aa7d3 sago007 2016-03-13 11:44 175
		}
ce5aa7d3 sago007 2016-03-13 11:44 176
	}
a077dceb sago007 2016-03-19 19:19 177
	if (event.type == SDL_CONTROLLERAXISMOTION  && event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ) {
a077dceb sago007 2016-03-19 19:19 178
		checkDeadZone(event);
a35ab74b sago007 2016-04-02 10:26 179
		const SDL_ControllerAxisEvent& a = event.caxis;
a077dceb sago007 2016-03-19 19:19 180
		if (getDeadZone(a.which, a.axis)) {
a077dceb sago007 2016-03-19 19:19 181
			if (event.caxis.value < -deadZoneLimit) {
a077dceb sago007 2016-03-19 19:19 182
				setDeadZone(a.which,a.axis,false);
a077dceb sago007 2016-03-19 19:19 183
				return true;
a077dceb sago007 2016-03-19 19:19 184
			}
a077dceb sago007 2016-03-19 19:19 185
		}
a077dceb sago007 2016-03-19 19:19 186
	}
ce5aa7d3 sago007 2016-03-13 11:44 187
	return false;
ce5aa7d3 sago007 2016-03-13 11:44 188
}
ce5aa7d3 sago007 2016-03-13 11:44 189
ce5aa7d3 sago007 2016-03-13 11:44 190
bool isPlayerLeftEvent(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 191
	if (skipThisPlayer(playerNumber, event)) {
ce5aa7d3 sago007 2016-03-13 11:44 192
		return false;
ce5aa7d3 sago007 2016-03-13 11:44 193
	}
ce5aa7d3 sago007 2016-03-13 11:44 194
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
ce5aa7d3 sago007 2016-03-13 11:44 195
		if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT ) {
ce5aa7d3 sago007 2016-03-13 11:44 196
			return true;
ce5aa7d3 sago007 2016-03-13 11:44 197
		}
ce5aa7d3 sago007 2016-03-13 11:44 198
	}
a077dceb sago007 2016-03-19 19:19 199
	if (event.type == SDL_CONTROLLERAXISMOTION  && event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ) {
a077dceb sago007 2016-03-19 19:19 200
		checkDeadZone(event);
a35ab74b sago007 2016-04-02 10:26 201
		const SDL_ControllerAxisEvent& a = event.caxis;
a077dceb sago007 2016-03-19 19:19 202
		if (getDeadZone(a.which, a.axis)) {
a077dceb sago007 2016-03-19 19:19 203
			if (event.caxis.value < -deadZoneLimit) {
a077dceb sago007 2016-03-19 19:19 204
				setDeadZone(a.which,a.axis,false);
a077dceb sago007 2016-03-19 19:19 205
				return true;
a077dceb sago007 2016-03-19 19:19 206
			}
a077dceb sago007 2016-03-19 19:19 207
		}
a077dceb sago007 2016-03-19 19:19 208
	}
ce5aa7d3 sago007 2016-03-13 11:44 209
	return false;
ce5aa7d3 sago007 2016-03-13 11:44 210
}
ce5aa7d3 sago007 2016-03-13 11:44 211
ce5aa7d3 sago007 2016-03-13 11:44 212
bool isPlayerRightEvent(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 213
	if (skipThisPlayer(playerNumber, event)) {
ce5aa7d3 sago007 2016-03-13 11:44 214
		return false;
ce5aa7d3 sago007 2016-03-13 11:44 215
	}
ce5aa7d3 sago007 2016-03-13 11:44 216
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
ce5aa7d3 sago007 2016-03-13 11:44 217
		if (event.cbutton.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT ) {
ce5aa7d3 sago007 2016-03-13 11:44 218
			return true;
ce5aa7d3 sago007 2016-03-13 11:44 219
		}
ce5aa7d3 sago007 2016-03-13 11:44 220
	}
a077dceb sago007 2016-03-19 19:19 221
	if (event.type == SDL_CONTROLLERAXISMOTION  && event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ) {
a077dceb sago007 2016-03-19 19:19 222
		checkDeadZone(event);
a35ab74b sago007 2016-04-02 10:26 223
		const SDL_ControllerAxisEvent& a = event.caxis;
a077dceb sago007 2016-03-19 19:19 224
		if (getDeadZone(a.which, a.axis)) {
a077dceb sago007 2016-03-19 19:19 225
			if (event.caxis.value > deadZoneLimit) {
a077dceb sago007 2016-03-19 19:19 226
				setDeadZone(a.which,a.axis,false);
a077dceb sago007 2016-03-19 19:19 227
				return true;
a077dceb sago007 2016-03-19 19:19 228
			}
a077dceb sago007 2016-03-19 19:19 229
		}
a077dceb sago007 2016-03-19 19:19 230
	}
ce5aa7d3 sago007 2016-03-13 11:44 231
	return false;
ce5aa7d3 sago007 2016-03-13 11:44 232
}
ce5aa7d3 sago007 2016-03-13 11:44 233
ce5aa7d3 sago007 2016-03-13 11:44 234
bool isPlayerSwitchEvent(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 235
	if (skipThisPlayer(playerNumber, event)) {
ce5aa7d3 sago007 2016-03-13 11:44 236
		return false;
ce5aa7d3 sago007 2016-03-13 11:44 237
	}
ce5aa7d3 sago007 2016-03-13 11:44 238
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
ce5aa7d3 sago007 2016-03-13 11:44 239
		if (event.cbutton.button == SDL_CONTROLLER_BUTTON_A || event.cbutton.button == SDL_CONTROLLER_BUTTON_B ) {
ce5aa7d3 sago007 2016-03-13 11:44 240
			return true;
ce5aa7d3 sago007 2016-03-13 11:44 241
		}
ce5aa7d3 sago007 2016-03-13 11:44 242
	}
ce5aa7d3 sago007 2016-03-13 11:44 243
	return false;
ce5aa7d3 sago007 2016-03-13 11:44 244
}
ce5aa7d3 sago007 2016-03-13 11:44 245
ce5aa7d3 sago007 2016-03-13 11:44 246
bool isPlayerPushEvent(int playerNumber, const SDL_Event& event) {
f2dac7e4 sago007 2016-04-09 19:24 247
	if (skipThisPlayer(playerNumber, event)) {
ce5aa7d3 sago007 2016-03-13 11:44 248
		return false;
ce5aa7d3 sago007 2016-03-13 11:44 249
	}
ce5aa7d3 sago007 2016-03-13 11:44 250
	if (event.type == SDL_CONTROLLERBUTTONDOWN) {
ce5aa7d3 sago007 2016-03-13 11:44 251
		if (event.cbutton.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER || event.cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ) {
ce5aa7d3 sago007 2016-03-13 11:44 252
			return true;
ce5aa7d3 sago007 2016-03-13 11:44 253
		}
ce5aa7d3 sago007 2016-03-13 11:44 254
	}
ce5aa7d3 sago007 2016-03-13 11:44 255
	return false;
ce5aa7d3 sago007 2016-03-13 11:44 256
}