gitignore no ha deixat versionar cap fitxer de core
afegida gestió de ratolí
This commit is contained in:
163
source/core/graphics/starfield.cpp
Normal file
163
source/core/graphics/starfield.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
// starfield.cpp - Implementació del sistema d'estrelles de fons
|
||||
// © 2025 Orni Attack
|
||||
|
||||
#include "core/graphics/starfield.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/rendering/shape_renderer.hpp"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
// Constructor
|
||||
Starfield::Starfield(SDL_Renderer* renderer,
|
||||
const Punt& punt_fuga,
|
||||
const SDL_FRect& area,
|
||||
int densitat)
|
||||
: renderer_(renderer)
|
||||
, punt_fuga_(punt_fuga)
|
||||
, area_(area)
|
||||
, densitat_(densitat) {
|
||||
// Carregar forma d'estrella
|
||||
shape_estrella_ = std::make_shared<Shape>("data/shapes/star.shp");
|
||||
|
||||
if (!shape_estrella_->es_valida()) {
|
||||
std::cerr << "ERROR: No s'ha pogut carregar data/shapes/star.shp" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Configurar 3 capes amb diferents velocitats i escales
|
||||
// Capa 0: Fons llunyà (lenta, petita)
|
||||
capes_.push_back({20.0f, 0.3f, 0.8f, densitat / 3});
|
||||
|
||||
// Capa 1: Profunditat mitjana
|
||||
capes_.push_back({40.0f, 0.5f, 1.2f, densitat / 3});
|
||||
|
||||
// Capa 2: Primer pla (ràpida, gran)
|
||||
capes_.push_back({80.0f, 0.8f, 2.0f, densitat / 3});
|
||||
|
||||
// Calcular radi màxim (distància del centre al racó més llunyà)
|
||||
float dx = std::max(punt_fuga_.x, area_.w - punt_fuga_.x);
|
||||
float dy = std::max(punt_fuga_.y, area_.h - punt_fuga_.y);
|
||||
radi_max_ = std::sqrt(dx * dx + dy * dy);
|
||||
|
||||
// Inicialitzar estrelles amb posicions distribuïdes (pre-omplir pantalla)
|
||||
for (int capa_idx = 0; capa_idx < 3; capa_idx++) {
|
||||
int num = capes_[capa_idx].num_estrelles;
|
||||
for (int i = 0; i < num; i++) {
|
||||
Estrella estrella;
|
||||
estrella.capa = capa_idx;
|
||||
|
||||
// Angle aleatori
|
||||
estrella.angle = (static_cast<float>(rand()) / RAND_MAX) * 2.0f * Defaults::Math::PI;
|
||||
|
||||
// Distància aleatòria (0.0 a 1.0) per omplir tota la pantalla
|
||||
estrella.distancia_centre = static_cast<float>(rand()) / RAND_MAX;
|
||||
|
||||
// Calcular posició des de la distància
|
||||
float radi = estrella.distancia_centre * radi_max_;
|
||||
estrella.posicio.x = punt_fuga_.x + radi * std::cos(estrella.angle);
|
||||
estrella.posicio.y = punt_fuga_.y + radi * std::sin(estrella.angle);
|
||||
|
||||
estrelles_.push_back(estrella);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inicialitzar una estrella (nova o regenerada)
|
||||
void Starfield::inicialitzar_estrella(Estrella& estrella) {
|
||||
// Angle aleatori des del punt de fuga cap a fora
|
||||
estrella.angle = (static_cast<float>(rand()) / RAND_MAX) * 2.0f * Defaults::Math::PI;
|
||||
|
||||
// Distància inicial petita (5% del radi màxim) - neix prop del centre
|
||||
estrella.distancia_centre = 0.05f;
|
||||
|
||||
// Posició inicial: molt prop del punt de fuga
|
||||
float radi = estrella.distancia_centre * radi_max_;
|
||||
estrella.posicio.x = punt_fuga_.x + radi * std::cos(estrella.angle);
|
||||
estrella.posicio.y = punt_fuga_.y + radi * std::sin(estrella.angle);
|
||||
}
|
||||
|
||||
// Verificar si una estrella està fora de l'àrea
|
||||
bool Starfield::fora_area(const Estrella& estrella) const {
|
||||
return (estrella.posicio.x < area_.x ||
|
||||
estrella.posicio.x > area_.x + area_.w ||
|
||||
estrella.posicio.y < area_.y ||
|
||||
estrella.posicio.y > area_.y + area_.h);
|
||||
}
|
||||
|
||||
// Calcular escala dinàmica segons distància del centre
|
||||
float Starfield::calcular_escala(const Estrella& estrella) const {
|
||||
const CapaConfig& capa = capes_[estrella.capa];
|
||||
|
||||
// Interpolació lineal basada en distància del centre
|
||||
// distancia_centre: 0.0 (centre) → 1.0 (vora)
|
||||
return capa.escala_min +
|
||||
(capa.escala_max - capa.escala_min) * estrella.distancia_centre;
|
||||
}
|
||||
|
||||
// Calcular brightness dinàmica segons distància del centre
|
||||
float Starfield::calcular_brightness(const Estrella& estrella) const {
|
||||
// Interpolació lineal: estrelles properes (vora) més brillants
|
||||
// distancia_centre: 0.0 (centre, llunyanes) → 1.0 (vora, properes)
|
||||
return Defaults::Brightness::STARFIELD_MIN +
|
||||
(Defaults::Brightness::STARFIELD_MAX - Defaults::Brightness::STARFIELD_MIN) *
|
||||
estrella.distancia_centre;
|
||||
}
|
||||
|
||||
// Actualitzar posicions de les estrelles
|
||||
void Starfield::actualitzar(float delta_time) {
|
||||
for (auto& estrella : estrelles_) {
|
||||
// Obtenir configuració de la capa
|
||||
const CapaConfig& capa = capes_[estrella.capa];
|
||||
|
||||
// Moure cap a fora des del centre
|
||||
float velocitat = capa.velocitat_base;
|
||||
float dx = velocitat * std::cos(estrella.angle) * delta_time;
|
||||
float dy = velocitat * std::sin(estrella.angle) * delta_time;
|
||||
|
||||
estrella.posicio.x += dx;
|
||||
estrella.posicio.y += dy;
|
||||
|
||||
// Actualitzar distància del centre
|
||||
float dx_centre = estrella.posicio.x - punt_fuga_.x;
|
||||
float dy_centre = estrella.posicio.y - punt_fuga_.y;
|
||||
float dist_px = std::sqrt(dx_centre * dx_centre + dy_centre * dy_centre);
|
||||
estrella.distancia_centre = dist_px / radi_max_;
|
||||
|
||||
// Si ha sortit de l'àrea, regenerar-la
|
||||
if (fora_area(estrella)) {
|
||||
inicialitzar_estrella(estrella);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dibuixar totes les estrelles
|
||||
void Starfield::dibuixar() {
|
||||
if (!shape_estrella_->es_valida()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& estrella : estrelles_) {
|
||||
// Calcular escala i brightness dinàmicament
|
||||
float escala = calcular_escala(estrella);
|
||||
float brightness = calcular_brightness(estrella);
|
||||
|
||||
// Renderitzar estrella sense rotació
|
||||
Rendering::render_shape(
|
||||
renderer_,
|
||||
shape_estrella_,
|
||||
estrella.posicio,
|
||||
0.0f, // angle (les estrelles no giren)
|
||||
escala, // escala dinàmica
|
||||
true, // dibuixar
|
||||
1.0f, // progress (sempre visible)
|
||||
brightness // brightness dinàmica
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
Reference in New Issue
Block a user