void MenuLoop(MenuSystem *menu) { assert(menu->numExitTypes > 0); for (;; SDL_Delay(10)) { MusicSetPlaying(&gSoundDevice, SDL_GetAppState() & SDL_APPINPUTFOCUS); // Input InputPoll(menu->inputDevices, SDL_GetTicks()); // Update if (menu->current->type == MENU_TYPE_KEYS && menu->current->u.normal.changeKeyMenu != NULL) { MenuProcessChangeKey(menu->current); } else { int cmd = GetMenuCmd(gPlayerDatas); MenuProcessCmd(menu, cmd); } if (MenuIsExit(menu)) { break; } // Draw GraphicsBlitBkg(menu->graphics); ShowControls(); MenuDisplay(menu); BlitFlip(menu->graphics, &gConfig.Graphics); } }
int NumPlayersSelection( int *numPlayers, campaign_mode_e mode, GraphicsDevice *graphics, InputDevices *input) { MenuSystem ms; int i; int res = 0; MenuSystemInit( &ms, input, graphics, Vec2iZero(), Vec2iNew( graphics->cachedConfig.ResolutionWidth, graphics->cachedConfig.ResolutionHeight)); ms.root = ms.current = MenuCreateNormal( "", "Select number of players", MENU_TYPE_NORMAL, 0); for (i = 0; i < MAX_PLAYERS; i++) { if (mode == CAMPAIGN_MODE_DOGFIGHT && i == 0) { // At least two players for dogfights continue; } char buf[2]; sprintf(buf, "%d", i + 1); MenuAddSubmenu(ms.current, MenuCreateReturn(buf, i + 1)); } MenuAddExitType(&ms, MENU_TYPE_RETURN); for (;;) { int cmd; InputPoll(&gInputDevices, SDL_GetTicks()); if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE)) { res = 0; break; // hack to allow exit } cmd = GetMenuCmd(gPlayerDatas); MenuProcessCmd(&ms, cmd); if (MenuIsExit(&ms)) { *numPlayers = ms.current->u.returnCode; res = 1; break; } GraphicsBlitBkg(graphics); MenuDisplay(&ms); BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); } MenuSystemTerminate(&ms); return res; }
static GameLoopResult PlayerEquipUpdate(void *data) { PlayerEquipData *pData = data; // Check if anyone pressed escape int cmds[MAX_LOCAL_PLAYERS]; memset(cmds, 0, sizeof cmds); GetPlayerCmds(&gEventHandlers, &cmds); if (EventIsEscape(&gEventHandlers, cmds, GetMenuCmd(&gEventHandlers))) { pData->IsOK = false; return UPDATE_RESULT_EXIT; } // Update menus int idx = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++, idx++) { const PlayerData *p = CArrayGet(&gPlayerDatas, i); if (!p->IsLocal) { idx--; continue; } if (!MenuIsExit(&pData->menus[idx].ms)) { MenuProcessCmd(&pData->menus[idx].ms, cmds[idx]); } else if (p->weaponCount == 0) { // Check exit condition; must have selected at least one weapon // Otherwise reset the current menu pData->menus[idx].ms.current = pData->menus[idx].ms.root; } } bool isDone = true; for (int i = 0; i < GetNumPlayers(false, false, true); i++) { if (strcmp(pData->menus[i].ms.current->name, "(End)") != 0) { isDone = false; } } if (isDone) { pData->IsOK = true; return UPDATE_RESULT_EXIT; } return UPDATE_RESULT_DRAW; }
static GameLoopResult MenuUpdate(void *data) { MenuSystem *ms = data; if (ms->current->type == MENU_TYPE_KEYS && ms->current->u.normal.changeKeyMenu != NULL) { MenuProcessChangeKey(ms->current); } else { const int cmd = GetMenuCmd(ms->handlers); if (cmd) { MenuProcessCmd(ms, cmd); } } // Check if anyone pressed escape, or we need a hard exit int cmds[MAX_LOCAL_PLAYERS]; memset(cmds, 0, sizeof cmds); GetPlayerCmds(&gEventHandlers, &cmds); const bool aborted = ms->allowAborts && EventIsEscape(&gEventHandlers, cmds, GetMenuCmd(&gEventHandlers)); if (aborted || ms->handlers->HasQuit) { ms->hasAbort = true; return UPDATE_RESULT_EXIT; } if (MenuIsExit(ms)) { return UPDATE_RESULT_EXIT; } if (ms->current->customPostUpdateFunc) { ms->current->customPostUpdateFunc( ms->current, ms->current->customPostUpdateData); } return UPDATE_RESULT_DRAW; }
int PlayerEquip(int numPlayers, GraphicsDevice *graphics) { int i; WeaponMenu menus[MAX_PLAYERS]; for (i = 0; i < numPlayers; i++) { WeaponMenuCreate( &menus[i], numPlayers, i, &gCampaign.Setting.characters.players[i], &gPlayerDatas[i], &gInputDevices, graphics, &gConfig.Input); } debug(D_NORMAL, "\n"); for (;;) { int cmds[MAX_PLAYERS]; int isDone = 1; InputPoll(&gInputDevices, SDL_GetTicks()); if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE)) { return 0; // hack to exit from menu } GetPlayerCmds(&cmds, gPlayerDatas); for (i = 0; i < numPlayers; i++) { if (!MenuIsExit(&menus[i].ms)) { MenuProcessCmd(&menus[i].ms, cmds[i]); } else if (gPlayerDatas[i].weaponCount == 0) { // Check exit condition; must have selected at least one weapon // Otherwise reset the current menu menus[i].ms.current = menus[i].ms.root; } } for (i = 0; i < numPlayers; i++) { if (!MenuIsExit(&menus[i].ms)) { isDone = 0; } } if (isDone) { break; } GraphicsBlitBkg(graphics); for (i = 0; i < numPlayers; i++) { MenuDisplay(&menus[i].ms); } BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); } for (i = 0; i < numPlayers; i++) { MenuSystemTerminate(&menus[i].ms); } return 1; }
int PlayerSelection(int numPlayers, GraphicsDevice *graphics) { int i; int hasInputDevice[MAX_PLAYERS]; PlayerSelectMenu menus[MAX_PLAYERS]; for (i = 0; i < numPlayers; i++) { PlayerSelectMenusCreate( &menus[i], numPlayers, i, &gCampaign.Setting.characters.players[i], &gPlayerDatas[i], &gInputDevices, graphics, &gConfig.Input); hasInputDevice[i] = 0; } KeyInit(&gInputDevices.keyboard); for (;;) { int cmds[MAX_PLAYERS]; int isDone = 1; InputPoll(&gInputDevices, SDL_GetTicks()); if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE)) { // TODO: destroy menus return 0; // hack to allow exit } GetPlayerCmds(&cmds, gPlayerDatas); for (i = 0; i < numPlayers; i++) { if (hasInputDevice[i] && !MenuIsExit(&menus[i].ms)) { MenuProcessCmd(&menus[i].ms, cmds[i]); } } for (i = 0; i < numPlayers; i++) { if (!MenuIsExit(&menus[i].ms)) { isDone = 0; } } if (isDone) { break; } AssignPlayerInputDevices( hasInputDevice, numPlayers, gPlayerDatas, &gInputDevices, &gConfig.Input); GraphicsBlitBkg(graphics); for (i = 0; i < numPlayers; i++) { if (hasInputDevice[i]) { MenuDisplay(&menus[i].ms); } else { Vec2i center; const char *prompt = "Press Fire to join..."; Vec2i offset = Vec2iScaleDiv(TextGetSize(prompt), -2); int w = graphics->cachedConfig.ResolutionWidth; int h = graphics->cachedConfig.ResolutionHeight; switch (numPlayers) { case 1: // Center of screen center = Vec2iNew(w / 2, h / 2); break; case 2: // Side by side center = Vec2iNew(i * w / 2 + w / 4, h / 2); break; case 3: case 4: // Four corners center = Vec2iNew( (i & 1) * w / 2 + w / 4, (i / 2) * h / 2 + h / 4); break; default: assert(0 && "not implemented"); break; } DrawTextString(prompt, graphics, Vec2iAdd(center, offset)); } } BlitFlip(graphics, &gConfig.Graphics); SDL_Delay(10); } for (i = 0; i < numPlayers; i++) { MenuSystemTerminate(&menus[i].ms); } return 1; }
static GameLoopResult PlayerSelectionUpdate(void *data) { PlayerSelectionData *pData = data; // Check if anyone pressed escape int cmds[MAX_LOCAL_PLAYERS]; memset(cmds, 0, sizeof cmds); GetPlayerCmds(&gEventHandlers, &cmds); if (EventIsEscape(&gEventHandlers, cmds, GetMenuCmd(&gEventHandlers))) { pData->IsOK = false; return UPDATE_RESULT_EXIT; } // Menu input int idx = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++, idx++) { const PlayerData *p = CArrayGet(&gPlayerDatas, i); if (!p->IsLocal) { idx--; continue; } if (p->inputDevice != INPUT_DEVICE_UNSET && !MenuIsExit(&pData->menus[idx].ms) && cmds[idx]) { MenuProcessCmd(&pData->menus[idx].ms, cmds[idx]); } } // Conditions for exit: at least one player has selected "Done", // and no other players, if any, are still selecting their player // The "players" with no input device are turned into AIs bool hasAtLeastOneInput = false; bool isDone = true; idx = 0; for (int i = 0; i < (int)gPlayerDatas.size; i++, idx++) { const PlayerData *p = CArrayGet(&gPlayerDatas, i); if (!p->IsLocal) { idx--; continue; } if (p->inputDevice != INPUT_DEVICE_UNSET) { hasAtLeastOneInput = true; if (strcmp(pData->menus[idx].ms.current->name, "Done") != 0) { isDone = false; } } } if (isDone && hasAtLeastOneInput) { return UPDATE_RESULT_EXIT; } AssignPlayerInputDevices(&gEventHandlers); return UPDATE_RESULT_DRAW; }