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;
+29 -29
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,12 +76,12 @@ 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!",
@@ -95,7 +95,7 @@ inline constexpr std::array<const char*, 12> MISSATGES_LEVEL_START = {
"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