// Event loop handler // Copyright (C) 2002 David Rosen // Copyright (C) 2003 Zachary Jack Slater // Copyright (C) 2003 Steven Fuller // Copyright (C) 2021 Nguyễn Gia Phong // // This file is part of Black Shades. // // Black Shades is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Black Shades is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Black Shades. If not, see . #include "Game.h" extern float multiplier; extern int visions; extern unsigned int gSourceID[100]; extern unsigned int gSampleSet[100]; extern Camera camera; extern float rad2deg; extern Fog fog; extern int environment; extern int slomo; void Game::HandleKeyDown(char key) { if (mainmenu) return; ALfloat pitch; XYZ facing; switch(key) { case 'l': lasersight ^= 1; break; case 'k': if (debug) timeremaining = 0; break; case 'b': if (!debug) break; alSourcePlay(gSourceID[soulinsound]); pitch = (slomo ^= 1) ? 0.5f : 1.0f; alSourcef(gSourceID[knifesong], AL_PITCH, pitch); alSourcef(gSourceID[shootsong], AL_PITCH, pitch); alSourcef(gSourceID[zombiesong], AL_PITCH, pitch); break; case 'B': if (!debug) break; alSourcePlay(gSourceID[soulinsound]); paused = 1 - paused; break; case 'f': if (!debug) break; alSourcePlay(gSourceID[souloutsound]); facing = 0; facing.z = -1; facing = DoRotation(facing, -camera.rotation2, 0, 0); facing = DoRotation(facing, 0, 0 - camera.rotation, 0); for(int i = 1; i < numpeople; i++) { if (person[i].skeleton.free == 1 || findDistancefast(person[i].playercoords, person[0].playercoords) > 1000) continue; person[i].skeleton.free = 1; person[i].longdead = 1; for (auto& joint : person[i].skeleton.joints) { joint.position = DoRotation(joint.position, 0, person[i].playerrotation, 0); joint.position += person[i].playercoords; joint.realoldposition = joint.position; joint.velocity = DoRotation(joint.velocity, 0, person[i].playerrotation, 0); joint.velocity += person[i].velocity; joint.velocity += facing * 50; joint.velocity.x += abs(Random() % 20) - 10; joint.velocity.y += abs(Random() % 20) - 10; joint.velocity.z += abs(Random() % 20) - 10; } } break; case 'X': if (!debug || person[0].grenphase) break; person[0].ammo = -1; person[0].whichgun++; person[0].grenphase = 0; person[0].reloads[person[0].whichgun] = 3; if (person[0].whichgun > 7) person[0].whichgun = 0; break; } } static int mapinit = 0; static int sdlkeymap[SDLK_LAST]; static unsigned char ourkeys[16]; static void init_sdlkeymap() { int i; for (i = 0; i < SDLK_LAST; i++) sdlkeymap[i] = -1; sdlkeymap[SDLK_1] = MAC_1_KEY; sdlkeymap[SDLK_2] = MAC_2_KEY; sdlkeymap[SDLK_3] = MAC_3_KEY; sdlkeymap[SDLK_4] = MAC_4_KEY; sdlkeymap[SDLK_5] = MAC_5_KEY; sdlkeymap[SDLK_6] = MAC_6_KEY; sdlkeymap[SDLK_7] = MAC_7_KEY; sdlkeymap[SDLK_8] = MAC_8_KEY; sdlkeymap[SDLK_9] = MAC_9_KEY; sdlkeymap[SDLK_0] = MAC_0_KEY; sdlkeymap[SDLK_KP1] = MAC_NUMPAD_1_KEY; sdlkeymap[SDLK_KP2] = MAC_NUMPAD_2_KEY; sdlkeymap[SDLK_KP3] = MAC_NUMPAD_3_KEY; sdlkeymap[SDLK_KP4] = MAC_NUMPAD_4_KEY; sdlkeymap[SDLK_KP5] = MAC_NUMPAD_5_KEY; sdlkeymap[SDLK_KP6] = MAC_NUMPAD_6_KEY; sdlkeymap[SDLK_KP7] = MAC_NUMPAD_7_KEY; sdlkeymap[SDLK_KP8] = MAC_NUMPAD_8_KEY; sdlkeymap[SDLK_KP9] = MAC_NUMPAD_9_KEY; sdlkeymap[SDLK_KP0] = MAC_NUMPAD_0_KEY; sdlkeymap[SDLK_a] = MAC_A_KEY; sdlkeymap[SDLK_b] = MAC_B_KEY; sdlkeymap[SDLK_c] = MAC_C_KEY; sdlkeymap[SDLK_d] = MAC_D_KEY; sdlkeymap[SDLK_e] = MAC_E_KEY; sdlkeymap[SDLK_f] = MAC_F_KEY; sdlkeymap[SDLK_g] = MAC_G_KEY; sdlkeymap[SDLK_h] = MAC_H_KEY; sdlkeymap[SDLK_i] = MAC_I_KEY; sdlkeymap[SDLK_j] = MAC_J_KEY; sdlkeymap[SDLK_k] = MAC_K_KEY; sdlkeymap[SDLK_l] = MAC_L_KEY; sdlkeymap[SDLK_m] = MAC_M_KEY; sdlkeymap[SDLK_n] = MAC_N_KEY; sdlkeymap[SDLK_o] = MAC_O_KEY; sdlkeymap[SDLK_p] = MAC_P_KEY; sdlkeymap[SDLK_q] = MAC_Q_KEY; sdlkeymap[SDLK_r] = MAC_R_KEY; sdlkeymap[SDLK_s] = MAC_S_KEY; sdlkeymap[SDLK_t] = MAC_T_KEY; sdlkeymap[SDLK_u] = MAC_U_KEY; sdlkeymap[SDLK_v] = MAC_V_KEY; sdlkeymap[SDLK_w] = MAC_W_KEY; sdlkeymap[SDLK_x] = MAC_X_KEY; sdlkeymap[SDLK_y] = MAC_Y_KEY; sdlkeymap[SDLK_z] = MAC_Z_KEY; sdlkeymap[SDLK_F1] = MAC_F1_KEY; sdlkeymap[SDLK_F2] = MAC_F2_KEY; sdlkeymap[SDLK_F3] = MAC_F3_KEY; sdlkeymap[SDLK_F4] = MAC_F4_KEY; sdlkeymap[SDLK_F5] = MAC_F5_KEY; sdlkeymap[SDLK_F6] = MAC_F6_KEY; sdlkeymap[SDLK_F7] = MAC_F7_KEY; sdlkeymap[SDLK_F8] = MAC_F8_KEY; sdlkeymap[SDLK_F9] = MAC_F9_KEY; sdlkeymap[SDLK_F10] = MAC_F10_KEY; sdlkeymap[SDLK_F11] = MAC_F11_KEY; sdlkeymap[SDLK_F12] = MAC_F12_KEY; sdlkeymap[SDLK_RETURN] = MAC_RETURN_KEY; sdlkeymap[SDLK_KP_ENTER] = MAC_ENTER_KEY; sdlkeymap[SDLK_TAB] = MAC_TAB_KEY; sdlkeymap[SDLK_SPACE] = MAC_SPACE_KEY; sdlkeymap[SDLK_BACKSPACE] = MAC_DELETE_KEY; sdlkeymap[SDLK_ESCAPE] = MAC_ESCAPE_KEY; sdlkeymap[SDLK_LCTRL] = MAC_CONTROL_KEY; sdlkeymap[SDLK_RCTRL] = MAC_CONTROL_KEY; sdlkeymap[SDLK_LSHIFT] = MAC_SHIFT_KEY; sdlkeymap[SDLK_RSHIFT] = MAC_SHIFT_KEY; sdlkeymap[SDLK_CAPSLOCK] = MAC_CAPS_LOCK_KEY; sdlkeymap[SDLK_LALT] = MAC_OPTION_KEY; sdlkeymap[SDLK_RALT] = MAC_OPTION_KEY; sdlkeymap[SDLK_PAGEUP] = MAC_PAGE_UP_KEY; sdlkeymap[SDLK_PAGEDOWN] = MAC_PAGE_DOWN_KEY; sdlkeymap[SDLK_INSERT] = MAC_INSERT_KEY; sdlkeymap[SDLK_DELETE] = MAC_DEL_KEY; sdlkeymap[SDLK_HOME] = MAC_HOME_KEY; sdlkeymap[SDLK_END] = MAC_END_KEY; sdlkeymap[SDLK_LEFTBRACKET] = MAC_LEFT_BRACKET_KEY; sdlkeymap[SDLK_RIGHTBRACKET] = MAC_RIGHT_BRACKET_KEY; sdlkeymap[SDLK_UP] = MAC_ARROW_UP_KEY; sdlkeymap[SDLK_DOWN] = MAC_ARROW_DOWN_KEY; sdlkeymap[SDLK_LEFT] = MAC_ARROW_LEFT_KEY; sdlkeymap[SDLK_RIGHT] = MAC_ARROW_RIGHT_KEY; mapinit = 1; } void GetKeys(unsigned long *keys) { /* this is just weird */ memcpy(keys, ourkeys, sizeof(ourkeys)); } static void DoSDLKey(Game *g, SDL_Event *event) { if (mapinit == 0) init_sdlkeymap(); int mackey = sdlkeymap[event->key.keysym.sym]; if (mackey != -1) { int index = mackey / 8; int mask = 1 << (mackey % 8); if (event->type == SDL_KEYDOWN) ourkeys[index] |= mask; else ourkeys[index] &= ~mask; } if (event->key.keysym.unicode && !(event->key.keysym.unicode & 0xFF80)) /* hey, at least it was aleady public */ g->HandleKeyDown(event->key.keysym.unicode); } static void ProcessSDLEvents(Game* g) { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_RETURN && event.key.keysym.mod & KMOD_ALT) { SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()); break; } else if (event.key.keysym.sym == SDLK_g && event.key.keysym.mod & KMOD_CTRL) { if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { SDL_WM_GrabInput(SDL_GRAB_ON); SDL_ShowCursor(SDL_DISABLE); } else { SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_ShowCursor(SDL_ENABLE); } break; } case SDL_KEYUP: DoSDLKey(g, &event); break; case SDL_QUIT: exit(0); } } } void eventLoop(Game* game) { unsigned char theKeyMap[16]; game->gQuit = false; game->framespersecond = 60.0f; while (!game->gQuit) { ProcessSDLEvents(game); game->start = TimerGetTime(&game->theTimer); GLfloat oldmult = multiplier; int colaccuracy = min(game->sps, game->sps / game->framespersecond + 1.0f); multiplier /= colaccuracy; for (int i = 0; i < (int) (colaccuracy + 0.5f); i++) game->Tick(); if (game->DrawGLScene()) SDL_GL_SwapBuffers(); else game->gQuit = true; multiplier = oldmult; do { game->end = TimerGetTime(&game->theTimer); game->timetaken = game->end - game->start; game->framespersecond = 6e8f / game->timetaken; } while (game->framespersecond > game->maxfps); game->multiplier5 = game->multiplier4; game->multiplier4 = game->multiplier3; game->multiplier3 = game->multiplier2; game->multiplier2 = 1 / game->framespersecond; multiplier = (game->multiplier2 + game->multiplier3 + game->multiplier4 + game->multiplier5) / 4.0f; multiplier = min(max(multiplier, 0.00001f), 1.0f); if (visions == 1 && !game->mainmenu) multiplier /= 3; if (slomo) multiplier /= 5; if (game->paused) multiplier = 0; GetKeys((unsigned long*) theKeyMap); if (IsKeyDown(theKeyMap, MAC_COMMAND_KEY) &&IsKeyDown(theKeyMap, MAC_Q_KEY)) { game->gQuit = true; if (game->score > game->highscore) { game->highscore = game->score; /* TODO */ ofstream opstream("highscore.txt"); opstream << game->highscore; opstream << "\n"; opstream << game->beatgame; opstream.close(); } } if (IsKeyDown(theKeyMap, MAC_ESCAPE_KEY)) { alSourcePause(gSourceID[rainsound]); game->mainmenu = 1; alSourcePlay(gSourceID[souloutsound]); game->flashamount = 1.0f; game->flashr = game->flashg = game->flashb = 1.0f; alSourceStop(gSourceID[visionsound]); game->whichsong = mainmenusong; alSourceStop(gSourceID[knifesong]); alSourceStop(gSourceID[shootsong]); alSourceStop(gSourceID[zombiesong]); alSourceStop(gSourceID[mainmenusong]); alSourcef(gSourceID[knifesong], AL_MIN_GAIN, 0); alSourcef(gSourceID[shootsong], AL_MIN_GAIN, 0); alSourcef(gSourceID[zombiesong], AL_MIN_GAIN, 0); alSourcef(gSourceID[mainmenusong], AL_MIN_GAIN, 0); alSourcePlay(gSourceID[game->whichsong]); alSourcef(gSourceID[game->whichsong], AL_MIN_GAIN, 1); } } }