fixed keybord selection for quit game play
This commit is contained in:
@ -586,6 +586,7 @@ bool ApplicationManager::initializeGame() {
|
|||||||
m_stateContext.hoveredButton = &m_hoveredButton;
|
m_stateContext.hoveredButton = &m_hoveredButton;
|
||||||
m_stateContext.showSettingsPopup = &m_showSettingsPopup;
|
m_stateContext.showSettingsPopup = &m_showSettingsPopup;
|
||||||
m_stateContext.showExitConfirmPopup = &m_showExitConfirmPopup;
|
m_stateContext.showExitConfirmPopup = &m_showExitConfirmPopup;
|
||||||
|
m_stateContext.exitPopupSelectedButton = &m_exitPopupSelectedButton;
|
||||||
|
|
||||||
// Create state instances
|
// Create state instances
|
||||||
m_loadingState = std::make_unique<LoadingState>(m_stateContext);
|
m_loadingState = std::make_unique<LoadingState>(m_stateContext);
|
||||||
@ -1048,7 +1049,8 @@ void ApplicationManager::setupStateHandlers() {
|
|||||||
logicalScale,
|
logicalScale,
|
||||||
static_cast<float>(winW),
|
static_cast<float>(winW),
|
||||||
static_cast<float>(winH),
|
static_cast<float>(winH),
|
||||||
m_showExitConfirmPopup
|
m_showExitConfirmPopup,
|
||||||
|
m_exitPopupSelectedButton
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reset viewport
|
// Reset viewport
|
||||||
|
|||||||
@ -94,6 +94,7 @@ private:
|
|||||||
int m_hoveredButton = -1;
|
int m_hoveredButton = -1;
|
||||||
bool m_showSettingsPopup = false;
|
bool m_showSettingsPopup = false;
|
||||||
bool m_showExitConfirmPopup = false;
|
bool m_showExitConfirmPopup = false;
|
||||||
|
int m_exitPopupSelectedButton = 1; // 0 = YES, 1 = NO
|
||||||
uint64_t m_loadStartTicks = 0;
|
uint64_t m_loadStartTicks = 0;
|
||||||
bool m_musicStarted = false;
|
bool m_musicStarted = false;
|
||||||
bool m_musicLoaded = false;
|
bool m_musicLoaded = false;
|
||||||
|
|||||||
@ -277,6 +277,7 @@ static void drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musi
|
|||||||
static double logoAnimCounter = 0.0;
|
static double logoAnimCounter = 0.0;
|
||||||
static bool showSettingsPopup = false;
|
static bool showSettingsPopup = false;
|
||||||
static bool showExitConfirmPopup = false;
|
static bool showExitConfirmPopup = false;
|
||||||
|
static int exitPopupSelectedButton = 1; // 0 = YES, 1 = NO
|
||||||
static bool musicEnabled = true;
|
static bool musicEnabled = true;
|
||||||
static int hoveredButton = -1; // -1 = none, 0 = play, 1 = level, 2 = settings
|
static int hoveredButton = -1; // -1 = none, 0 = play, 1 = level, 2 = settings
|
||||||
static bool isNewHighScore = false;
|
static bool isNewHighScore = false;
|
||||||
@ -650,6 +651,7 @@ int main(int, char **)
|
|||||||
ctx.hoveredButton = &hoveredButton;
|
ctx.hoveredButton = &hoveredButton;
|
||||||
ctx.showSettingsPopup = &showSettingsPopup;
|
ctx.showSettingsPopup = &showSettingsPopup;
|
||||||
ctx.showExitConfirmPopup = &showExitConfirmPopup;
|
ctx.showExitConfirmPopup = &showExitConfirmPopup;
|
||||||
|
ctx.exitPopupSelectedButton = &exitPopupSelectedButton;
|
||||||
|
|
||||||
// Instantiate state objects
|
// Instantiate state objects
|
||||||
auto loadingState = std::make_unique<LoadingState>(ctx);
|
auto loadingState = std::make_unique<LoadingState>(ctx);
|
||||||
@ -1324,7 +1326,8 @@ int main(int, char **)
|
|||||||
logicalScale,
|
logicalScale,
|
||||||
(float)winW,
|
(float)winW,
|
||||||
(float)winH,
|
(float)winH,
|
||||||
showExitConfirmPopup
|
showExitConfirmPopup,
|
||||||
|
exitPopupSelectedButton
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case AppState::GameOver:
|
case AppState::GameOver:
|
||||||
|
|||||||
@ -276,6 +276,7 @@ static void drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musi
|
|||||||
static double logoAnimCounter = 0.0;
|
static double logoAnimCounter = 0.0;
|
||||||
static bool showSettingsPopup = false;
|
static bool showSettingsPopup = false;
|
||||||
static bool showExitConfirmPopup = false;
|
static bool showExitConfirmPopup = false;
|
||||||
|
static int exitPopupSelectedButton = 1; // 0 = YES, 1 = NO
|
||||||
static bool musicEnabled = true;
|
static bool musicEnabled = true;
|
||||||
static int hoveredButton = -1; // -1 = none, 0 = play, 1 = level, 2 = settings
|
static int hoveredButton = -1; // -1 = none, 0 = play, 1 = level, 2 = settings
|
||||||
|
|
||||||
@ -644,6 +645,7 @@ int main(int, char **)
|
|||||||
ctx.hoveredButton = &hoveredButton;
|
ctx.hoveredButton = &hoveredButton;
|
||||||
ctx.showSettingsPopup = &showSettingsPopup;
|
ctx.showSettingsPopup = &showSettingsPopup;
|
||||||
ctx.showExitConfirmPopup = &showExitConfirmPopup;
|
ctx.showExitConfirmPopup = &showExitConfirmPopup;
|
||||||
|
ctx.exitPopupSelectedButton = &exitPopupSelectedButton;
|
||||||
|
|
||||||
// Instantiate state objects
|
// Instantiate state objects
|
||||||
auto loadingState = std::make_unique<LoadingState>(ctx);
|
auto loadingState = std::make_unique<LoadingState>(ctx);
|
||||||
|
|||||||
@ -24,6 +24,17 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
// We keep short-circuited input here; main still owns mouse UI
|
// We keep short-circuited input here; main still owns mouse UI
|
||||||
if (e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
|
if (e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
|
||||||
if (!ctx.game) return;
|
if (!ctx.game) return;
|
||||||
|
|
||||||
|
auto setExitSelection = [&](int value) {
|
||||||
|
if (ctx.exitPopupSelectedButton) {
|
||||||
|
*ctx.exitPopupSelectedButton = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto getExitSelection = [&]() -> int {
|
||||||
|
return ctx.exitPopupSelectedButton ? *ctx.exitPopupSelectedButton : 1;
|
||||||
|
};
|
||||||
|
|
||||||
// Pause toggle (P)
|
// Pause toggle (P)
|
||||||
if (e.key.scancode == SDL_SCANCODE_P) {
|
if (e.key.scancode == SDL_SCANCODE_P) {
|
||||||
bool paused = ctx.game->isPaused();
|
bool paused = ctx.game->isPaused();
|
||||||
@ -35,20 +46,26 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
if (ctx.showExitConfirmPopup && *ctx.showExitConfirmPopup) {
|
if (ctx.showExitConfirmPopup && *ctx.showExitConfirmPopup) {
|
||||||
// Navigate between YES (0) and NO (1) buttons
|
// Navigate between YES (0) and NO (1) buttons
|
||||||
if (e.key.scancode == SDL_SCANCODE_LEFT || e.key.scancode == SDL_SCANCODE_UP) {
|
if (e.key.scancode == SDL_SCANCODE_LEFT || e.key.scancode == SDL_SCANCODE_UP) {
|
||||||
exitPopupSelectedButton = 0; // YES
|
setExitSelection(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.key.scancode == SDL_SCANCODE_RIGHT || e.key.scancode == SDL_SCANCODE_DOWN) {
|
if (e.key.scancode == SDL_SCANCODE_RIGHT || e.key.scancode == SDL_SCANCODE_DOWN) {
|
||||||
exitPopupSelectedButton = 1; // NO
|
setExitSelection(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate selected button with Enter or Space
|
// Activate selected button with Enter or Space
|
||||||
if (e.key.scancode == SDL_SCANCODE_RETURN || e.key.scancode == SDL_SCANCODE_KP_ENTER || e.key.scancode == SDL_SCANCODE_SPACE) {
|
if (e.key.scancode == SDL_SCANCODE_RETURN || e.key.scancode == SDL_SCANCODE_KP_ENTER || e.key.scancode == SDL_SCANCODE_SPACE) {
|
||||||
|
const bool confirmExit = (getExitSelection() == 0);
|
||||||
*ctx.showExitConfirmPopup = false;
|
*ctx.showExitConfirmPopup = false;
|
||||||
if (exitPopupSelectedButton == 0) {
|
if (confirmExit) {
|
||||||
// YES - Reset game and return to menu
|
// YES - Reset game and return to menu
|
||||||
ctx.game->reset(false);
|
if (ctx.startLevelSelection) {
|
||||||
|
ctx.game->reset(*ctx.startLevelSelection);
|
||||||
|
} else {
|
||||||
|
ctx.game->reset(0);
|
||||||
|
}
|
||||||
|
ctx.game->setPaused(false);
|
||||||
if (ctx.stateManager) ctx.stateManager->setState(AppState::Menu);
|
if (ctx.stateManager) ctx.stateManager->setState(AppState::Menu);
|
||||||
} else {
|
} else {
|
||||||
// NO - Just close popup and resume
|
// NO - Just close popup and resume
|
||||||
@ -60,6 +77,7 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
if (e.key.scancode == SDL_SCANCODE_ESCAPE) {
|
if (e.key.scancode == SDL_SCANCODE_ESCAPE) {
|
||||||
*ctx.showExitConfirmPopup = false;
|
*ctx.showExitConfirmPopup = false;
|
||||||
ctx.game->setPaused(false);
|
ctx.game->setPaused(false);
|
||||||
|
setExitSelection(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// While modal is open, suppress other gameplay keys
|
// While modal is open, suppress other gameplay keys
|
||||||
@ -71,6 +89,7 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
if (ctx.showExitConfirmPopup) {
|
if (ctx.showExitConfirmPopup) {
|
||||||
if (ctx.game) ctx.game->setPaused(true);
|
if (ctx.game) ctx.game->setPaused(true);
|
||||||
*ctx.showExitConfirmPopup = true;
|
*ctx.showExitConfirmPopup = true;
|
||||||
|
setExitSelection(1); // Default to NO for safety
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -78,7 +97,7 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
// Tetris controls (only when not paused)
|
// Tetris controls (only when not paused)
|
||||||
if (!ctx.game->isPaused()) {
|
if (!ctx.game->isPaused()) {
|
||||||
// Rotation (still event-based for precise timing)
|
// Rotation (still event-based for precise timing)
|
||||||
if (e.key.scancode == SDL_SCANCODE_UP || e.key.scancode == SDL_SCANCODE_W ||
|
if (e.key.scancode == SDL_SCANCODE_UP || e.key.scancode == SDL_SCANCODE_W ||
|
||||||
e.key.scancode == SDL_SCANCODE_Z) {
|
e.key.scancode == SDL_SCANCODE_Z) {
|
||||||
ctx.game->rotate(1); // Clockwise rotation
|
ctx.game->rotate(1); // Clockwise rotation
|
||||||
return;
|
return;
|
||||||
@ -87,7 +106,7 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
ctx.game->rotate(-1); // Counter-clockwise rotation
|
ctx.game->rotate(-1); // Counter-clockwise rotation
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hard drop (space)
|
// Hard drop (space)
|
||||||
if (e.key.scancode == SDL_SCANCODE_SPACE) {
|
if (e.key.scancode == SDL_SCANCODE_SPACE) {
|
||||||
ctx.game->hardDrop();
|
ctx.game->hardDrop();
|
||||||
@ -95,8 +114,8 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Left/Right movement and soft drop are now handled by
|
// Note: Left/Right movement and soft drop are now handled by
|
||||||
// ApplicationManager's update handler for proper DAS/ARR timing
|
// ApplicationManager's update handler for proper DAS/ARR timing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,5 +14,4 @@ public:
|
|||||||
private:
|
private:
|
||||||
// Local per-state variables if needed
|
// Local per-state variables if needed
|
||||||
bool localPaused = false;
|
bool localPaused = false;
|
||||||
int exitPopupSelectedButton = 1; // 0 = YES, 1 = NO (default to NO for safety)
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -47,6 +47,7 @@ struct StateContext {
|
|||||||
// Menu popups (exposed from main)
|
// Menu popups (exposed from main)
|
||||||
bool* showSettingsPopup = nullptr;
|
bool* showSettingsPopup = nullptr;
|
||||||
bool* showExitConfirmPopup = nullptr; // If true, show "Exit game?" confirmation while playing
|
bool* showExitConfirmPopup = nullptr; // If true, show "Exit game?" confirmation while playing
|
||||||
|
int* exitPopupSelectedButton = nullptr; // 0 = YES, 1 = NO (default)
|
||||||
// Pointer to the application's StateManager so states can request transitions
|
// Pointer to the application's StateManager so states can request transitions
|
||||||
StateManager* stateManager = nullptr;
|
StateManager* stateManager = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user