Tennix 1.3.4
[tennix.git] / src / input.cc
blobefcc95d897766edbec652a224da8dccc2b791ca7
2 /**
4 * Tennix! SDL Port
5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 **/
24 #include <string.h>
26 #include <cstdlib>
28 #include "tennix.h"
29 #include "graphics.h"
30 #include "game.h"
31 #include "input.h"
32 #include "util.h"
33 #include "archive.h"
36 static InputDevice devices[MAX_INPUT_DEVICES];
37 static int devices_count;
39 #ifdef HAVE_PYTHON
40 #include "tennixpy.h"
41 #endif
43 void init_input(TennixArchive& tnxar)
45 int n, x;
47 SDL_JoystickEventState(SDL_ENABLE);
49 /* keyboard presets */
50 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
51 devices[devices_count].up_key = SDL_SCANCODE_W;
52 devices[devices_count].down_key = SDL_SCANCODE_S;
53 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDL_SCANCODE_D;
54 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDL_SCANCODE_E;
55 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDL_SCANCODE_F;
56 devices[devices_count].icon = GR_INPUT_KEYBOARD_WS;
57 devices[devices_count].exclusive_to_player = 1;
58 strcpy(devices[devices_count].name, "Keyboard (WS/DEF)");
59 devices_count++;
61 /* keyboard presets */
62 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
63 devices[devices_count].up_key = SDL_SCANCODE_O;
64 devices[devices_count].down_key = SDL_SCANCODE_L;
65 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDL_SCANCODE_K;
66 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDL_SCANCODE_I;
67 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDL_SCANCODE_J;
68 devices[devices_count].icon = GR_INPUT_KEYBOARD_OL;
69 devices[devices_count].exclusive_to_player = 2;
70 strcpy(devices[devices_count].name, "Keyboard (OL/KIJ)");
71 devices_count++;
73 /* keyboard presets */
74 devices[devices_count].type = INPUT_TYPE_KEYBOARD;
75 devices[devices_count].up_key = SDL_SCANCODE_UP;
76 devices[devices_count].down_key = SDL_SCANCODE_DOWN;
77 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDL_SCANCODE_SPACE;
78 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDL_SCANCODE_LCTRL;
79 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDL_SCANCODE_LALT;
80 devices[devices_count].icon = GR_INPUT_KEYBOARD_ARROWS;
81 strcpy(devices[devices_count].name, "Keyboard (arrows)");
82 devices_count++;
84 /* mouse */
85 devices[devices_count].type = INPUT_TYPE_MOUSE;
86 devices[devices_count].input_keys[INPUT_KEY_HIT]= SDL_BUTTON(1);
87 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = SDL_BUTTON(2);
88 devices[devices_count].input_keys[INPUT_KEY_SMASH] = SDL_BUTTON(3);
89 devices[devices_count].icon = GR_INPUT_MOUSE;
90 strcpy(devices[devices_count].name, "Mouse");
91 devices_count++;
93 /* network peer */
94 devices[devices_count].type = INPUT_TYPE_NETWORK;
95 devices[devices_count].icon = GR_INPUT_AI; /* FIXME - network icon! */
96 strcpy(devices[devices_count].name, "Network player");
97 devices_count++;
99 /* joysticks */
100 n = SDL_NumJoysticks();
101 for (x=0; x<n && devices_count<MAX_INPUT_DEVICES; x++) {
102 strcpy(devices[devices_count].name, SDL_JoystickNameForIndex(x));
103 devices[devices_count].type = INPUT_TYPE_JOYSTICK;
104 devices[devices_count].joystick = SDL_JoystickOpen(x);
105 devices[devices_count].x_axis = 0;
106 devices[devices_count].y_axis = 0;
107 devices[devices_count].input_keys[INPUT_KEY_HIT]= 0;
108 devices[devices_count].input_keys[INPUT_KEY_TOPSPIN] = 1;
109 devices[devices_count].input_keys[INPUT_KEY_SMASH] = 2;
110 devices[devices_count].icon = GR_INPUT_GAMEPAD;
111 devices_count++;
114 #ifdef HAVE_PYTHON
115 /* This will init Python and load all available bots */
116 tennixpy_init(tnxar);
117 #endif
121 void uninit_input()
123 int i;
124 SDL_JoystickEventState(SDL_IGNORE);
126 for (i=0; i<devices_count; i++) {
127 if (devices[i].type == INPUT_TYPE_JOYSTICK) {
128 SDL_JoystickClose(devices[i].joystick);
129 #ifdef HAVE_PYTHON
130 } else if (devices[i].type == INPUT_TYPE_AI_PYTHON) {
131 tennixpy_unregister_bot(&(devices[i]));
132 #endif
136 #ifdef HAVE_PYTHON
137 tennixpy_uninit();
138 #endif
140 devices_count = 0;
143 Uint8
144 input_pack_axis(float v)
146 static const float min = -1.2;
147 static const float max = 1.2;
148 tnx_assert(v >= min && v < max);
149 return (Uint8)((1U<<7) * (v-min) / (max-min));
152 float
153 input_unpack_axis(Uint8 v)
155 static const float min = -1.2;
156 static const float max = 1.2;
157 tnx_assert(v < (1U<<7));
158 return v * (max-min) / (1U<<7) + min;
162 InputDevice* find_input_devices(unsigned int* count)
164 *count = devices_count;
165 return devices;
168 void input_device_join_game(InputDevice* device, void* gamestate, int player_id)
170 if (device == NULL) {
171 /* player is a c-style bot with no device attached */
172 return;
174 fprintf(stderr, "Input Device %s joins the game\n", device->name);
175 #ifdef HAVE_PYTHON
176 if (device->type == INPUT_TYPE_AI_PYTHON) {
177 tennixpy_create_bot(device, (GameState*)gamestate, player_id);
179 #endif
182 void input_device_part_game(InputDevice* device)
184 if (device == NULL) {
185 /* player is a c-style bot with no device attached */
186 return;
188 #ifdef HAVE_PYTHON
189 if (device->type == INPUT_TYPE_AI_PYTHON) {
190 tennixpy_destroy_bot(device);
192 #endif
193 fprintf(stderr, "Input Device %s leaves the game\n", device->name);
196 const char* input_device_get_name(InputDevice* d)
198 return d->name;
201 float input_device_get_axis(InputDevice* d, unsigned const char axis) {
202 const Uint8 *keystate;
203 //Uint8 mb;
204 Uint8 net_value;
205 float result = 0.0;
207 SDL_PumpEvents();
209 if (d->type == INPUT_TYPE_KEYBOARD) {
210 keystate = SDL_GetKeyboardState(NULL);
211 if (axis == INPUT_AXIS_X) {
212 result = 1.0*keystate[d->right_key] + -1.0*keystate[d->left_key];
213 } else {
214 result = 1.0*keystate[d->down_key] + -1.0*keystate[d->up_key];
216 } else if (d->type == INPUT_TYPE_JOYSTICK) {
217 if (axis == INPUT_AXIS_X) {
218 result = JOYSTICK_PERCENTIZE(SDL_JoystickGetAxis(d->joystick, d->x_axis*2));
219 } else {
220 result = JOYSTICK_PERCENTIZE(SDL_JoystickGetAxis(d->joystick, 1+d->y_axis*2));
222 } else if (d->type == INPUT_TYPE_MOUSE) {
223 //mb = SDL_GetMouseState(&d->mx, &d->my);
224 if (axis == INPUT_AXIS_X) {
225 /* Not x-movement yet (PLAYER_MOVE_X is not defined!) */
226 /*if (std::abs(d->mx - d->player_x) > PLAYER_MOVE_X) {
227 if (d->mx > d->player_x) {
228 return 1.0;
229 } else if (d->mx < d->player_x) {
230 return -1.0;
233 } else {
234 if (std::abs(d->my - d->player_y) > PLAYER_MOVE_Y) {
235 if (d->my > d->player_y) {
236 result = 1.0;
237 } else if (d->my < d->player_y) {
238 result = -1.0;
242 #ifdef HAVE_PYTHON
243 } else if (d->type == INPUT_TYPE_AI_PYTHON) {
244 result = tennixpy_bot_get_axis(d, axis);
245 #endif
246 } else if (d->type == INPUT_TYPE_NETWORK) {
247 if (axis == INPUT_AXIS_X) {
248 result = input_unpack_axis(d->net.x);
249 } else if (axis == INPUT_AXIS_Y) {
250 result = input_unpack_axis(d->net.y);
252 } else {
253 tnx_assert(0/*unimplemented*/);
256 net_value = input_pack_axis(result);
257 if (axis == INPUT_AXIS_X) {
258 d->net.x = net_value;
259 } else if (axis == INPUT_AXIS_Y) {
260 d->net.y = net_value;
263 return result;
266 char input_device_get_key(InputDevice* d, unsigned const char key) {
267 Uint8 mb;
268 char result = 0;
269 SDL_PumpEvents();
271 if (d->type == INPUT_TYPE_KEYBOARD) {
272 result = SDL_GetKeyboardState(NULL)[d->input_keys[key]];
273 } else if (d->type == INPUT_TYPE_JOYSTICK) {
274 result = SDL_JoystickGetButton(d->joystick, d->input_keys[key]);
275 } else if (d->type == INPUT_TYPE_MOUSE) {
276 mb = SDL_GetMouseState(NULL, NULL);
277 result = (mb & d->input_keys[key]) != 0;
278 #ifdef HAVE_PYTHON
279 } else if (d->type == INPUT_TYPE_AI_PYTHON) {
280 result = tennixpy_bot_get_key(d, key);
281 #endif
282 } else if (d->type == INPUT_TYPE_NETWORK) {
283 result = (d->net.keys & (1<<key));
284 } else {
285 tnx_assert(0/*unimplemented*/);
288 /* Update the input device's NetworkInputData struct */
289 if(result) {
290 d->net.keys |= (1<<key);
291 } else {
292 d->net.keys &= ~(1<<key);
295 return result;
299 InputDevice *
300 input_add_device()
302 tnx_assert(devices_count < MAX_INPUT_DEVICES);
303 return &(devices[devices_count++]);