removed s shortcut for sound fx toggle
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
Fullscreen=1
|
||||
|
||||
[Audio]
|
||||
Music=1
|
||||
Music=0
|
||||
Sound=1
|
||||
|
||||
[Gameplay]
|
||||
|
||||
@ -775,7 +775,8 @@ void TetrisApp::Impl::runLoop()
|
||||
Settings::instance().setMusicEnabled(true);
|
||||
}
|
||||
}
|
||||
if (e.key.scancode == SDL_SCANCODE_S)
|
||||
// K: Toggle sound effects (S is reserved for co-op movement)
|
||||
if (e.key.scancode == SDL_SCANCODE_K)
|
||||
{
|
||||
SoundEffectManager::instance().setEnabled(!SoundEffectManager::instance().isEnabled());
|
||||
Settings::instance().setSoundEnabled(SoundEffectManager::instance().isEnabled());
|
||||
|
||||
@ -932,8 +932,8 @@ void ApplicationManager::setupStateHandlers() {
|
||||
m_showExitConfirmPopup = true;
|
||||
return;
|
||||
}
|
||||
// S: toggle SFX enable state (music handled globally)
|
||||
if (event.key.scancode == SDL_SCANCODE_S) {
|
||||
// K: toggle SFX enable state (music handled globally)
|
||||
if (event.key.scancode == SDL_SCANCODE_K) {
|
||||
SoundEffectManager::instance().setEnabled(!SoundEffectManager::instance().isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1841,6 +1841,7 @@ void GameRenderer::renderCoopPlayingState(
|
||||
SDL_Texture* scorePanelTex,
|
||||
SDL_Texture* nextPanelTex,
|
||||
SDL_Texture* holdPanelTex,
|
||||
bool paused,
|
||||
float logicalW,
|
||||
float logicalH,
|
||||
float logicalScale,
|
||||
@ -1962,6 +1963,229 @@ void GameRenderer::renderCoopPlayingState(
|
||||
SDL_RenderLine(renderer, gridX, lineY, gridX + GRID_W, lineY);
|
||||
}
|
||||
|
||||
// In-grid 3D starfield + ambient sparkles (match classic feel, per-half)
|
||||
{
|
||||
static Uint32 s_lastCoopSparkTick = SDL_GetTicks();
|
||||
static std::mt19937 s_coopSparkRng{ std::random_device{}() };
|
||||
static std::vector<Sparkle> s_leftSparkles;
|
||||
static std::vector<Sparkle> s_rightSparkles;
|
||||
static std::vector<ImpactSpark> s_leftImpactSparks;
|
||||
static std::vector<ImpactSpark> s_rightImpactSparks;
|
||||
static float s_leftSparkleSpawnAcc = 0.0f;
|
||||
static float s_rightSparkleSpawnAcc = 0.0f;
|
||||
|
||||
float halfW = GRID_W * 0.5f;
|
||||
const float leftGridX = gridX;
|
||||
const float rightGridX = gridX + halfW;
|
||||
|
||||
Uint32 sparkNow = nowTicks;
|
||||
float sparkDeltaMs = static_cast<float>(sparkNow - s_lastCoopSparkTick);
|
||||
s_lastCoopSparkTick = sparkNow;
|
||||
if (sparkDeltaMs < 0.0f || sparkDeltaMs > 100.0f) {
|
||||
sparkDeltaMs = 16.0f;
|
||||
}
|
||||
|
||||
if (!s_starfieldInitialized) {
|
||||
s_inGridStarfield.init(static_cast<int>(halfW), static_cast<int>(GRID_H), 180);
|
||||
s_starfieldInitialized = true;
|
||||
} else {
|
||||
s_inGridStarfield.resize(static_cast<int>(halfW), static_cast<int>(GRID_H));
|
||||
}
|
||||
|
||||
const float deltaSeconds = std::clamp(sparkDeltaMs / 1000.0f, 0.0f, 0.033f);
|
||||
s_inGridStarfield.update(deltaSeconds);
|
||||
|
||||
struct MagnetInfo { bool active{false}; float x{0.0f}; float y{0.0f}; };
|
||||
auto computeMagnet = [&](CoopGame::PlayerSide side) -> MagnetInfo {
|
||||
MagnetInfo info{};
|
||||
const CoopGame::Piece& activePiece = game->current(side);
|
||||
const int pieceType = static_cast<int>(activePiece.type);
|
||||
if (pieceType < 0 || pieceType >= PIECE_COUNT) {
|
||||
return info;
|
||||
}
|
||||
|
||||
float sumLocalX = 0.0f;
|
||||
float sumLocalY = 0.0f;
|
||||
int filledCells = 0;
|
||||
const int localXOffsetCols = (side == CoopGame::PlayerSide::Right) ? 10 : 0;
|
||||
for (int cy = 0; cy < 4; ++cy) {
|
||||
for (int cx = 0; cx < 4; ++cx) {
|
||||
if (!CoopGame::cellFilled(activePiece, cx, cy)) continue;
|
||||
sumLocalX += ((activePiece.x - localXOffsetCols) + cx + 0.5f) * finalBlockSize;
|
||||
sumLocalY += (activePiece.y + cy + 0.5f) * finalBlockSize;
|
||||
++filledCells;
|
||||
}
|
||||
}
|
||||
if (filledCells <= 0) {
|
||||
return info;
|
||||
}
|
||||
|
||||
info.active = true;
|
||||
info.x = std::clamp(sumLocalX / static_cast<float>(filledCells), 0.0f, halfW);
|
||||
info.y = std::clamp(sumLocalY / static_cast<float>(filledCells), 0.0f, GRID_H);
|
||||
return info;
|
||||
};
|
||||
|
||||
const MagnetInfo leftMagnet = computeMagnet(CoopGame::PlayerSide::Left);
|
||||
const MagnetInfo rightMagnet = computeMagnet(CoopGame::PlayerSide::Right);
|
||||
|
||||
SDL_BlendMode oldBlend = SDL_BLENDMODE_NONE;
|
||||
SDL_GetRenderDrawBlendMode(renderer, &oldBlend);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
auto drawStarfieldHalf = [&](float originX, const MagnetInfo& magnet) {
|
||||
if (magnet.active) {
|
||||
const float magnetStrength = finalBlockSize * 2.2f;
|
||||
s_inGridStarfield.setMagnetTarget(magnet.x, magnet.y, magnetStrength);
|
||||
} else {
|
||||
s_inGridStarfield.clearMagnetTarget();
|
||||
}
|
||||
|
||||
const float jitterAmp = 1.6f;
|
||||
const float tms = static_cast<float>(sparkNow) * 0.001f;
|
||||
const float jitterX = std::sin(tms * 1.7f) * jitterAmp + std::cos(tms * 0.9f) * 0.4f;
|
||||
const float jitterY = std::sin(tms * 1.1f + 3.7f) * (jitterAmp * 0.6f);
|
||||
s_inGridStarfield.draw(renderer, originX + jitterX, gridY + jitterY, 0.22f, true);
|
||||
};
|
||||
|
||||
drawStarfieldHalf(leftGridX, leftMagnet);
|
||||
drawStarfieldHalf(rightGridX, rightMagnet);
|
||||
|
||||
auto updateAndDrawSparkleLayer = [&](std::vector<Sparkle>& sparkles,
|
||||
std::vector<ImpactSpark>& impactSparks,
|
||||
float& spawnAcc,
|
||||
const MagnetInfo& magnet,
|
||||
float originX) {
|
||||
if (!paused) {
|
||||
const float spawnInterval = 0.08f;
|
||||
spawnAcc += deltaSeconds;
|
||||
while (spawnAcc >= spawnInterval) {
|
||||
spawnAcc -= spawnInterval;
|
||||
|
||||
Sparkle s;
|
||||
bool spawnNearPiece = magnet.active && (std::uniform_real_distribution<float>(0.0f, 1.0f)(s_coopSparkRng) > 0.35f);
|
||||
|
||||
float sx = 0.0f;
|
||||
float sy = 0.0f;
|
||||
if (spawnNearPiece) {
|
||||
float jitterX = std::uniform_real_distribution<float>(-finalBlockSize * 1.2f, finalBlockSize * 1.2f)(s_coopSparkRng);
|
||||
float jitterY = std::uniform_real_distribution<float>(-finalBlockSize * 1.2f, finalBlockSize * 1.2f)(s_coopSparkRng);
|
||||
sx = std::clamp(magnet.x + jitterX, -finalBlockSize * 2.0f, halfW + finalBlockSize * 2.0f);
|
||||
sy = std::clamp(magnet.y + jitterY, -finalBlockSize * 2.0f, GRID_H + finalBlockSize * 2.0f);
|
||||
} else {
|
||||
float side = std::uniform_real_distribution<float>(0.0f, 1.0f)(s_coopSparkRng);
|
||||
const float borderBand = std::max(12.0f, finalBlockSize * 1.0f);
|
||||
if (side < 0.2f) {
|
||||
sx = std::uniform_real_distribution<float>(-borderBand, 0.0f)(s_coopSparkRng);
|
||||
sy = std::uniform_real_distribution<float>(-borderBand, GRID_H + borderBand)(s_coopSparkRng);
|
||||
} else if (side < 0.4f) {
|
||||
sx = std::uniform_real_distribution<float>(halfW, halfW + borderBand)(s_coopSparkRng);
|
||||
sy = std::uniform_real_distribution<float>(-borderBand, GRID_H + borderBand)(s_coopSparkRng);
|
||||
} else if (side < 0.6f) {
|
||||
sx = std::uniform_real_distribution<float>(-borderBand, halfW + borderBand)(s_coopSparkRng);
|
||||
sy = std::uniform_real_distribution<float>(-borderBand, 0.0f)(s_coopSparkRng);
|
||||
} else if (side < 0.9f) {
|
||||
sx = std::uniform_real_distribution<float>(0.0f, halfW)(s_coopSparkRng);
|
||||
sy = std::uniform_real_distribution<float>(0.0f, finalBlockSize * 2.0f)(s_coopSparkRng);
|
||||
} else {
|
||||
sx = std::uniform_real_distribution<float>(-borderBand, halfW + borderBand)(s_coopSparkRng);
|
||||
sy = std::uniform_real_distribution<float>(GRID_H, GRID_H + borderBand)(s_coopSparkRng);
|
||||
}
|
||||
}
|
||||
|
||||
s.x = sx;
|
||||
s.y = sy;
|
||||
float speed = std::uniform_real_distribution<float>(10.0f, 60.0f)(s_coopSparkRng);
|
||||
float ang = std::uniform_real_distribution<float>(-3.14159f, 3.14159f)(s_coopSparkRng);
|
||||
s.vx = std::cos(ang) * speed;
|
||||
s.vy = std::sin(ang) * speed * 0.25f;
|
||||
s.maxLifeMs = std::uniform_real_distribution<float>(350.0f, 900.0f)(s_coopSparkRng);
|
||||
s.lifeMs = s.maxLifeMs;
|
||||
s.size = std::uniform_real_distribution<float>(1.5f, 5.0f)(s_coopSparkRng);
|
||||
if (std::uniform_real_distribution<float>(0.0f, 1.0f)(s_coopSparkRng) < 0.5f) {
|
||||
s.color = SDL_Color{255, 230, 180, 255};
|
||||
} else {
|
||||
s.color = SDL_Color{180, 220, 255, 255};
|
||||
}
|
||||
s.pulse = std::uniform_real_distribution<float>(0.0f, 6.28f)(s_coopSparkRng);
|
||||
sparkles.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sparkles.empty()) {
|
||||
auto it = sparkles.begin();
|
||||
while (it != sparkles.end()) {
|
||||
Sparkle& sp = *it;
|
||||
sp.lifeMs -= sparkDeltaMs;
|
||||
if (sp.lifeMs <= 0.0f) {
|
||||
const int burstCount = std::uniform_int_distribution<int>(4, 8)(s_coopSparkRng);
|
||||
for (int bi = 0; bi < burstCount; ++bi) {
|
||||
ImpactSpark ps;
|
||||
ps.x = originX + sp.x + std::uniform_real_distribution<float>(-2.0f, 2.0f)(s_coopSparkRng);
|
||||
ps.y = gridY + sp.y + std::uniform_real_distribution<float>(-2.0f, 2.0f)(s_coopSparkRng);
|
||||
float ang = std::uniform_real_distribution<float>(0.0f, 6.2831853f)(s_coopSparkRng);
|
||||
float speed = std::uniform_real_distribution<float>(10.0f, 120.0f)(s_coopSparkRng);
|
||||
ps.vx = std::cos(ang) * speed;
|
||||
ps.vy = std::sin(ang) * speed * 0.8f;
|
||||
ps.maxLifeMs = std::uniform_real_distribution<float>(220.0f, 500.0f)(s_coopSparkRng);
|
||||
ps.lifeMs = ps.maxLifeMs;
|
||||
ps.size = std::max(1.0f, sp.size * 0.5f);
|
||||
ps.color = sp.color;
|
||||
impactSparks.push_back(ps);
|
||||
}
|
||||
it = sparkles.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
float lifeRatio = sp.lifeMs / sp.maxLifeMs;
|
||||
sp.x += sp.vx * deltaSeconds;
|
||||
sp.y += sp.vy * deltaSeconds;
|
||||
sp.vy *= 0.995f;
|
||||
sp.pulse += deltaSeconds * 8.0f;
|
||||
|
||||
float pulse = 0.5f + 0.5f * std::sin(sp.pulse);
|
||||
Uint8 alpha = static_cast<Uint8>(std::clamp(lifeRatio * pulse, 0.0f, 1.0f) * 255.0f);
|
||||
SDL_SetRenderDrawColor(renderer, sp.color.r, sp.color.g, sp.color.b, alpha);
|
||||
float half = sp.size * 0.5f;
|
||||
SDL_FRect fr{ originX + sp.x - half, gridY + sp.y - half, sp.size, sp.size };
|
||||
SDL_RenderFillRect(renderer, &fr);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (!impactSparks.empty()) {
|
||||
auto it = impactSparks.begin();
|
||||
while (it != impactSparks.end()) {
|
||||
ImpactSpark& spark = *it;
|
||||
spark.vy += 0.00045f * sparkDeltaMs;
|
||||
spark.x += spark.vx * sparkDeltaMs;
|
||||
spark.y += spark.vy * sparkDeltaMs;
|
||||
spark.lifeMs -= sparkDeltaMs;
|
||||
if (spark.lifeMs <= 0.0f) {
|
||||
it = impactSparks.erase(it);
|
||||
continue;
|
||||
}
|
||||
float lifeRatio = spark.lifeMs / spark.maxLifeMs;
|
||||
Uint8 alpha = static_cast<Uint8>(std::clamp(lifeRatio, 0.0f, 1.0f) * 160.0f);
|
||||
SDL_SetRenderDrawColor(renderer, spark.color.r, spark.color.g, spark.color.b, alpha);
|
||||
SDL_FRect sparkRect{
|
||||
spark.x - spark.size * 0.5f,
|
||||
spark.y - spark.size * 0.5f,
|
||||
spark.size,
|
||||
spark.size * 1.4f
|
||||
};
|
||||
SDL_RenderFillRect(renderer, &sparkRect);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateAndDrawSparkleLayer(s_leftSparkles, s_leftImpactSparks, s_leftSparkleSpawnAcc, leftMagnet, leftGridX);
|
||||
updateAndDrawSparkleLayer(s_rightSparkles, s_rightImpactSparks, s_rightSparkleSpawnAcc, rightMagnet, rightGridX);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, oldBlend);
|
||||
}
|
||||
|
||||
// Half-row feedback: lightly tint rows where one side is filled, brighter where both are pending clear
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
const auto& rowStates = game->rowHalfStates();
|
||||
|
||||
@ -72,6 +72,7 @@ public:
|
||||
SDL_Texture* scorePanelTex,
|
||||
SDL_Texture* nextPanelTex,
|
||||
SDL_Texture* holdPanelTex,
|
||||
bool paused,
|
||||
float logicalW,
|
||||
float logicalH,
|
||||
float logicalScale,
|
||||
|
||||
@ -232,6 +232,6 @@ void UIRenderer::drawSettingsPopup(SDL_Renderer* renderer, FontAtlas* font, floa
|
||||
|
||||
// Instructions
|
||||
font->draw(renderer, popupX + 20, popupY + 150, "M = TOGGLE MUSIC", 1.0f, {200, 200, 220, 255});
|
||||
font->draw(renderer, popupX + 20, popupY + 170, "S = TOGGLE SOUND FX", 1.0f, {200, 200, 220, 255});
|
||||
font->draw(renderer, popupX + 20, popupY + 170, "K = TOGGLE SOUND FX", 1.0f, {200, 200, 220, 255});
|
||||
font->draw(renderer, popupX + 20, popupY + 190, "ESC = CLOSE", 1.0f, {200, 200, 220, 255});
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ void Render(SDL_Renderer* renderer, FontAtlas& font, float logicalWidth, float l
|
||||
{"ESC", "Back / cancel current popup"},
|
||||
{"F11 or ALT+ENTER", "Toggle fullscreen"},
|
||||
{"M", "Mute or unmute music"},
|
||||
{"S", "Toggle sound effects"}
|
||||
{"K", "Toggle sound effects"}
|
||||
}};
|
||||
|
||||
const std::array<ShortcutEntry, 2> menuShortcuts{{
|
||||
|
||||
@ -1248,7 +1248,7 @@ void MenuState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logi
|
||||
{"ESC", "Back / cancel current popup"},
|
||||
{"F11 or ALT+ENTER", "Toggle fullscreen"},
|
||||
{"M", "Mute or unmute music"},
|
||||
{"S", "Toggle sound effects"}
|
||||
{"K", "Toggle sound effects"}
|
||||
};
|
||||
const ShortcutEntry menuShortcuts[] = {
|
||||
{"ARROW KEYS", "Navigate menu buttons"},
|
||||
|
||||
@ -322,6 +322,7 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
paused,
|
||||
1200.0f,
|
||||
1000.0f,
|
||||
logicalScale,
|
||||
@ -438,6 +439,7 @@ void PlayingState::render(SDL_Renderer* renderer, float logicalScale, SDL_Rect l
|
||||
ctx.scorePanelTex,
|
||||
ctx.nextPanelTex,
|
||||
ctx.holdPanelTex,
|
||||
paused,
|
||||
1200.0f,
|
||||
1000.0f,
|
||||
logicalScale,
|
||||
|
||||
@ -83,6 +83,6 @@ void menu_drawSettingsPopup(SDL_Renderer* renderer, FontAtlas& font, bool musicE
|
||||
bool sfxOn = true;
|
||||
font.draw(renderer, popupX + 140, popupY + 100, sfxOn ? "ON" : "OFF", 1.5f, sfxOn ? SDL_Color{0,255,0,255} : SDL_Color{255,0,0,255});
|
||||
font.draw(renderer, popupX + 20, popupY + 150, "M = TOGGLE MUSIC", 1.0f, SDL_Color{200,200,220,255});
|
||||
font.draw(renderer, popupX + 20, popupY + 170, "S = TOGGLE SOUND FX", 1.0f, SDL_Color{200,200,220,255});
|
||||
font.draw(renderer, popupX + 20, popupY + 170, "K = TOGGLE SOUND FX", 1.0f, SDL_Color{200,200,220,255});
|
||||
font.draw(renderer, popupX + 20, popupY + 190, "ESC = CLOSE", 1.0f, SDL_Color{200,200,220,255});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user