feat(playfield): refactor a Playfield amb animació de creació durant l'INIT_HUD
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
// playfield.cpp - Implementació del fons del playfield
|
||||
// © 2026 JailDesigner
|
||||
|
||||
#include "core/graphics/playfield.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/rendering/line_renderer.hpp"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
Playfield::Playfield(Rendering::Renderer* renderer)
|
||||
: renderer_(renderer) {
|
||||
buildLines();
|
||||
total_slots_ = static_cast<int>(lines_.size());
|
||||
|
||||
// Distribuïm els spawns de manera que la última línia acabe just a TOTAL_ANIMATION_DURATION_S.
|
||||
// last_line_start = (N-1) * spawn_interval
|
||||
// last_line_end = last_line_start + LINE_GROWTH_DURATION_S = TOTAL_ANIMATION_DURATION_S
|
||||
if (total_slots_ > 1) {
|
||||
spawn_interval_s_ =
|
||||
(Defaults::Playfield::TOTAL_ANIMATION_DURATION_S - Defaults::Playfield::LINE_GROWTH_DURATION_S) / static_cast<float>(total_slots_ - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Playfield::update(float delta_time) {
|
||||
elapsed_s_ += delta_time;
|
||||
}
|
||||
|
||||
void Playfield::buildLines() {
|
||||
const SDL_FRect& zona = Defaults::Zones::PLAYAREA;
|
||||
const float CELL_W = zona.w / static_cast<float>(Defaults::Playfield::COLUMNS);
|
||||
const float CELL_H = zona.h / static_cast<float>(Defaults::Playfield::ROWS);
|
||||
const float SUB_W = CELL_W / static_cast<float>(Defaults::Playfield::SUBDIVISIONS);
|
||||
const float SUB_H = CELL_H / static_cast<float>(Defaults::Playfield::SUBDIVISIONS);
|
||||
const int SUB_VERTS = Defaults::Playfield::COLUMNS * Defaults::Playfield::SUBDIVISIONS;
|
||||
const int SUB_HORIZ = Defaults::Playfield::ROWS * Defaults::Playfield::SUBDIVISIONS;
|
||||
|
||||
std::vector<Line> verticals;
|
||||
std::vector<Line> horizontals;
|
||||
|
||||
// Verticals: posicions i ∈ [1, SUB_VERTS-1]. Si i % SUBDIVISIONS == 0 → línia
|
||||
// de la graella principal; si no, sub-graella.
|
||||
for (int i = 1; i < SUB_VERTS; i++) {
|
||||
const float X = zona.x + (static_cast<float>(i) * SUB_W);
|
||||
const bool IS_MAIN = (i % Defaults::Playfield::SUBDIVISIONS) == 0;
|
||||
const float BRIGHTNESS = IS_MAIN
|
||||
? Defaults::Playfield::GRID_BRIGHTNESS
|
||||
: Defaults::Playfield::SUBGRID_BRIGHTNESS;
|
||||
verticals.push_back(Line{
|
||||
.start = {.x = X, .y = zona.y},
|
||||
.end = {.x = X, .y = zona.y + zona.h},
|
||||
.brightness = BRIGHTNESS,
|
||||
.slot = 0});
|
||||
}
|
||||
|
||||
// Horitzontals: posicions j ∈ [1, SUB_HORIZ-1]. Mateix criteri main/sub.
|
||||
for (int j = 1; j < SUB_HORIZ; j++) {
|
||||
const float Y = zona.y + (static_cast<float>(j) * SUB_H);
|
||||
const bool IS_MAIN = (j % Defaults::Playfield::SUBDIVISIONS) == 0;
|
||||
const float BRIGHTNESS = IS_MAIN
|
||||
? Defaults::Playfield::GRID_BRIGHTNESS
|
||||
: Defaults::Playfield::SUBGRID_BRIGHTNESS;
|
||||
horizontals.push_back(Line{
|
||||
.start = {.x = zona.x, .y = Y},
|
||||
.end = {.x = zona.x + zona.w, .y = Y},
|
||||
.brightness = BRIGHTNESS,
|
||||
.slot = 0});
|
||||
}
|
||||
|
||||
// Verticals ja venen ordenats per x ascendent (loop sobre i). Assignem slots 0..N-1.
|
||||
// Horitzontals ja venen ordenats per y ascendent. Assignem slots N..total-1.
|
||||
lines_.clear();
|
||||
lines_.reserve(verticals.size() + horizontals.size());
|
||||
|
||||
int slot = 0;
|
||||
for (auto& line : verticals) {
|
||||
line.slot = slot++;
|
||||
lines_.push_back(line);
|
||||
}
|
||||
for (auto& line : horizontals) {
|
||||
line.slot = slot++;
|
||||
lines_.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
auto Playfield::computeLineProgress(int slot) const -> float {
|
||||
const float LINE_START = static_cast<float>(slot) * spawn_interval_s_;
|
||||
const float LINE_ELAPSED = elapsed_s_ - LINE_START;
|
||||
return std::clamp(LINE_ELAPSED / Defaults::Playfield::LINE_GROWTH_DURATION_S, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
void Playfield::draw() const {
|
||||
for (const auto& line : lines_) {
|
||||
const float P = computeLineProgress(line.slot);
|
||||
if (P <= 0.0F) {
|
||||
continue;
|
||||
}
|
||||
const float END_X = line.start.x + ((line.end.x - line.start.x) * P);
|
||||
const float END_Y = line.start.y + ((line.end.y - line.start.y) * P);
|
||||
Rendering::linea(
|
||||
renderer_,
|
||||
static_cast<int>(line.start.x),
|
||||
static_cast<int>(line.start.y),
|
||||
static_cast<int>(END_X),
|
||||
static_cast<int>(END_Y),
|
||||
line.brightness);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
Reference in New Issue
Block a user