fixed cooperate play
This commit is contained in:
@ -38,6 +38,7 @@
|
||||
|
||||
#include "gameplay/core/Game.h"
|
||||
#include "gameplay/coop/CoopGame.h"
|
||||
#include "gameplay/coop/CoopAIController.h"
|
||||
#include "gameplay/effects/LineEffect.h"
|
||||
|
||||
#include "graphics/effects/SpaceWarp.h"
|
||||
@ -239,6 +240,11 @@ struct TetrisApp::Impl {
|
||||
bool suppressLineVoiceForLevelUp = false;
|
||||
bool skipNextLevelUpJingle = false;
|
||||
|
||||
// COOPERATE option: when true, right player is AI-controlled.
|
||||
bool coopVsAI = false;
|
||||
|
||||
CoopAIController coopAI;
|
||||
|
||||
AppState state = AppState::Loading;
|
||||
double loadingProgress = 0.0;
|
||||
Uint64 loadStart = 0;
|
||||
@ -567,6 +573,7 @@ int TetrisApp::Impl::init()
|
||||
ctx.mainScreenW = mainScreenW;
|
||||
ctx.mainScreenH = mainScreenH;
|
||||
ctx.musicEnabled = &musicEnabled;
|
||||
ctx.coopVsAI = &coopVsAI;
|
||||
ctx.startLevelSelection = &startLevelSelection;
|
||||
ctx.hoveredButton = &hoveredButton;
|
||||
ctx.showSettingsPopup = &showSettingsPopup;
|
||||
@ -628,10 +635,17 @@ int TetrisApp::Impl::init()
|
||||
return;
|
||||
}
|
||||
if (state != AppState::Menu) {
|
||||
if (game && game->getMode() == GameMode::Cooperate && coopGame && coopVsAI) {
|
||||
coopAI.reset();
|
||||
}
|
||||
state = AppState::Playing;
|
||||
ctx.stateManager->setState(state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (game && game->getMode() == GameMode::Cooperate && coopGame && coopVsAI) {
|
||||
coopAI.reset();
|
||||
}
|
||||
beginStateFade(AppState::Playing, true);
|
||||
};
|
||||
ctx.startPlayTransition = startMenuPlayTransition;
|
||||
@ -894,27 +908,45 @@ void TetrisApp::Impl::runLoop()
|
||||
if (!showHelpOverlay && state == AppState::GameOver && e.type == SDL_EVENT_KEY_DOWN && !e.key.repeat) {
|
||||
if (isNewHighScore) {
|
||||
if (game && game->getMode() == GameMode::Cooperate && coopGame) {
|
||||
// Two-name entry flow
|
||||
if (e.key.scancode == SDL_SCANCODE_BACKSPACE) {
|
||||
if (highScoreEntryIndex == 0 && !playerName.empty()) playerName.pop_back();
|
||||
else if (highScoreEntryIndex == 1 && !player2Name.empty()) player2Name.pop_back();
|
||||
} else if (e.key.scancode == SDL_SCANCODE_RETURN || e.key.scancode == SDL_SCANCODE_KP_ENTER) {
|
||||
if (highScoreEntryIndex == 0) {
|
||||
if (playerName.empty()) playerName = "P1";
|
||||
highScoreEntryIndex = 1; // move to second name
|
||||
} else {
|
||||
if (coopVsAI) {
|
||||
// One-name entry flow (CPU is LEFT, human enters RIGHT name)
|
||||
if (e.key.scancode == SDL_SCANCODE_BACKSPACE) {
|
||||
if (!player2Name.empty()) player2Name.pop_back();
|
||||
} else if (e.key.scancode == SDL_SCANCODE_RETURN || e.key.scancode == SDL_SCANCODE_KP_ENTER) {
|
||||
if (player2Name.empty()) player2Name = "P2";
|
||||
// Submit combined name
|
||||
std::string combined = playerName + " & " + player2Name;
|
||||
std::string combined = std::string("CPU") + " & " + player2Name;
|
||||
int leftScore = coopGame->score(CoopGame::PlayerSide::Left);
|
||||
int rightScore = coopGame->score(CoopGame::PlayerSide::Right);
|
||||
int combinedScore = leftScore + rightScore;
|
||||
ensureScoresLoaded();
|
||||
scores.submit(combinedScore, coopGame->lines(), coopGame->level(), coopGame->elapsed(), combined, "cooperate");
|
||||
Settings::instance().setPlayerName(playerName);
|
||||
Settings::instance().setPlayerName(player2Name);
|
||||
isNewHighScore = false;
|
||||
SDL_StopTextInput(window);
|
||||
}
|
||||
} else {
|
||||
// Two-name entry flow
|
||||
if (e.key.scancode == SDL_SCANCODE_BACKSPACE) {
|
||||
if (highScoreEntryIndex == 0 && !playerName.empty()) playerName.pop_back();
|
||||
else if (highScoreEntryIndex == 1 && !player2Name.empty()) player2Name.pop_back();
|
||||
} else if (e.key.scancode == SDL_SCANCODE_RETURN || e.key.scancode == SDL_SCANCODE_KP_ENTER) {
|
||||
if (highScoreEntryIndex == 0) {
|
||||
if (playerName.empty()) playerName = "P1";
|
||||
highScoreEntryIndex = 1; // move to second name
|
||||
} else {
|
||||
if (player2Name.empty()) player2Name = "P2";
|
||||
// Submit combined name
|
||||
std::string combined = playerName + " & " + player2Name;
|
||||
int leftScore = coopGame->score(CoopGame::PlayerSide::Left);
|
||||
int rightScore = coopGame->score(CoopGame::PlayerSide::Right);
|
||||
int combinedScore = leftScore + rightScore;
|
||||
ensureScoresLoaded();
|
||||
scores.submit(combinedScore, coopGame->lines(), coopGame->level(), coopGame->elapsed(), combined, "cooperate");
|
||||
Settings::instance().setPlayerName(playerName);
|
||||
isNewHighScore = false;
|
||||
SDL_StopTextInput(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (e.key.scancode == SDL_SCANCODE_BACKSPACE && !playerName.empty()) {
|
||||
@ -972,11 +1004,9 @@ void TetrisApp::Impl::runLoop()
|
||||
startMenuPlayTransition();
|
||||
break;
|
||||
case ui::BottomMenuItem::Cooperate:
|
||||
if (game) {
|
||||
game->setMode(GameMode::Cooperate);
|
||||
game->reset(startLevelSelection);
|
||||
if (menuState) {
|
||||
menuState->showCoopSetupPanel(true);
|
||||
}
|
||||
startMenuPlayTransition();
|
||||
break;
|
||||
case ui::BottomMenuItem::Challenge:
|
||||
if (game) {
|
||||
@ -1288,13 +1318,44 @@ void TetrisApp::Impl::runLoop()
|
||||
p2LeftHeld = false;
|
||||
p2RightHeld = false;
|
||||
} else {
|
||||
handleSide(CoopGame::PlayerSide::Left, p1LeftHeld, p1RightHeld, p1MoveTimerMs, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_S);
|
||||
handleSide(CoopGame::PlayerSide::Right, p2LeftHeld, p2RightHeld, p2MoveTimerMs, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_DOWN);
|
||||
// Define canonical key mappings for left and right players
|
||||
const SDL_Scancode leftLeftKey = SDL_SCANCODE_A;
|
||||
const SDL_Scancode leftRightKey = SDL_SCANCODE_D;
|
||||
const SDL_Scancode leftDownKey = SDL_SCANCODE_S;
|
||||
|
||||
p1LeftHeld = ks[SDL_SCANCODE_A];
|
||||
p1RightHeld = ks[SDL_SCANCODE_D];
|
||||
p2LeftHeld = ks[SDL_SCANCODE_LEFT];
|
||||
p2RightHeld = ks[SDL_SCANCODE_RIGHT];
|
||||
const SDL_Scancode rightLeftKey = SDL_SCANCODE_LEFT;
|
||||
const SDL_Scancode rightRightKey = SDL_SCANCODE_RIGHT;
|
||||
const SDL_Scancode rightDownKey = SDL_SCANCODE_DOWN;
|
||||
|
||||
if (!coopVsAI) {
|
||||
// Standard two-player: left uses WASD, right uses arrow keys
|
||||
handleSide(CoopGame::PlayerSide::Left, p1LeftHeld, p1RightHeld, p1MoveTimerMs, leftLeftKey, leftRightKey, leftDownKey);
|
||||
handleSide(CoopGame::PlayerSide::Right, p2LeftHeld, p2RightHeld, p2MoveTimerMs, rightLeftKey, rightRightKey, rightDownKey);
|
||||
|
||||
p1LeftHeld = ks[leftLeftKey];
|
||||
p1RightHeld = ks[leftRightKey];
|
||||
p2LeftHeld = ks[rightLeftKey];
|
||||
p2RightHeld = ks[rightRightKey];
|
||||
} else {
|
||||
// Coop vs CPU: AI controls LEFT, human controls RIGHT (arrow keys).
|
||||
// Handle continuous input for the human on the right side.
|
||||
handleSide(CoopGame::PlayerSide::Right, p2LeftHeld, p2RightHeld, p2MoveTimerMs, rightLeftKey, rightRightKey, rightDownKey);
|
||||
|
||||
// Mirror the human soft-drop to the AI-controlled left board so both fall together.
|
||||
const bool pRightSoftDrop = ks[rightDownKey];
|
||||
coopGame->setSoftDropping(CoopGame::PlayerSide::Left, pRightSoftDrop);
|
||||
|
||||
// Reset left continuous timers/held flags (AI handles movement)
|
||||
p1MoveTimerMs = 0.0;
|
||||
p1LeftHeld = false;
|
||||
p1RightHeld = false;
|
||||
|
||||
// Update AI for the left side
|
||||
coopAI.update(*coopGame, CoopGame::PlayerSide::Left, frameMs);
|
||||
// Update human-held flags for right-side controls so DAS/ARR state is tracked
|
||||
p2LeftHeld = ks[rightLeftKey];
|
||||
p2RightHeld = ks[rightRightKey];
|
||||
}
|
||||
|
||||
coopGame->tickGravity(frameMs);
|
||||
coopGame->updateVisualEffects(frameMs);
|
||||
@ -1307,14 +1368,22 @@ void TetrisApp::Impl::runLoop()
|
||||
int combinedScore = leftScore + rightScore;
|
||||
if (combinedScore > 0) {
|
||||
isNewHighScore = true;
|
||||
playerName.clear();
|
||||
player2Name.clear();
|
||||
highScoreEntryIndex = 0;
|
||||
if (coopVsAI) {
|
||||
// AI is left, prompt human (right) for name
|
||||
playerName = "CPU";
|
||||
player2Name.clear();
|
||||
highScoreEntryIndex = 1; // enter P2 (human)
|
||||
} else {
|
||||
playerName.clear();
|
||||
player2Name.clear();
|
||||
highScoreEntryIndex = 0;
|
||||
}
|
||||
SDL_StartTextInput(window);
|
||||
} else {
|
||||
isNewHighScore = false;
|
||||
ensureScoresLoaded();
|
||||
scores.submit(combinedScore, coopGame->lines(), coopGame->level(), coopGame->elapsed(), "P1 & P2", "cooperate");
|
||||
// When AI is present, label should indicate CPU left and human right
|
||||
scores.submit(combinedScore, coopGame->lines(), coopGame->level(), coopGame->elapsed(), coopVsAI ? "CPU & P2" : "P1 & P2", "cooperate");
|
||||
}
|
||||
state = AppState::GameOver;
|
||||
stateMgr->setState(state);
|
||||
|
||||
Reference in New Issue
Block a user