Merge branch 'tune/gameplay': balas, velocitat, stage 1 i so hit

This commit is contained in:
2026-05-21 19:05:53 +02:00
8 changed files with 60 additions and 55 deletions
Binary file not shown.
+3 -3
View File
@@ -9,11 +9,11 @@ metadata:
stages: stages:
# STAGE 1: Tutorial - Only pentagons, slow speed # STAGE 1: Tutorial - Only pentagons, slow speed
- stage_id: 1 - stage_id: 1
total_enemies: 5 total_enemies: 50
spawn_config: spawn_config:
mode: "progressive" mode: "progressive"
initial_delay: 2.0 initial_delay: 0.3
spawn_interval: 3.0 spawn_interval: 0.4
enemy_distribution: enemy_distribution:
pentagon: 100 pentagon: 100
cuadrado: 0 cuadrado: 0
+1
View File
@@ -38,6 +38,7 @@ namespace Defaults::Sound {
constexpr const char* EXPLOSION = "effects/explosion.wav"; // Explosión constexpr const char* EXPLOSION = "effects/explosion.wav"; // Explosión
constexpr const char* EXPLOSION2 = "effects/explosion2.wav"; // Explosión alternativa constexpr const char* EXPLOSION2 = "effects/explosion2.wav"; // Explosión alternativa
constexpr const char* FRIENDLY_FIRE_HIT = "effects/friendly_fire.wav"; // Friendly fire hit constexpr const char* FRIENDLY_FIRE_HIT = "effects/friendly_fire.wav"; // Friendly fire hit
constexpr const char* HIT = "effects/hit.wav"; // Enemic ferit (primer impacte → HURT)
constexpr const char* INIT_HUD = "effects/init_hud.wav"; // Para la animación del HUD constexpr const char* INIT_HUD = "effects/init_hud.wav"; // Para la animación del HUD
constexpr const char* LASER = "effects/laser_shoot.wav"; // Disparo constexpr const char* LASER = "effects/laser_shoot.wav"; // Disparo
constexpr const char* LOGO = "effects/logo.wav"; // Logo constexpr const char* LOGO = "effects/logo.wav"; // Logo
+1 -1
View File
@@ -6,7 +6,7 @@
namespace Defaults::Entities { namespace Defaults::Entities {
constexpr int MAX_ORNIS = 15; constexpr int MAX_ORNIS = 15;
constexpr int MAX_BALES = 3; constexpr int MAX_BALES = 50;
constexpr float SHIP_RADIUS = 12.0F; constexpr float SHIP_RADIUS = 12.0F;
constexpr float ENEMY_RADIUS = 20.0F; constexpr float ENEMY_RADIUS = 20.0F;
+1 -1
View File
@@ -7,7 +7,7 @@ namespace Defaults::Physics {
constexpr float ROTATION_SPEED = 3.14F; // rad/s (~180°/s) constexpr float ROTATION_SPEED = 3.14F; // rad/s (~180°/s)
constexpr float ACCELERATION = 400.0F; // px/s² constexpr float ACCELERATION = 400.0F; // px/s²
constexpr float MAX_VELOCITY = 120.0F; // px/s constexpr float MAX_VELOCITY = 180.0F; // px/s
constexpr float FRICTION = 20.0F; // px/s² constexpr float FRICTION = 20.0F; // px/s²
// Bullet — impacto físico contra enemigo (impulse mass-aware). // Bullet — impacto físico contra enemigo (impulse mass-aware).
+2
View File
@@ -8,6 +8,7 @@
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include "core/audio/audio.hpp"
#include "core/defaults.hpp" #include "core/defaults.hpp"
#include "core/entities/entity.hpp" #include "core/entities/entity.hpp"
#include "core/graphics/shape_loader.hpp" #include "core/graphics/shape_loader.hpp"
@@ -276,6 +277,7 @@ void Enemy::destruir() {
void Enemy::herir(uint8_t shooter_id) { void Enemy::herir(uint8_t shooter_id) {
wounded_timer_ = Defaults::Enemies::Wounded::DURATION; wounded_timer_ = Defaults::Enemies::Wounded::DURATION;
last_hit_by_ = shooter_id; last_hit_by_ = shooter_id;
Audio::get()->playSound(Defaults::Sound::HIT, Audio::Group::GAME);
} }
void Enemy::applyImpulse(const Vec2& impulse) { void Enemy::applyImpulse(const Vec2& impulse) {
+5 -3
View File
@@ -850,9 +850,11 @@ void GameScene::fireBullet(uint8_t player_id) {
float tip_y = (LOCAL_TIP_X * sin_a) + (LOCAL_TIP_Y * cos_a) + ship_centre.y; float tip_y = (LOCAL_TIP_X * sin_a) + (LOCAL_TIP_Y * cos_a) + ship_centre.y;
Vec2 posicio_dispar = {.x = tip_x, .y = tip_y}; Vec2 posicio_dispar = {.x = tip_x, .y = tip_y};
// Buscar primera bullet inactiva en el pool del player // Buscar primera bullet inactiva en el pool del player.
int start_idx = player_id * 3; // P1=[0,1,2], P2=[3,4,5] // El pool global té MAX_BALES slots per jugador (P1=[0..MAX-1], P2=[MAX..2*MAX-1]).
for (int i = start_idx; i < start_idx + 3; i++) { constexpr int SLOTS_PER_PLAYER = Defaults::Entities::MAX_BALES;
const int START_IDX = player_id * SLOTS_PER_PLAYER;
for (int i = START_IDX; i < START_IDX + SLOTS_PER_PLAYER; i++) {
if (!bullets_[i].isActive()) { if (!bullets_[i].isActive()) {
bullets_[i].disparar(posicio_dispar, ship_angle, player_id); bullets_[i].disparar(posicio_dispar, ship_angle, player_id);
break; break;
+47 -47
View File
@@ -10,46 +10,46 @@
namespace StageSystem { namespace StageSystem {
// Tipo de mode de spawn // Tipo de mode de spawn
enum class ModeSpawn : std::uint8_t { enum class ModeSpawn : std::uint8_t {
PROGRESSIVE, // Spawn progressiu con intervals PROGRESSIVE, // Spawn progressiu con intervals
IMMEDIATE, // Todos los enemigos de cop IMMEDIATE, // Todos los enemigos de cop
WAVE // Onades de 3-5 enemigos (futura extensió) WAVE // Onades de 3-5 enemigos (futura extensió)
}; };
// Configuración de spawn // Configuración de spawn
struct ConfigSpawn { struct ConfigSpawn {
ModeSpawn mode; ModeSpawn mode;
float delay_inicial; // Segons antes del primer spawn float delay_inicial; // Segons antes del primer spawn
float interval_spawn; // Segons entre spawns consecutius float interval_spawn; // Segons entre spawns consecutius
}; };
// Distribució de type de enemigos (percentatges) // Distribució de type de enemigos (percentatges)
struct DistribucioEnemics { struct DistribucioEnemics {
uint8_t pentagon; // 0-100 uint8_t pentagon; // 0-100
uint8_t cuadrado; // 0-100 uint8_t cuadrado; // 0-100
uint8_t molinillo; // 0-100 uint8_t molinillo; // 0-100
// Suma ha de ser 100, validat en StageLoader // Suma ha de ser 100, validat en StageLoader
}; };
// Multiplicadors de dificultat // Multiplicadors de dificultat
struct MultiplicadorsDificultat { struct MultiplicadorsDificultat {
float velocity; // 0.5-2.0 típic float velocity; // 0.5-2.0 típic
float rotation; // 0.5-2.0 típic float rotation; // 0.5-2.0 típic
float tracking_strength; // 0.0-1.5 (aplicat a Cuadrado) float tracking_strength; // 0.0-1.5 (aplicat a Cuadrado)
}; };
// Metadades del file YAML // Metadades del file YAML
struct MetadataStages { struct MetadataStages {
std::string version; std::string version;
uint8_t total_stages; uint8_t total_stages;
std::string descripcio; std::string descripcio;
}; };
// Configuración completa de un stage // Configuración completa de un stage
struct StageConfig { struct StageConfig {
uint8_t stage_id; // 1-10 uint8_t stage_id; // 1-10
uint8_t total_enemies; // 5-15 uint8_t total_enemies; // 1-200 (el cap simultani en pantalla el marca MAX_ORNIS)
ConfigSpawn config_spawn; ConfigSpawn config_spawn;
DistribucioEnemics distribucio; DistribucioEnemics distribucio;
MultiplicadorsDificultat multiplicadors; MultiplicadorsDificultat multiplicadors;
@@ -59,13 +59,13 @@ struct StageConfig {
// stage_id es uint8_t: el rango superior (<=255) está garantizado por // stage_id es uint8_t: el rango superior (<=255) está garantizado por
// el tipo; basta con confirmar que no es 0 (sentinela "sin asignar"). // el tipo; basta con confirmar que no es 0 (sentinela "sin asignar").
return stage_id >= 1 && return stage_id >= 1 &&
total_enemies > 0 && total_enemies <= 15 && total_enemies > 0 && total_enemies <= 200 &&
distribucio.pentagon + distribucio.cuadrado + distribucio.molinillo == 100; distribucio.pentagon + distribucio.cuadrado + distribucio.molinillo == 100;
} }
}; };
// Configuración completa del sistema (carregada desde YAML) // Configuración completa del sistema (carregada desde YAML)
struct StageSystemConfig { struct StageSystemConfig {
MetadataStages metadata; MetadataStages metadata;
std::vector<StageConfig> stages; // Índex [0] = stage 1 std::vector<StageConfig> stages; // Índex [0] = stage 1
@@ -76,26 +76,26 @@ struct StageSystemConfig {
} }
return &stages[stage_id - 1]; return &stages[stage_id - 1];
} }
}; };
// Constants per messages de transición // Constants per messages de transición
namespace Constants { namespace Constants {
// Pool de messages per start de level (selecció aleatòria) // Pool de messages per start de level (selecció aleatòria)
inline constexpr std::array<const char*, 12> MISSATGES_LEVEL_START = { inline constexpr std::array<const char*, 12> MISSATGES_LEVEL_START = {
"ORNI ALERT!", "ORNI ALERT!",
"INCOMING ORNIS!", "INCOMING ORNIS!",
"ROLLING THREAT!", "ROLLING THREAT!",
"ENEMY WAVE!", "ENEMY WAVE!",
"WAVE OF ORNIS DETECTED!", "WAVE OF ORNIS DETECTED!",
"NEXT SWARM APPROACHING!", "NEXT SWARM APPROACHING!",
"BRACE FOR THE NEXT WAVE!", "BRACE FOR THE NEXT WAVE!",
"ANOTHER ATTACK INCOMING!", "ANOTHER ATTACK INCOMING!",
"SENSORS DETECT HOSTILE ORNIS...", "SENSORS DETECT HOSTILE ORNIS...",
"UNIDENTIFIED ROLLING OBJECTS INBOUND!", "UNIDENTIFIED ROLLING OBJECTS INBOUND!",
"ENEMY FORCES MOBILIZING!", "ENEMY FORCES MOBILIZING!",
"PREPARE FOR IMPACT!"}; "PREPARE FOR IMPACT!"};
constexpr const char* MISSATGE_LEVEL_COMPLETED = "GOOD JOB COMMANDER!"; constexpr const char* MISSATGE_LEVEL_COMPLETED = "GOOD JOB COMMANDER!";
} // namespace Constants } // namespace Constants
} // namespace StageSystem } // namespace StageSystem