add boss wave counter and countdown to the title bar
This commit is contained in:
@@ -295,7 +295,8 @@ The screen is divided into three vertical sections:
|
|||||||
+-----------------+-----------------+--------------+
|
+-----------------+-----------------+--------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
- REQ-UI-HEADER: The header bar spans the full width above the game world and always shows the elapsed survival time and the current global building blocks stock on the left, and game speed controls on the right.
|
- REQ-UI-HEADER: The header bar spans the full width above the game world and always shows the elapsed survival time and the current global building blocks stock on the left, the boss wave counter and boss countdown (REQ-UI-BOSS-STATUS) to the left of the speed buttons, and game speed controls on the right.
|
||||||
|
- REQ-UI-BOSS-STATUS: The header bar displays, to the left of the speed buttons, the current boss wave counter (REQ-WAV-BOSS-COUNTER) and the time remaining on the boss countdown (REQ-WAV-BOSS-COUNTDOWN). The boss wave counter is shown as `Boss Wave #<x>` and the countdown as `Next boss: <M:SS>`, where `<M:SS>` is the remaining seconds formatted as whole minutes and two-digit seconds. Both values update continuously as the simulation runs.
|
||||||
- REQ-UI-SPEED: The game speed controls in the header bar are buttons for 0×, 0.5×, 1×, 2×, and 4× speed. The currently active speed is shown as selected. All game simulation (production, movement, threat accumulation, wave timing) scales with the selected speed. 0× pauses the game.
|
- REQ-UI-SPEED: The game speed controls in the header bar are buttons for 0×, 0.5×, 1×, 2×, and 4× speed. The currently active speed is shown as selected. All game simulation (production, movement, threat accumulation, wave timing) scales with the selected speed. 0× pauses the game.
|
||||||
- REQ-UI-WORLD-HEIGHT: The game world view occupies 70% of the remaining screen height below the header bar.
|
- REQ-UI-WORLD-HEIGHT: The game world view occupies 70% of the remaining screen height below the header bar.
|
||||||
- REQ-UI-PANEL-HEIGHT: The UI panel occupies the remaining 30% of the screen height, split horizontally into a selected building panel (left), a build button grid (center), and a blueprint panel (right).
|
- REQ-UI-PANEL-HEIGHT: The UI panel occupies the remaining 30% of the screen height, split horizontally into a selected building panel (left), a build button grid (center), and a blueprint panel (right).
|
||||||
|
|||||||
@@ -532,6 +532,16 @@ double Simulation::threatLevel() const
|
|||||||
return m_waveSystem->threatLevel();
|
return m_waveSystem->threatLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Simulation::bossWaveCounter() const
|
||||||
|
{
|
||||||
|
return m_waveSystem->bossWaveCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tick Simulation::bossCountdownTicks() const
|
||||||
|
{
|
||||||
|
return m_waveSystem->bossCountdownTicks();
|
||||||
|
}
|
||||||
|
|
||||||
int Simulation::schematicLevel(const std::string& shipId) const
|
int Simulation::schematicLevel(const std::string& shipId) const
|
||||||
{
|
{
|
||||||
const std::map<std::string, SchematicState>::const_iterator it =
|
const std::map<std::string, SchematicState>::const_iterator it =
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ public:
|
|||||||
int buildingBlocksStock() const;
|
int buildingBlocksStock() const;
|
||||||
bool isGameOver() const;
|
bool isGameOver() const;
|
||||||
double threatLevel() const;
|
double threatLevel() const;
|
||||||
|
int bossWaveCounter() const;
|
||||||
|
Tick bossCountdownTicks() const;
|
||||||
|
|
||||||
// Schematic state queries.
|
// Schematic state queries.
|
||||||
int schematicLevel(const std::string& shipId) const;
|
int schematicLevel(const std::string& shipId) const;
|
||||||
|
|||||||
@@ -100,6 +100,16 @@ int WaveSystem::generation() const
|
|||||||
return m_generation;
|
return m_generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WaveSystem::bossWaveCounter() const
|
||||||
|
{
|
||||||
|
return m_bossWaveCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tick WaveSystem::bossCountdownTicks() const
|
||||||
|
{
|
||||||
|
return m_bossCountdownTicks;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Private helpers
|
// Private helpers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ public:
|
|||||||
// incremented by 1 after each push — REQ-PSH-STATION-STATS).
|
// incremented by 1 after each push — REQ-PSH-STATION-STATS).
|
||||||
int generation() const;
|
int generation() const;
|
||||||
|
|
||||||
|
// Boss wave counter (REQ-WAV-BOSS-COUNTER): current cycle number, starts at 1.
|
||||||
|
int bossWaveCounter() const;
|
||||||
|
|
||||||
|
// Ticks remaining until the next boss wave fires (REQ-WAV-BOSS-COUNTDOWN).
|
||||||
|
Tick bossCountdownTicks() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SpawnEntry
|
struct SpawnEntry
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -240,7 +240,9 @@ void GameWorldView::onFrame()
|
|||||||
// Emit state update for header bar / build grid
|
// Emit state update for header bar / build grid
|
||||||
emit stateUpdated(m_sim->currentTick(),
|
emit stateUpdated(m_sim->currentTick(),
|
||||||
m_sim->buildingBlocksStock(),
|
m_sim->buildingBlocksStock(),
|
||||||
m_gameSpeedMultiplier);
|
m_gameSpeedMultiplier,
|
||||||
|
m_sim->bossWaveCounter(),
|
||||||
|
m_sim->bossCountdownTicks());
|
||||||
|
|
||||||
// Game over check
|
// Game over check
|
||||||
if (m_sim->isGameOver() && !m_gameOverShown)
|
if (m_sim->isGameOver() && !m_gameOverShown)
|
||||||
@@ -1390,7 +1392,9 @@ void GameWorldView::setGameSpeed(double multiplier)
|
|||||||
m_gameSpeedMultiplier = multiplier;
|
m_gameSpeedMultiplier = multiplier;
|
||||||
emit stateUpdated(m_sim->currentTick(),
|
emit stateUpdated(m_sim->currentTick(),
|
||||||
m_sim->buildingBlocksStock(),
|
m_sim->buildingBlocksStock(),
|
||||||
m_gameSpeedMultiplier);
|
m_gameSpeedMultiplier,
|
||||||
|
m_sim->bossWaveCounter(),
|
||||||
|
m_sim->bossCountdownTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameWorldView::resetForNewGame()
|
void GameWorldView::resetForNewGame()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void selectionChanged(const std::vector<BuildingId>& ids);
|
void selectionChanged(const std::vector<BuildingId>& ids);
|
||||||
void stateUpdated(Tick tick, int blocks, double speed);
|
void stateUpdated(Tick tick, int blocks, double speed, int bossCounter, Tick bossCountdownTicks);
|
||||||
void gameOver();
|
void gameOver();
|
||||||
void builderModeExited();
|
void builderModeExited();
|
||||||
void blueprintModeExited();
|
void blueprintModeExited();
|
||||||
|
|||||||
@@ -22,9 +22,11 @@ HeaderBar::HeaderBar(QWidget* parent)
|
|||||||
|
|
||||||
m_timeLabel = new QLabel("00:00", this);
|
m_timeLabel = new QLabel("00:00", this);
|
||||||
m_blocksLabel = new QLabel("Blocks: 0", this);
|
m_blocksLabel = new QLabel("Blocks: 0", this);
|
||||||
|
m_bossLabel = new QLabel("Boss Wave #1 Next boss: 5:00", this);
|
||||||
layout->addWidget(m_timeLabel);
|
layout->addWidget(m_timeLabel);
|
||||||
layout->addWidget(m_blocksLabel);
|
layout->addWidget(m_blocksLabel);
|
||||||
layout->addStretch();
|
layout->addStretch();
|
||||||
|
layout->addWidget(m_bossLabel);
|
||||||
|
|
||||||
const char* labels[] = { "0x", "0.5x", "1x", "2x", "4x" };
|
const char* labels[] = { "0x", "0.5x", "1x", "2x", "4x" };
|
||||||
QSignalMapper* mapper = new QSignalMapper(this);
|
QSignalMapper* mapper = new QSignalMapper(this);
|
||||||
@@ -43,7 +45,8 @@ HeaderBar::HeaderBar(QWidget* parent)
|
|||||||
setFixedHeight(sizeHint().height());
|
setFixedHeight(sizeHint().height());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeaderBar::onStateUpdated(Tick tick, int buildingBlocks, double gameSpeed)
|
void HeaderBar::onStateUpdated(Tick tick, int buildingBlocks, double gameSpeed,
|
||||||
|
int bossCounter, Tick bossCountdownTicks)
|
||||||
{
|
{
|
||||||
const int totalSeconds = static_cast<int>(ticksToSeconds(tick));
|
const int totalSeconds = static_cast<int>(ticksToSeconds(tick));
|
||||||
const int minutes = totalSeconds / 60;
|
const int minutes = totalSeconds / 60;
|
||||||
@@ -56,6 +59,16 @@ void HeaderBar::onStateUpdated(Tick tick, int buildingBlocks, double gameSpeed)
|
|||||||
|
|
||||||
m_blocksLabel->setText(QString("Blocks: %1").arg(buildingBlocks));
|
m_blocksLabel->setText(QString("Blocks: %1").arg(buildingBlocks));
|
||||||
|
|
||||||
|
const int bossSeconds = static_cast<int>(ticksToSeconds(
|
||||||
|
bossCountdownTicks > 0 ? bossCountdownTicks : 0));
|
||||||
|
const int bossMin = bossSeconds / 60;
|
||||||
|
const int bossSec = bossSeconds % 60;
|
||||||
|
m_bossLabel->setText(
|
||||||
|
QString("Boss Wave #%1 Next boss: %2:%3")
|
||||||
|
.arg(bossCounter)
|
||||||
|
.arg(bossMin)
|
||||||
|
.arg(bossSec, 2, 10, QChar('0')));
|
||||||
|
|
||||||
for (int i = 0; i < kSpeedCount; ++i)
|
for (int i = 0; i < kSpeedCount; ++i)
|
||||||
{
|
{
|
||||||
const bool active = (std::abs(kSpeeds[i] - gameSpeed) < 0.001);
|
const bool active = (std::abs(kSpeeds[i] - gameSpeed) < 0.001);
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ public:
|
|||||||
explicit HeaderBar(QWidget* parent = nullptr);
|
explicit HeaderBar(QWidget* parent = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onStateUpdated(Tick tick, int buildingBlocks, double gameSpeed);
|
void onStateUpdated(Tick tick, int buildingBlocks, double gameSpeed,
|
||||||
|
int bossCounter, Tick bossCountdownTicks);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void speedChanged(double multiplier);
|
void speedChanged(double multiplier);
|
||||||
@@ -28,6 +29,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
QLabel* m_timeLabel;
|
QLabel* m_timeLabel;
|
||||||
QLabel* m_blocksLabel;
|
QLabel* m_blocksLabel;
|
||||||
|
QLabel* m_bossLabel;
|
||||||
std::vector<QPushButton*> m_speedButtons;
|
std::vector<QPushButton*> m_speedButtons;
|
||||||
|
|
||||||
static const double kSpeeds[];
|
static const double kSpeeds[];
|
||||||
|
|||||||
Reference in New Issue
Block a user