afegit efecte de "colp" quan el jugador es "alcanssat" per un globo
This commit is contained in:
@@ -9,7 +9,7 @@ game.play_area.rect.h 200 # Alto de la zona jugable
|
||||
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
||||
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
|
||||
game.hit_stop true # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
||||
game.hit_stop_ms 300 # Cantidad de milisegundos que dura el hit_stop
|
||||
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
||||
|
||||
## --- FADE ---
|
||||
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
||||
|
||||
@@ -9,7 +9,7 @@ game.play_area.rect.h 216 # Alto de la zona jugable
|
||||
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
||||
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
|
||||
game.hit_stop true # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
||||
game.hit_stop_ms 300 # Cantidad de milisegundos que dura el hit_stop
|
||||
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
||||
|
||||
## --- FADE ---
|
||||
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
||||
|
||||
BIN
data/gfx/player/hit.png
Normal file
BIN
data/gfx/player/hit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 312 B |
@@ -60,6 +60,16 @@ void Audio::pauseMusic() {
|
||||
}
|
||||
}
|
||||
|
||||
// Continua la música pausada
|
||||
void Audio::resumeMusic() {
|
||||
if (music_enabled_ && music_.state == MusicState::PAUSED) {
|
||||
#ifndef NO_AUDIO
|
||||
JA_ResumeMusic();
|
||||
#endif
|
||||
music_.state = MusicState::PLAYING;
|
||||
}
|
||||
}
|
||||
|
||||
// Detiene la música
|
||||
void Audio::stopMusic() {
|
||||
if (music_enabled_) {
|
||||
|
||||
@@ -25,11 +25,12 @@ class Audio {
|
||||
auto operator=(const Audio &) -> Audio & = delete; // Evitar asignación
|
||||
|
||||
// --- Método principal ---
|
||||
void update();
|
||||
void update();
|
||||
|
||||
// --- Control de Música ---
|
||||
void playMusic(const std::string &name, int loop = -1); // Reproducir música en bucle
|
||||
void pauseMusic(); // Pausar reproducción de música
|
||||
void resumeMusic(); // Continua la música pausada
|
||||
void stopMusic(); // Detener completamente la música
|
||||
void fadeOutMusic(int milliseconds) const; // Fundido de salida de la música
|
||||
|
||||
|
||||
@@ -402,10 +402,13 @@ void Director::setFileList() {
|
||||
Asset::get()->add(PREFIX + "/data/gfx/player/player2_coffee2.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(PREFIX + "/data/gfx/player/player2_invencible.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(PREFIX + "/data/gfx/player/player2_power.png", AssetType::BITMAP);
|
||||
|
||||
|
||||
// Animaciones del jugador
|
||||
Asset::get()->add(PREFIX + "/data/gfx/player/player.ani", AssetType::ANIMATION);
|
||||
Asset::get()->add(PREFIX + "/data/gfx/player/player_power.ani", AssetType::ANIMATION);
|
||||
|
||||
// Texturas - Golpe del jugador
|
||||
Asset::get()->add(PREFIX + "/data/gfx/player/hit.png", AssetType::BITMAP);
|
||||
|
||||
// Fuentes de texto
|
||||
Asset::get()->add(PREFIX + "/data/font/8bithud.png", AssetType::BITMAP);
|
||||
|
||||
61
source/hit.h
Normal file
61
source/hit.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h> // Para SDL_FPoint
|
||||
|
||||
#include <memory> // Para std::unique_ptr y std::shared_ptr
|
||||
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
|
||||
// Estructura que representa una colisión o impacto visual
|
||||
struct Hit {
|
||||
private:
|
||||
// Indica si el Hit está activo o no
|
||||
bool enabled{false};
|
||||
|
||||
// Sprite asociado al Hit, gestionado con un puntero único
|
||||
std::unique_ptr<Sprite> sprite;
|
||||
|
||||
public:
|
||||
// Elimina el constructor por defecto para obligar a pasar una textura
|
||||
Hit() = delete;
|
||||
|
||||
// Constructor que obliga a pasar una textura compartida para crear el Sprite
|
||||
// Esto evita que se pueda crear un Hit sin recursos gráficos válidos
|
||||
explicit Hit(std::shared_ptr<Texture> texture)
|
||||
: sprite(std::make_unique<Sprite>(texture)) {}
|
||||
|
||||
// Establece la posición del Sprite en el espacio
|
||||
void setPos(SDL_FPoint position) {
|
||||
SDL_FPoint centered_position = {position.x - (sprite->getWidth() / 2), position.y - (sprite->getHeight() / 2)};
|
||||
sprite->setPosition(centered_position);
|
||||
}
|
||||
|
||||
// Activa o desactiva el Hit
|
||||
void enable(bool value) {
|
||||
enabled = value;
|
||||
}
|
||||
|
||||
// Consulta si el Hit está activo
|
||||
bool isEnabled() const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
// Crea un "Hit" en la posición especificada
|
||||
void create(SDL_FPoint position) {
|
||||
setPos(position);
|
||||
enable(true);
|
||||
}
|
||||
|
||||
// Dibuja el hit
|
||||
void render() {
|
||||
if (enabled) {
|
||||
sprite->render();
|
||||
}
|
||||
}
|
||||
|
||||
// Deshabilita el hit
|
||||
void disable() {
|
||||
enabled = false;
|
||||
}
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <functional> // Para function
|
||||
#include <iostream> // Para std::cout, std::endl
|
||||
#include <iterator> // Para distance, size
|
||||
#include <memory> // Para std::make_unique
|
||||
|
||||
#include "asset.h" // Para Asset
|
||||
#include "audio.h" // Para Audio
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "fade.h" // Para Fade, FadeType, FadeMode
|
||||
#include "global_events.h" // Para check
|
||||
#include "global_inputs.h" // Para check
|
||||
#include "hit.h" // Para Hit
|
||||
#include "input.h" // Para InputAction, Input, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_ALLOW_REPEAT, InputDevice
|
||||
#include "item.h" // Para Item, ItemType
|
||||
#include "lang.h" // Para getText
|
||||
@@ -49,7 +51,8 @@ Game::Game(int player_id, int current_stage, bool demo)
|
||||
fade_in_(std::make_unique<Fade>()),
|
||||
fade_out_(std::make_unique<Fade>()),
|
||||
balloon_manager_(std::make_unique<BalloonManager>()),
|
||||
tabe_(std::make_unique<Tabe>()) {
|
||||
tabe_(std::make_unique<Tabe>()),
|
||||
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
||||
// Pasa variables
|
||||
demo_.enabled = demo;
|
||||
|
||||
@@ -213,7 +216,7 @@ void Game::updatePlayers() {
|
||||
}
|
||||
// En caso contrario, el jugador ha sido golpeado por un globo activo
|
||||
else {
|
||||
handlePlayerCollision(player);
|
||||
handlePlayerCollision(player, balloon);
|
||||
|
||||
if (demo_.enabled && allPlayersAreNotPlaying()) {
|
||||
fade_out_->setType(FadeType::RANDOM_SQUARE);
|
||||
@@ -830,7 +833,7 @@ void Game::renderPathSprites() {
|
||||
}
|
||||
|
||||
// Acciones a realizar cuando el jugador colisiona con un globo
|
||||
void Game::handlePlayerCollision(std::shared_ptr<Player> &player) {
|
||||
void Game::handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_ptr<Balloon> &balloon) {
|
||||
if (!player->isPlaying() || player->isInvulnerable()) {
|
||||
// Si no está jugando o tiene inmunidad, no hace nada
|
||||
return;
|
||||
@@ -847,15 +850,19 @@ void Game::handlePlayerCollision(std::shared_ptr<Player> &player) {
|
||||
// Si no tiene cafes, muere
|
||||
playSound("player_collision.wav");
|
||||
if (param.game.hit_stop) {
|
||||
pauseMusic();
|
||||
auto position = getCollisionPoint(player->getCollider(), balloon->getCollider());
|
||||
putHitOnScreen(position);
|
||||
SDL_Delay(param.game.hit_stop_ms);
|
||||
hit_.disable();
|
||||
resumeMusic();
|
||||
}
|
||||
screen_->shake();
|
||||
playSound("voice_no.wav");
|
||||
player->setPlayingState(PlayerState::ROLLING);
|
||||
players_to_reorder_.push_back(player);
|
||||
if (allPlayersAreNotPlaying()) {
|
||||
// No se puede subir poder de fase si no hay nadie jugando
|
||||
Stage::power_can_be_added = false;
|
||||
Stage::power_can_be_added = false; // No se puede subir poder de fase si no hay nadie jugando
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -979,6 +986,7 @@ void Game::fillCanvas() {
|
||||
// Dibuja los objetos
|
||||
background_->render();
|
||||
renderPlayers();
|
||||
renderHit();
|
||||
renderSmartSprites();
|
||||
renderItems();
|
||||
balloon_manager_->render();
|
||||
@@ -1598,6 +1606,16 @@ void Game::playMusic() {
|
||||
Audio::get()->playMusic("playing.ogg");
|
||||
}
|
||||
|
||||
// Pausa la música
|
||||
void Game::pauseMusic() {
|
||||
Audio::get()->pauseMusic();
|
||||
}
|
||||
|
||||
// Retoma la música que eestaba pausada
|
||||
void Game::resumeMusic() {
|
||||
Audio::get()->resumeMusic();
|
||||
}
|
||||
|
||||
// Detiene la música
|
||||
void Game::stopMusic() const {
|
||||
if (!demo_.enabled) {
|
||||
@@ -1823,6 +1841,19 @@ void Game::checkServiceMenu() {
|
||||
service_menu_was_active_ = service_menu_is_active;
|
||||
}
|
||||
|
||||
// Dibuja el golpe que recibe el jugador al impactarle un globo
|
||||
void Game::renderHit() {
|
||||
hit_.render();
|
||||
}
|
||||
|
||||
// Coloca el Hit en pantalla obligando a hacer un renderizado
|
||||
void Game::putHitOnScreen(SDL_FPoint position) {
|
||||
hit_.create(position);
|
||||
fillCanvas();
|
||||
render();
|
||||
hit_.disable();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Comprueba los eventos en el modo DEBUG
|
||||
void Game::checkDebugEvents(const SDL_Event &event) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string> // Para string
|
||||
#include <vector> // Para vector
|
||||
|
||||
#include "hit.h" // Para Hit
|
||||
#include "item.h" // Para Item, ItemType
|
||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||
#include "options.h" // Para SettingsOptions, settings
|
||||
@@ -147,6 +148,7 @@ class Game {
|
||||
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
||||
GameState state_ = GameState::FADE_IN; // Estado
|
||||
std::vector<std::shared_ptr<Player>> players_to_reorder_;
|
||||
Hit hit_; // Para representar colisiones en pantalla
|
||||
|
||||
#ifdef _DEBUG
|
||||
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
|
||||
@@ -186,9 +188,9 @@ class Game {
|
||||
auto allPlayersAreNotPlaying() -> bool; // Verifica si ningún jugador está activo
|
||||
|
||||
// --- Colisiones de jugadores ---
|
||||
void handlePlayerCollision(std::shared_ptr<Player> &player); // Procesa colisión de jugador con globo
|
||||
auto checkPlayerBalloonCollision(std::shared_ptr<Player> &player) -> std::shared_ptr<Balloon>; // Detecta colisión jugador-globo
|
||||
void checkPlayerItemCollision(std::shared_ptr<Player> &player); // Detecta colisión jugador-ítem
|
||||
void handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_ptr<Balloon> &balloon); // Procesa colisión de jugador con globo
|
||||
auto checkPlayerBalloonCollision(std::shared_ptr<Player> &player) -> std::shared_ptr<Balloon>; // Detecta colisión jugador-globo
|
||||
void checkPlayerItemCollision(std::shared_ptr<Player> &player); // Detecta colisión jugador-ítem
|
||||
|
||||
// --- Sistema de entrada (input) ---
|
||||
void checkInput(); // Gestiona toda la entrada durante el juego
|
||||
@@ -284,11 +286,16 @@ class Game {
|
||||
// --- Sistema de audio ---
|
||||
static void playMusic(); // Reproduce la música de fondo
|
||||
void stopMusic() const; // Detiene la reproducción de música
|
||||
void pauseMusic(); // Pausa la música
|
||||
void resumeMusic(); // Retoma la música que eestaba pausada
|
||||
void playSound(const std::string &name) const; // Reproduce un efecto de sonido específico
|
||||
|
||||
// --- Utilidades y servicios ---
|
||||
void checkServiceMenu(); // Verifica si el menú de servicio está activo
|
||||
|
||||
void renderHit(); // Dibuja el golpe que recibe el jugador al impactarle un globo
|
||||
void putHitOnScreen(SDL_FPoint position); // Coloca el Hit en pantalla obligando a hacer un renderizado
|
||||
|
||||
// SISTEMA DE GRABACIÓN (CONDICIONAL)
|
||||
#ifdef RECORDING
|
||||
void updateRecording(); // Actualiza variables durante modo de grabación
|
||||
|
||||
@@ -24,6 +24,25 @@ auto distanceSquared(int x1, int y1, int x2, int y2) -> double {
|
||||
return DELTA_X * DELTA_X + DELTA_Y * DELTA_Y;
|
||||
}
|
||||
|
||||
// Obtiene el punto de colisión entre dos circulos
|
||||
auto getCollisionPoint(const Circle &a, const Circle &b) -> SDL_FPoint {
|
||||
float dx = b.x - a.x;
|
||||
float dy = b.y - a.y;
|
||||
float dist = std::sqrt(dx * dx + dy * dy);
|
||||
|
||||
// Normaliza el vector
|
||||
float nx = dx / dist;
|
||||
float ny = dy / dist;
|
||||
|
||||
// Punto en el borde del círculo A hacia B
|
||||
SDL_FPoint contact;
|
||||
contact.x = a.x + nx * a.r;
|
||||
contact.y = a.y + ny * a.r;
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
|
||||
// Detector de colisiones entre dos circulos
|
||||
auto checkCollision(const Circle &a, const Circle &b) -> bool {
|
||||
// Calcula el radio total al cuadrado
|
||||
|
||||
@@ -79,6 +79,7 @@ struct Zone {
|
||||
|
||||
// Colisiones y geometría
|
||||
auto distanceSquared(int x1, int y1, int x2, int y2) -> double;
|
||||
auto getCollisionPoint(const Circle &a, const Circle &b) -> SDL_FPoint;
|
||||
auto checkCollision(const Circle &a, const Circle &b) -> bool;
|
||||
auto checkCollision(const Circle &a, const SDL_FRect &b) -> bool;
|
||||
auto checkCollision(const SDL_FRect &a, const SDL_FRect &b) -> bool;
|
||||
|
||||
Reference in New Issue
Block a user