Lint: rename públicos al inglés + refactor cognitive-complexity + unused-includes
Identifier-naming: rename de métodos públicos y cross-file al inglés
(camelBack), traducción de campos y locales en el proceso (TitleShip,
StageManager, SpawnController, ShipAnimator, helpers de PlayArea, etc.).
Refactor por cognitive-complexity (>25): GameScene::draw (59→3) con 9
helpers de estado, PhysicsWorld::resolveBodyCollisions (35→5) extrayendo
resolveBodyPair, Options::load{Window,Physics,Audio}ConfigFromYaml
(32/49/57→5/2/3) con templates readField, TitleScene::update (68→4) con
5 sub-pasos por estado + handleSkipInput/handleStartInput +
triggerExitForJoinedPlayers, DebrisManager::explode (39→3) con
extractSegments/spawnDebris/applyAngularVelocity/applyVisualRotation.
use-anyofallof: bucles → std::ranges::any_of/all_of en Input,
ShipAnimator y SpawnController.
readability-static-accessed-through-instance: Director::run y
VectorText::getTextWidth/Height invocados por clase.
readability-convert-member-functions-to-static: ResourcePack::decryptData.
unused-includes: eliminación de <utility>, <cstdint>, <vector>,
<iostream>, defaults.hpp y otros no usados directamente en headers y
unidades de traducción. Restablecido core/defaults.hpp en title_scene.cpp
(falsa "unused" del header).
Bug fix: eliminado isActive() duplicado en Bullet (redeclaración tras
rename de esta_activa→isActive que chocaba con el override de Entity).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -62,147 +62,150 @@ void DebrisManager::explode(const std::shared_ptr<Graphics::Shape>& shape,
|
||||
// Reproducir sonido de explosión
|
||||
Audio::get()->playSound(sound, Audio::Group::GAME);
|
||||
|
||||
// Obtenir centro de la shape para transformacions
|
||||
const Vec2& shape_centre = shape->getCenter();
|
||||
|
||||
// Iterar sobre todas las primitives de la shape
|
||||
for (const auto& primitive : shape->get_primitives()) {
|
||||
// Processar cada segment de línia
|
||||
std::vector<std::pair<Vec2, Vec2>> segments;
|
||||
for (const auto& primitive : shape->getPrimitives()) {
|
||||
for (const auto& [local_p1, local_p2] : extractSegments(primitive)) {
|
||||
// Transformar points locals → coordenades mundials
|
||||
Vec2 world_p1 = transformPoint(local_p1, shape_centre, centro, angle, scale);
|
||||
Vec2 world_p2 = transformPoint(local_p2, shape_centre, centro, angle, scale);
|
||||
|
||||
if (primitive.type == Graphics::PrimitiveType::POLYLINE) {
|
||||
// Polyline: extreure segments consecutius
|
||||
for (size_t i = 0; i < primitive.points.size() - 1; i++) {
|
||||
segments.emplace_back(primitive.points[i], primitive.points[i + 1]);
|
||||
}
|
||||
} else { // PrimitiveType::LINE
|
||||
// Line: un únic segment
|
||||
if (primitive.points.size() >= 2) {
|
||||
segments.emplace_back(primitive.points[0], primitive.points[1]);
|
||||
// Si el pool es ple, no té sentit continuar amb la resta de segments
|
||||
if (!spawnDebris(world_p1, world_p2, centro, velocitat_base, brightness,
|
||||
velocitat_objecte, velocitat_angular,
|
||||
factor_herencia_visual, color)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Crear debris para cada segment
|
||||
for (const auto& [local_p1, local_p2] : segments) {
|
||||
// 1. Transformar points locals → coordenades mundials
|
||||
Vec2 world_p1 =
|
||||
transformPoint(local_p1, shape_centre, centro, angle, scale);
|
||||
Vec2 world_p2 =
|
||||
transformPoint(local_p2, shape_centre, centro, angle, scale);
|
||||
auto DebrisManager::extractSegments(const Graphics::ShapePrimitive& primitive)
|
||||
-> std::vector<std::pair<Vec2, Vec2>> {
|
||||
std::vector<std::pair<Vec2, Vec2>> segments;
|
||||
|
||||
// 2. Trobar slot lliure
|
||||
Debris* debris = findFreeSlot();
|
||||
if (debris == nullptr) {
|
||||
std::cerr << "[DebrisManager] Warning: no debris slots disponibles\n";
|
||||
return; // Pool ple
|
||||
}
|
||||
|
||||
// 3. Inicialitzar geometria
|
||||
debris->p1 = world_p1;
|
||||
debris->p2 = world_p2;
|
||||
|
||||
// 4. Calcular direcció de explosión (radial, des del centro hacia fuera)
|
||||
Vec2 direccio = computeExplosionDirection(world_p1, world_p2, centro);
|
||||
|
||||
// 5. Velocidad inicial (base ± variació aleatòria + velocity heretada)
|
||||
float speed =
|
||||
velocitat_base +
|
||||
(((std::rand() / static_cast<float>(RAND_MAX)) * 2.0F - 1.0F) *
|
||||
Defaults::Physics::Debris::VARIACIO_VELOCITAT);
|
||||
|
||||
// Heredar velocity de l'objecte original (suma vectorial)
|
||||
debris->velocity.x = (direccio.x * speed) + velocitat_objecte.x;
|
||||
debris->velocity.y = (direccio.y * speed) + velocitat_objecte.y;
|
||||
debris->acceleration = Defaults::Physics::Debris::ACCELERACIO;
|
||||
|
||||
// 6. Herència de velocity angular con sin + conversió de excés
|
||||
|
||||
// 6a. Rotación de TRAYECTORIA con sin + conversió tangencial
|
||||
if (std::abs(velocitat_angular) > 0.01F) {
|
||||
// FASE 1: Aplicar herència i variació (igual que antes)
|
||||
float factor_herencia =
|
||||
Defaults::Physics::Debris::FACTOR_HERENCIA_MIN +
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) *
|
||||
(Defaults::Physics::Debris::FACTOR_HERENCIA_MAX -
|
||||
Defaults::Physics::Debris::FACTOR_HERENCIA_MIN));
|
||||
|
||||
float velocitat_ang_heretada = velocitat_angular * factor_herencia;
|
||||
|
||||
float variacio =
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) * 0.2F) - 0.1F;
|
||||
velocitat_ang_heretada *= (1.0F + variacio);
|
||||
|
||||
// FASE 2: Aplicar sin i calcular excés
|
||||
constexpr float CAP = Defaults::Physics::Debris::VELOCITAT_ROT_MAX;
|
||||
float abs_ang = std::abs(velocitat_ang_heretada);
|
||||
float sign_ang = (velocitat_ang_heretada >= 0.0F) ? 1.0F : -1.0F;
|
||||
|
||||
if (abs_ang > CAP) {
|
||||
// Excés: convertir a velocity tangencial
|
||||
float excess = abs_ang - CAP;
|
||||
|
||||
// Radi de la shape (enemigos = 20 px)
|
||||
float radius = 20.0F;
|
||||
|
||||
// Velocidad tangencial = ω_excés × radi
|
||||
float v_tangential = excess * radius;
|
||||
|
||||
// Direcció tangencial: perpendicular a la radial (90° CCW)
|
||||
// Si direccio = (dx, dy), tangent = (-dy, dx)
|
||||
float tangent_x = -direccio.y;
|
||||
float tangent_y = direccio.x;
|
||||
|
||||
// Añadir velocity tangencial (suma vectorial)
|
||||
debris->velocity.x += tangent_x * v_tangential;
|
||||
debris->velocity.y += tangent_y * v_tangential;
|
||||
|
||||
// Aplicar hacia velocity angular (preservar signe)
|
||||
debris->velocitat_rot = sign_ang * CAP;
|
||||
} else {
|
||||
// Per sota del sin: comportament normal
|
||||
debris->velocitat_rot = velocitat_ang_heretada;
|
||||
}
|
||||
} else {
|
||||
debris->velocitat_rot = 0.0F; // Nave: sin curvas
|
||||
}
|
||||
|
||||
// 6b. Rotación VISUAL (proporcional según factor_herencia_visual)
|
||||
if (factor_herencia_visual > 0.01F && std::abs(velocitat_angular) > 0.01F) {
|
||||
// Heredar rotación visual con factor proporcional
|
||||
debris->velocitat_rot_visual = debris->velocitat_rot * factor_herencia_visual;
|
||||
|
||||
// Variació aleatòria pequeña (±5%) per naturalitat
|
||||
float variacio_visual =
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) * 0.1F) - 0.05F;
|
||||
debris->velocitat_rot_visual *= (1.0F + variacio_visual);
|
||||
} else {
|
||||
// Rotación visual aleatòria (factor = 0.0 o sin velocidad angular)
|
||||
debris->velocitat_rot_visual =
|
||||
Defaults::Physics::Debris::ROTACIO_MIN +
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) *
|
||||
(Defaults::Physics::Debris::ROTACIO_MAX -
|
||||
Defaults::Physics::Debris::ROTACIO_MIN));
|
||||
|
||||
// 50% probabilitat de rotación en sentit contrari
|
||||
if (std::rand() % 2 == 0) {
|
||||
debris->velocitat_rot_visual = -debris->velocitat_rot_visual;
|
||||
}
|
||||
}
|
||||
|
||||
debris->angle_rotacio = 0.0F;
|
||||
|
||||
// 7. Configurar vida i shrinking
|
||||
debris->temps_vida = 0.0F;
|
||||
debris->temps_max = Defaults::Physics::Debris::TEMPS_VIDA;
|
||||
debris->factor_shrink = Defaults::Physics::Debris::SHRINK_RATE;
|
||||
|
||||
// 8. Heredar brightness y color del padre
|
||||
debris->brightness = brightness;
|
||||
debris->color = color;
|
||||
|
||||
// 9. Activar
|
||||
debris->active = true;
|
||||
if (primitive.type == Graphics::PrimitiveType::POLYLINE) {
|
||||
// Polyline: extreure segments consecutius
|
||||
for (size_t i = 0; i + 1 < primitive.points.size(); i++) {
|
||||
segments.emplace_back(primitive.points[i], primitive.points[i + 1]);
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
// PrimitiveType::LINE: un únic segment (si té els 2 punts)
|
||||
if (primitive.points.size() >= 2) {
|
||||
segments.emplace_back(primitive.points[0], primitive.points[1]);
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
|
||||
auto DebrisManager::spawnDebris(const Vec2& world_p1, const Vec2& world_p2,
|
||||
const Vec2& centro, float velocitat_base, float brightness,
|
||||
const Vec2& velocitat_objecte, float velocitat_angular,
|
||||
float factor_herencia_visual, SDL_Color color) -> bool {
|
||||
Debris* debris = findFreeSlot();
|
||||
if (debris == nullptr) {
|
||||
std::cerr << "[DebrisManager] Warning: no debris slots disponibles\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Geometria
|
||||
debris->p1 = world_p1;
|
||||
debris->p2 = world_p2;
|
||||
|
||||
// Direcció radial (desde el centro hacia el segment)
|
||||
Vec2 direccio = computeExplosionDirection(world_p1, world_p2, centro);
|
||||
|
||||
// Velocidad inicial (base ± variació aleatòria + velocity heretada de l'objecte)
|
||||
float speed =
|
||||
velocitat_base +
|
||||
(((std::rand() / static_cast<float>(RAND_MAX)) * 2.0F - 1.0F) *
|
||||
Defaults::Physics::Debris::VARIACIO_VELOCITAT);
|
||||
debris->velocity.x = (direccio.x * speed) + velocitat_objecte.x;
|
||||
debris->velocity.y = (direccio.y * speed) + velocitat_objecte.y;
|
||||
debris->acceleration = Defaults::Physics::Debris::ACCELERACIO;
|
||||
|
||||
// Rotación de trayectoria (con conversió a tangencial si excedeix cap)
|
||||
applyAngularVelocity(*debris, direccio, velocitat_angular);
|
||||
|
||||
// Rotación visual (proporcional o aleatòria)
|
||||
applyVisualRotation(*debris, velocitat_angular, factor_herencia_visual);
|
||||
|
||||
debris->angle_rotacio = 0.0F;
|
||||
|
||||
// Vida i shrinking
|
||||
debris->temps_vida = 0.0F;
|
||||
debris->temps_max = Defaults::Physics::Debris::TEMPS_VIDA;
|
||||
debris->factor_shrink = Defaults::Physics::Debris::SHRINK_RATE;
|
||||
|
||||
// Visuals heretades
|
||||
debris->brightness = brightness;
|
||||
debris->color = color;
|
||||
|
||||
debris->active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DebrisManager::applyAngularVelocity(Debris& debris, const Vec2& direccio,
|
||||
float velocitat_angular) {
|
||||
if (std::abs(velocitat_angular) <= 0.01F) {
|
||||
debris.velocitat_rot = 0.0F; // Nave: sin curvas
|
||||
return;
|
||||
}
|
||||
|
||||
// FASE 1: Aplicar herència i variació
|
||||
float factor_herencia =
|
||||
Defaults::Physics::Debris::FACTOR_HERENCIA_MIN +
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) *
|
||||
(Defaults::Physics::Debris::FACTOR_HERENCIA_MAX -
|
||||
Defaults::Physics::Debris::FACTOR_HERENCIA_MIN));
|
||||
float velocitat_ang_heretada = velocitat_angular * factor_herencia;
|
||||
float variacio = ((std::rand() / static_cast<float>(RAND_MAX)) * 0.2F) - 0.1F;
|
||||
velocitat_ang_heretada *= (1.0F + variacio);
|
||||
|
||||
// FASE 2: Cap a la velocity màxima; l'excés es converteix en tangencial
|
||||
constexpr float CAP = Defaults::Physics::Debris::VELOCITAT_ROT_MAX;
|
||||
float abs_ang = std::abs(velocitat_ang_heretada);
|
||||
float sign_ang = (velocitat_ang_heretada >= 0.0F) ? 1.0F : -1.0F;
|
||||
|
||||
if (abs_ang <= CAP) {
|
||||
debris.velocitat_rot = velocitat_ang_heretada;
|
||||
return;
|
||||
}
|
||||
|
||||
// Excés: converteix l'excés de velocitat angular en velocitat tangencial lineal
|
||||
float excess = abs_ang - CAP;
|
||||
constexpr float RADIUS = 20.0F; // Radi típic de la shape (enemigos = 20 px)
|
||||
float v_tangential = excess * RADIUS;
|
||||
|
||||
// Direcció tangencial: perpendicular a la radial (90° CCW): tangent = (-dy, dx)
|
||||
debris.velocity.x += -direccio.y * v_tangential;
|
||||
debris.velocity.y += direccio.x * v_tangential;
|
||||
|
||||
// Velocitat angular limitada al cap (preservant el signe)
|
||||
debris.velocitat_rot = sign_ang * CAP;
|
||||
}
|
||||
|
||||
void DebrisManager::applyVisualRotation(Debris& debris, float velocitat_angular,
|
||||
float factor_herencia_visual) {
|
||||
if (factor_herencia_visual > 0.01F && std::abs(velocitat_angular) > 0.01F) {
|
||||
// Heredar rotación visual con factor proporcional + ±5% de variació
|
||||
debris.velocitat_rot_visual = debris.velocitat_rot * factor_herencia_visual;
|
||||
float variacio_visual =
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) * 0.1F) - 0.05F;
|
||||
debris.velocitat_rot_visual *= (1.0F + variacio_visual);
|
||||
return;
|
||||
}
|
||||
|
||||
// Rotación visual aleatòria (factor = 0.0 o sin velocidad angular)
|
||||
debris.velocitat_rot_visual =
|
||||
Defaults::Physics::Debris::ROTACIO_MIN +
|
||||
((std::rand() / static_cast<float>(RAND_MAX)) *
|
||||
(Defaults::Physics::Debris::ROTACIO_MAX -
|
||||
Defaults::Physics::Debris::ROTACIO_MIN));
|
||||
|
||||
// 50% probabilitat de rotación en sentit contrari
|
||||
if (std::rand() % 2 == 0) {
|
||||
debris.velocitat_rot_visual = -debris.velocitat_rot_visual;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user