basic gameplay for cooperative
This commit is contained in:
@ -442,7 +442,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
case SDL_SCANCODE_LEFT:
|
||||
case SDL_SCANCODE_UP:
|
||||
{
|
||||
const int total = 7;
|
||||
const int total = MENU_BTN_COUNT;
|
||||
selectedButton = (selectedButton + total - 1) % total;
|
||||
// brief bright flash on navigation
|
||||
buttonFlash = 1.0;
|
||||
@ -451,7 +451,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
case SDL_SCANCODE_RIGHT:
|
||||
case SDL_SCANCODE_DOWN:
|
||||
{
|
||||
const int total = 7;
|
||||
const int total = MENU_BTN_COUNT;
|
||||
selectedButton = (selectedButton + 1) % total;
|
||||
// brief bright flash on navigation
|
||||
buttonFlash = 1.0;
|
||||
@ -470,6 +470,17 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
triggerPlay();
|
||||
break;
|
||||
case 1:
|
||||
// Cooperative play
|
||||
if (ctx.game) {
|
||||
ctx.game->setMode(GameMode::Cooperate);
|
||||
ctx.game->reset(ctx.startLevelSelection ? *ctx.startLevelSelection : 0);
|
||||
}
|
||||
if (ctx.coopGame) {
|
||||
ctx.coopGame->reset(ctx.startLevelSelection ? *ctx.startLevelSelection : 0);
|
||||
}
|
||||
triggerPlay();
|
||||
break;
|
||||
case 2:
|
||||
// Start challenge run at level 1
|
||||
if (ctx.game) {
|
||||
ctx.game->setMode(GameMode::Challenge);
|
||||
@ -480,7 +491,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
}
|
||||
triggerPlay();
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
// Toggle inline level selector HUD (show/hide)
|
||||
if (!levelPanelVisible && !levelPanelAnimating) {
|
||||
levelPanelAnimating = true;
|
||||
@ -492,7 +503,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
levelDirection = -1; // hide
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// Toggle the options panel with an animated slide-in/out.
|
||||
if (!optionsVisible && !optionsAnimating) {
|
||||
optionsAnimating = true;
|
||||
@ -502,7 +513,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
optionsDirection = -1; // hide
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
// Toggle the inline HELP HUD (show/hide)
|
||||
if (!helpPanelVisible && !helpPanelAnimating) {
|
||||
helpPanelAnimating = true;
|
||||
@ -513,7 +524,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
helpDirection = -1; // hide
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
// Toggle the inline ABOUT HUD (show/hide)
|
||||
if (!aboutPanelVisible && !aboutPanelAnimating) {
|
||||
aboutPanelAnimating = true;
|
||||
@ -523,7 +534,7 @@ void MenuState::handleEvent(const SDL_Event& e) {
|
||||
aboutDirection = -1;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
// Show the inline exit HUD
|
||||
if (!exitPanelVisible && !exitPanelAnimating) {
|
||||
exitPanelAnimating = true;
|
||||
|
||||
@ -21,7 +21,7 @@ public:
|
||||
void showAboutPanel(bool show);
|
||||
|
||||
private:
|
||||
int selectedButton = 0; // 0 = PLAY, 1 = LEVEL, 2 = OPTIONS, 3 = HELP, 4 = ABOUT, 5 = EXIT
|
||||
int selectedButton = 0; // 0=PLAY,1=COOPERATE,2=CHALLENGE,3=LEVEL,4=OPTIONS,5=HELP,6=ABOUT,7=EXIT
|
||||
|
||||
// Button icons (optional - will use text if nullptr)
|
||||
SDL_Texture* playIcon = nullptr;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "PlayingState.h"
|
||||
#include "../core/state/StateManager.h"
|
||||
#include "../gameplay/core/Game.h"
|
||||
#include "../gameplay/coop/CoopGame.h"
|
||||
#include "../gameplay/effects/LineEffect.h"
|
||||
#include "../persistence/Scores.h"
|
||||
#include "../audio/Audio.h"
|
||||
@ -18,12 +19,15 @@ PlayingState::PlayingState(StateContext& ctx) : State(ctx) {}
|
||||
|
||||
void PlayingState::onEnter() {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[PLAYING] Entering Playing state");
|
||||
// Initialize the game based on mode: endless uses chosen start level, challenge keeps its run state
|
||||
// Initialize the game based on mode: endless/cooperate use chosen start level, challenge keeps its run state
|
||||
if (ctx.game) {
|
||||
if (ctx.game->getMode() == GameMode::Endless) {
|
||||
if (ctx.game->getMode() == GameMode::Endless || ctx.game->getMode() == GameMode::Cooperate) {
|
||||
if (ctx.startLevelSelection) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[PLAYING] Resetting game with level %d", *ctx.startLevelSelection);
|
||||
ctx.game->reset(*ctx.startLevelSelection);
|
||||
if (ctx.game->getMode() == GameMode::Cooperate && ctx.coopGame) {
|
||||
ctx.coopGame->reset(*ctx.startLevelSelection);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Challenge run is prepared before entering; ensure gameplay is unpaused
|
||||
@ -45,124 +49,164 @@ void PlayingState::onExit() {
|
||||
}
|
||||
|
||||
void PlayingState::handleEvent(const SDL_Event& e) {
|
||||
if (!ctx.game) return;
|
||||
|
||||
// If a transport animation is active, ignore gameplay input entirely.
|
||||
if (GameRenderer::isTransportActive()) {
|
||||
return;
|
||||
}
|
||||
// We keep short-circuited input here; main still owns mouse UI
|
||||
if (e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
|
||||
if (!ctx.game) return;
|
||||
|
||||
auto setExitSelection = [&](int value) {
|
||||
if (ctx.exitPopupSelectedButton) {
|
||||
*ctx.exitPopupSelectedButton = value;
|
||||
}
|
||||
};
|
||||
const bool coopActive = ctx.game->getMode() == GameMode::Cooperate && ctx.coopGame;
|
||||
|
||||
auto getExitSelection = [&]() -> int {
|
||||
return ctx.exitPopupSelectedButton ? *ctx.exitPopupSelectedButton : 1;
|
||||
};
|
||||
auto setExitSelection = [&](int idx) {
|
||||
if (ctx.exitPopupSelectedButton) {
|
||||
*ctx.exitPopupSelectedButton = idx;
|
||||
}
|
||||
};
|
||||
auto getExitSelection = [&]() -> int {
|
||||
return ctx.exitPopupSelectedButton ? *ctx.exitPopupSelectedButton : 1;
|
||||
};
|
||||
|
||||
// Pause toggle (P)
|
||||
if (e.key.scancode == SDL_SCANCODE_P) {
|
||||
bool paused = ctx.game->isPaused();
|
||||
ctx.game->setPaused(!paused);
|
||||
if (e.type != SDL_EVENT_KEY_DOWN || e.key.repeat) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If exit-confirm popup is visible, handle shortcuts here
|
||||
if (ctx.showExitConfirmPopup && *ctx.showExitConfirmPopup) {
|
||||
// Navigate between YES (0) and NO (1) buttons
|
||||
if (e.key.scancode == SDL_SCANCODE_LEFT || e.key.scancode == SDL_SCANCODE_UP) {
|
||||
setExitSelection(0);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_RIGHT || e.key.scancode == SDL_SCANCODE_DOWN) {
|
||||
setExitSelection(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// If exit-confirm popup is visible, handle shortcuts here
|
||||
if (ctx.showExitConfirmPopup && *ctx.showExitConfirmPopup) {
|
||||
// Navigate between YES (0) and NO (1) buttons
|
||||
if (e.key.scancode == SDL_SCANCODE_LEFT || e.key.scancode == SDL_SCANCODE_UP) {
|
||||
setExitSelection(0);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_RIGHT || e.key.scancode == SDL_SCANCODE_DOWN) {
|
||||
setExitSelection(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
const bool confirmExit = (getExitSelection() == 0);
|
||||
*ctx.showExitConfirmPopup = false;
|
||||
if (confirmExit) {
|
||||
// YES - Reset game and return to menu
|
||||
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);
|
||||
// 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) {
|
||||
const bool confirmExit = (getExitSelection() == 0);
|
||||
*ctx.showExitConfirmPopup = false;
|
||||
if (confirmExit) {
|
||||
// YES - Reset game and return to menu
|
||||
if (ctx.startLevelSelection) {
|
||||
ctx.game->reset(*ctx.startLevelSelection);
|
||||
} else {
|
||||
// NO - Just close popup and resume
|
||||
ctx.game->setPaused(false);
|
||||
ctx.game->reset(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Cancel with Esc (same as NO)
|
||||
if (e.key.scancode == SDL_SCANCODE_ESCAPE) {
|
||||
*ctx.showExitConfirmPopup = false;
|
||||
ctx.game->setPaused(false);
|
||||
setExitSelection(1);
|
||||
return;
|
||||
if (ctx.stateManager) ctx.stateManager->setState(AppState::Menu);
|
||||
} else {
|
||||
// NO - Just close popup and resume
|
||||
ctx.game->setPaused(false);
|
||||
}
|
||||
// While modal is open, suppress other gameplay keys
|
||||
return;
|
||||
}
|
||||
|
||||
// ESC key - open confirmation popup
|
||||
// Cancel with Esc (same as NO)
|
||||
if (e.key.scancode == SDL_SCANCODE_ESCAPE) {
|
||||
if (ctx.showExitConfirmPopup) {
|
||||
if (ctx.game) ctx.game->setPaused(true);
|
||||
*ctx.showExitConfirmPopup = true;
|
||||
setExitSelection(1); // Default to NO for safety
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug: skip to next challenge level (B)
|
||||
if (e.key.scancode == SDL_SCANCODE_B && ctx.game && ctx.game->getMode() == GameMode::Challenge) {
|
||||
ctx.game->beginNextChallengeLevel();
|
||||
// Cancel any countdown so play resumes immediately on the new level
|
||||
if (ctx.gameplayCountdownActive) *ctx.gameplayCountdownActive = false;
|
||||
if (ctx.menuPlayCountdownArmed) *ctx.menuPlayCountdownArmed = false;
|
||||
*ctx.showExitConfirmPopup = false;
|
||||
ctx.game->setPaused(false);
|
||||
setExitSelection(1);
|
||||
return;
|
||||
}
|
||||
// While modal is open, suppress other gameplay keys
|
||||
return;
|
||||
}
|
||||
|
||||
// ESC key - open confirmation popup
|
||||
if (e.key.scancode == SDL_SCANCODE_ESCAPE) {
|
||||
if (ctx.showExitConfirmPopup) {
|
||||
ctx.game->setPaused(true);
|
||||
*ctx.showExitConfirmPopup = true;
|
||||
setExitSelection(1); // Default to NO for safety
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug: skip to next challenge level (B)
|
||||
if (e.key.scancode == SDL_SCANCODE_B && ctx.game->getMode() == GameMode::Challenge) {
|
||||
ctx.game->beginNextChallengeLevel();
|
||||
// Cancel any countdown so play resumes immediately on the new level
|
||||
if (ctx.gameplayCountdownActive) *ctx.gameplayCountdownActive = false;
|
||||
if (ctx.menuPlayCountdownArmed) *ctx.menuPlayCountdownArmed = false;
|
||||
ctx.game->setPaused(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tetris controls (only when not paused)
|
||||
if (ctx.game->isPaused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (coopActive && ctx.coopGame) {
|
||||
// Player 1 (left): A/D move via DAS in ApplicationManager; here handle rotations/hold/hard-drop
|
||||
if (e.key.scancode == SDL_SCANCODE_W) {
|
||||
ctx.coopGame->rotate(CoopGame::PlayerSide::Left, 1);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_Q) {
|
||||
ctx.coopGame->rotate(CoopGame::PlayerSide::Left, -1);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_LSHIFT) {
|
||||
SoundEffectManager::instance().playSound("hard_drop", 0.7f);
|
||||
ctx.coopGame->hardDrop(CoopGame::PlayerSide::Left);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_LCTRL) {
|
||||
ctx.coopGame->holdCurrent(CoopGame::PlayerSide::Left);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tetris controls (only when not paused)
|
||||
if (!ctx.game->isPaused()) {
|
||||
// Hold / swap current piece (H)
|
||||
if (e.key.scancode == SDL_SCANCODE_H) {
|
||||
ctx.game->holdCurrent();
|
||||
return;
|
||||
}
|
||||
// Player 2 (right): arrow keys move via DAS; rotations/hold/hard-drop here
|
||||
if (e.key.scancode == SDL_SCANCODE_UP) {
|
||||
bool upIsCW = Settings::instance().isUpRotateClockwise();
|
||||
ctx.coopGame->rotate(CoopGame::PlayerSide::Right, upIsCW ? 1 : -1);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_RALT) {
|
||||
ctx.coopGame->rotate(CoopGame::PlayerSide::Right, -1);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_RSHIFT) {
|
||||
SoundEffectManager::instance().playSound("hard_drop", 0.7f);
|
||||
ctx.coopGame->hardDrop(CoopGame::PlayerSide::Right);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_RCTRL) {
|
||||
ctx.coopGame->holdCurrent(CoopGame::PlayerSide::Right);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Single-player classic controls
|
||||
// Hold / swap current piece (H)
|
||||
if (e.key.scancode == SDL_SCANCODE_H) {
|
||||
ctx.game->holdCurrent();
|
||||
return;
|
||||
}
|
||||
|
||||
// Rotation (still event-based for precise timing)
|
||||
if (e.key.scancode == SDL_SCANCODE_UP) {
|
||||
// Use user setting to determine whether UP rotates clockwise
|
||||
bool upIsCW = Settings::instance().isUpRotateClockwise();
|
||||
ctx.game->rotate(upIsCW ? 1 : -1);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_X) {
|
||||
// Toggle the mapping so UP will rotate in the opposite direction
|
||||
bool current = Settings::instance().isUpRotateClockwise();
|
||||
Settings::instance().setUpRotateClockwise(!current);
|
||||
Settings::instance().save();
|
||||
// Play a subtle feedback sound if available
|
||||
SoundEffectManager::instance().playSound("menu_toggle", 0.6f);
|
||||
return;
|
||||
}
|
||||
// Rotation (still event-based for precise timing)
|
||||
if (e.key.scancode == SDL_SCANCODE_UP) {
|
||||
// Use user setting to determine whether UP rotates clockwise
|
||||
bool upIsCW = Settings::instance().isUpRotateClockwise();
|
||||
ctx.game->rotate(upIsCW ? 1 : -1);
|
||||
return;
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_X) {
|
||||
// Toggle the mapping so UP will rotate in the opposite direction
|
||||
bool current = Settings::instance().isUpRotateClockwise();
|
||||
Settings::instance().setUpRotateClockwise(!current);
|
||||
Settings::instance().save();
|
||||
// Play a subtle feedback sound if available
|
||||
SoundEffectManager::instance().playSound("menu_toggle", 0.6f);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hard drop (space)
|
||||
if (e.key.scancode == SDL_SCANCODE_SPACE) {
|
||||
SoundEffectManager::instance().playSound("hard_drop", 0.7f);
|
||||
ctx.game->hardDrop();
|
||||
return;
|
||||
}
|
||||
// Hard drop (space)
|
||||
if (e.key.scancode == SDL_SCANCODE_SPACE) {
|
||||
SoundEffectManager::instance().playSound("hard_drop", 0.7f);
|
||||
ctx.game->hardDrop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +216,21 @@ void PlayingState::handleEvent(const SDL_Event& e) {
|
||||
|
||||
void PlayingState::update(double frameMs) {
|
||||
if (!ctx.game) return;
|
||||
|
||||
|
||||
const bool coopActive = ctx.game->getMode() == GameMode::Cooperate && ctx.coopGame;
|
||||
|
||||
if (coopActive) {
|
||||
// Visual effects only; gravity and movement handled from ApplicationManager for coop
|
||||
ctx.coopGame->updateVisualEffects(frameMs);
|
||||
// Update line clear effect for coop mode as well (renderer starts the effect)
|
||||
if (ctx.lineEffect && ctx.lineEffect->isActive()) {
|
||||
if (ctx.lineEffect->update(frameMs / 1000.0f)) {
|
||||
ctx.coopGame->clearCompletedLines();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.game->updateVisualEffects(frameMs);
|
||||
// If a transport animation is active, pause gameplay updates and ignore inputs
|
||||
if (GameRenderer::isTransportActive()) {
|
||||
@ -204,6 +262,8 @@ void PlayingState::update(double frameMs) {
|
||||
void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logicalVP) {
|
||||
if (!ctx.game) return;
|
||||
|
||||
const bool coopActive = ctx.game->getMode() == GameMode::Cooperate && ctx.coopGame;
|
||||
|
||||
// Get current window size
|
||||
int winW = 0, winH = 0;
|
||||
SDL_GetRenderOutputSize(renderer, &winW, &winH);
|
||||
@ -244,26 +304,44 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
|
||||
// Render game content (no overlays)
|
||||
// If a transport effect was requested due to a recent spawn, start it here so
|
||||
// the renderer has the correct layout and renderer context to compute coords.
|
||||
if (s_pendingTransport) {
|
||||
if (!coopActive && s_pendingTransport) {
|
||||
GameRenderer::startTransportEffectForGame(ctx.game, ctx.blocksTex, 1200.0f, 1000.0f, logicalScale, (float)winW, (float)winH, 0.4f);
|
||||
s_pendingTransport = false;
|
||||
}
|
||||
|
||||
GameRenderer::renderPlayingState(
|
||||
renderer,
|
||||
ctx.game,
|
||||
ctx.pixelFont,
|
||||
ctx.lineEffect,
|
||||
ctx.blocksTex,
|
||||
ctx.asteroidsTex,
|
||||
ctx.statisticsPanelTex,
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
countdown,
|
||||
1200.0f, // LOGICAL_W
|
||||
1000.0f, // LOGICAL_H
|
||||
logicalScale,
|
||||
if (coopActive && ctx.coopGame) {
|
||||
GameRenderer::renderCoopPlayingState(
|
||||
renderer,
|
||||
ctx.coopGame,
|
||||
ctx.pixelFont,
|
||||
ctx.lineEffect,
|
||||
ctx.blocksTex,
|
||||
ctx.statisticsPanelTex,
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
1200.0f,
|
||||
1000.0f,
|
||||
logicalScale,
|
||||
(float)winW,
|
||||
(float)winH
|
||||
);
|
||||
} else {
|
||||
GameRenderer::renderPlayingState(
|
||||
renderer,
|
||||
ctx.game,
|
||||
ctx.pixelFont,
|
||||
ctx.lineEffect,
|
||||
ctx.blocksTex,
|
||||
ctx.asteroidsTex,
|
||||
ctx.statisticsPanelTex,
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
countdown,
|
||||
1200.0f, // LOGICAL_W
|
||||
1000.0f, // LOGICAL_H
|
||||
logicalScale,
|
||||
(float)winW,
|
||||
(float)winH,
|
||||
challengeClearFx,
|
||||
@ -272,7 +350,8 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
|
||||
challengeClearDuration,
|
||||
countdown ? nullptr : ctx.challengeStoryText,
|
||||
countdown ? 0.0f : (ctx.challengeStoryAlpha ? *ctx.challengeStoryAlpha : 0.0f)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
// Reset to screen
|
||||
SDL_SetRenderTarget(renderer, nullptr);
|
||||
@ -341,33 +420,53 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
|
||||
|
||||
} else {
|
||||
// Render normally directly to screen
|
||||
if (s_pendingTransport) {
|
||||
if (!coopActive && s_pendingTransport) {
|
||||
GameRenderer::startTransportEffectForGame(ctx.game, ctx.blocksTex, 1200.0f, 1000.0f, logicalScale, (float)winW, (float)winH, 0.4f);
|
||||
s_pendingTransport = false;
|
||||
}
|
||||
GameRenderer::renderPlayingState(
|
||||
renderer,
|
||||
ctx.game,
|
||||
ctx.pixelFont,
|
||||
ctx.lineEffect,
|
||||
ctx.blocksTex,
|
||||
ctx.asteroidsTex,
|
||||
ctx.statisticsPanelTex,
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
countdown,
|
||||
1200.0f,
|
||||
1000.0f,
|
||||
logicalScale,
|
||||
(float)winW,
|
||||
(float)winH,
|
||||
challengeClearFx,
|
||||
challengeClearOrder,
|
||||
challengeClearElapsed,
|
||||
challengeClearDuration,
|
||||
countdown ? nullptr : ctx.challengeStoryText,
|
||||
countdown ? 0.0f : (ctx.challengeStoryAlpha ? *ctx.challengeStoryAlpha : 0.0f)
|
||||
);
|
||||
|
||||
if (coopActive && ctx.coopGame) {
|
||||
GameRenderer::renderCoopPlayingState(
|
||||
renderer,
|
||||
ctx.coopGame,
|
||||
ctx.pixelFont,
|
||||
ctx.lineEffect,
|
||||
ctx.blocksTex,
|
||||
ctx.statisticsPanelTex,
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
1200.0f,
|
||||
1000.0f,
|
||||
logicalScale,
|
||||
(float)winW,
|
||||
(float)winH
|
||||
);
|
||||
} else {
|
||||
GameRenderer::renderPlayingState(
|
||||
renderer,
|
||||
ctx.game,
|
||||
ctx.pixelFont,
|
||||
ctx.lineEffect,
|
||||
ctx.blocksTex,
|
||||
ctx.asteroidsTex,
|
||||
ctx.statisticsPanelTex,
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
countdown,
|
||||
1200.0f,
|
||||
1000.0f,
|
||||
logicalScale,
|
||||
(float)winW,
|
||||
(float)winH,
|
||||
challengeClearFx,
|
||||
challengeClearOrder,
|
||||
challengeClearElapsed,
|
||||
challengeClearDuration,
|
||||
countdown ? nullptr : ctx.challengeStoryText,
|
||||
countdown ? 0.0f : (ctx.challengeStoryAlpha ? *ctx.challengeStoryAlpha : 0.0f)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
// Forward declarations for frequently used types
|
||||
class Game;
|
||||
class CoopGame;
|
||||
class ScoreManager;
|
||||
class Starfield;
|
||||
class Starfield3D;
|
||||
@ -24,6 +25,7 @@ class StateManager;
|
||||
struct StateContext {
|
||||
// Core subsystems (may be null if not available)
|
||||
Game* game = nullptr;
|
||||
CoopGame* coopGame = nullptr;
|
||||
ScoreManager* scores = nullptr;
|
||||
Starfield* starfield = nullptr;
|
||||
Starfield3D* starfield3D = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user