From 74a7863a8f0844c96510ad51214b2b4039879fb4 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 23 Jul 2024 22:35:50 +0200 Subject: [PATCH] acabat el nou motor d'animacions --- Makefile | 2 +- data/gfx/player.ani | 2 +- source/game.cpp | 157 +++++++++++++++++++--------------------- source/player.cpp | 169 ++++++++++++-------------------------------- source/player.h | 35 ++++----- 5 files changed, 138 insertions(+), 227 deletions(-) diff --git a/Makefile b/Makefile index afeb0ba..6c0cb1c 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ ifeq ($(OS),Windows_NT) FixPath = $(subst /,\,$1) SOURCES := source/*.cpp source/common/*.cpp CXXFLAGS:= -std=c++11 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows - CXXFLAGS2:= -std=c++11 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ + CXXFLAGS2:= -std=c++11 -Wall -static-libstdc++ LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32 RM = del /Q MKD:= mkdir diff --git a/data/gfx/player.ani b/data/gfx/player.ani index 1564e86..d8640ad 100644 --- a/data/gfx/player.ani +++ b/data/gfx/player.ani @@ -45,7 +45,7 @@ frames=20,21,22,23 [animation] name=death -speed=5 +speed=15 loop=0 frames=24,25,26,27 [/animation] \ No newline at end of file diff --git a/source/game.cpp b/source/game.cpp index 267e807..b273787 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -28,6 +28,15 @@ Game::Game(int playerID, int currentStage, SDL_Renderer *renderer, Screen *scree scoreboard = new Scoreboard(renderer, screen, asset, lang, options); background = new Background(renderer, screen, asset, param); + // Inicializa vectores + playerAnimations.clear(); + balloonAnimations.clear(); + itemAnimations.clear(); + player1Textures.clear(); + player2Textures.clear(); + itemTextures.clear(); + balloonTextures.clear(); + // Carga los recursos loadMedia(); @@ -91,48 +100,69 @@ Game::~Game() // Animaciones for (auto animation : playerAnimations) { - delete animation; + if (animation) + { + delete animation; + } } playerAnimations.clear(); for (auto animation : balloonAnimations) { - delete animation; + if (animation) + { + delete animation; + } } balloonAnimations.clear(); for (auto animation : itemAnimations) { - delete animation; + if (animation) + { + delete animation; + } } itemAnimations.clear(); // Texturas for (auto texture : player1Textures) { - texture->unload(); - delete texture; + if (texture) + { + texture->unload(); + delete texture; + } } player1Textures.clear(); for (auto texture : player2Textures) { - texture->unload(); - delete texture; + if (texture) + { + texture->unload(); + delete texture; + } } player2Textures.clear(); for (auto texture : itemTextures) { - texture->unload(); - delete texture; + if (texture) + { + texture->unload(); + delete texture; + } } itemTextures.clear(); for (auto texture : balloonTextures) { - texture->unload(); - delete texture; + if (texture) + { + texture->unload(); + delete texture; + } } balloonTextures.clear(); @@ -423,61 +453,31 @@ void Game::loadMedia() itemTextures.push_back(item6); // Texturas - Player1 - Texture *player1Head = new Texture(renderer, asset->get("player_bal1_head.png")); - player1Textures.push_back(player1Head); + Texture *player1 = new Texture(renderer, asset->get("player.png")); + player1Textures.push_back(player1); - Texture *player1Body = new Texture(renderer, asset->get("player_bal1_body.png")); - player1Textures.push_back(player1Body); - - Texture *player1Legs = new Texture(renderer, asset->get("player_bal1_legs.png")); - player1Textures.push_back(player1Legs); - - Texture *player1Death = new Texture(renderer, asset->get("player_bal1_death.png")); - player1Textures.push_back(player1Death); - - Texture *player1Fire = new Texture(renderer, asset->get("player_bal1_fire.png")); - player1Textures.push_back(player1Fire); + Texture *player1Power = new Texture(renderer, asset->get("player_power.png")); + player1Textures.push_back(player1Power); playerTextures.push_back(player1Textures); // Texturas - Player2 - Texture *player2Head = new Texture(renderer, asset->get("player_arounder_head.png")); - player2Textures.push_back(player2Head); + Texture *player2 = new Texture(renderer, asset->get("player.png")); + player2Textures.push_back(player2); - Texture *player2Body = new Texture(renderer, asset->get("player_arounder_body.png")); - player2Textures.push_back(player2Body); - - Texture *player2Legs = new Texture(renderer, asset->get("player_arounder_legs.png")); - player2Textures.push_back(player2Legs); - - Texture *player2Death = new Texture(renderer, asset->get("player_arounder_death.png")); - player2Textures.push_back(player2Death); - - Texture *player2Fire = new Texture(renderer, asset->get("player_arounder_fire.png")); - player2Textures.push_back(player2Fire); + Texture *player2Power = new Texture(renderer, asset->get("player_power.png")); + player2Textures.push_back(player2Power); playerTextures.push_back(player2Textures); // Animaciones -- Jugador - std::vector *playerHeadAnimation = new std::vector; - loadAnimations(asset->get("player_head.ani"), playerHeadAnimation); - playerAnimations.push_back(playerHeadAnimation); + std::vector *playerAnimation = new std::vector; + loadAnimations(asset->get("player.ani"), playerAnimation); + playerAnimations.push_back(playerAnimation); - std::vector *playerBodyAnimation = new std::vector; - loadAnimations(asset->get("player_body.ani"), playerBodyAnimation); - playerAnimations.push_back(playerBodyAnimation); - - std::vector *playerLegsAnimation = new std::vector; - loadAnimations(asset->get("player_legs.ani"), playerLegsAnimation); - playerAnimations.push_back(playerLegsAnimation); - - std::vector *playerDeathAnimation = new std::vector; - loadAnimations(asset->get("player_death.ani"), playerDeathAnimation); - playerAnimations.push_back(playerDeathAnimation); - - std::vector *playerFireAnimation = new std::vector; - loadAnimations(asset->get("player_fire.ani"), playerFireAnimation); - playerAnimations.push_back(playerFireAnimation); + std::vector *playerPowerAnimation = new std::vector; + loadAnimations(asset->get("player_power.ani"), playerPowerAnimation); + playerAnimations.push_back(playerPowerAnimation); // Animaciones -- Globos std::vector *balloon1Animation = new std::vector; @@ -2441,37 +2441,28 @@ void Game::renderSmartSprites() // Acciones a realizar cuando el jugador muere void Game::killPlayer(Player *player) { - if (!player->isEnabled()) - { + if (!player->isEnabled() && player->isInvulnerable()) + { // Si no está habilitado o tiene inmunidad, no hace nada return; } - if (!player->isInvulnerable()) - { - if (player->hasExtraHit()) - { - player->removeExtraHit(); - throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2)); - JA_PlaySound(coffeeOutSound); - screen->shake(); - } - else - { - JA_PauseMusic(); - stopAllBalloons(10); - JA_PlaySound(playerCollisionSound); - screen->shake(); - JA_PlaySound(coffeeOutSound); - player->setAlive(false); - if (allPlayersAreDead()) - { - JA_StopMusic(); - } - else - { - JA_ResumeMusic(); - } - } + // Si tiene cafes + if (player->hasExtraHit()) + { // Lo pierde + player->removeExtraHit(); + throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2)); + JA_PlaySound(coffeeOutSound); + screen->shake(); + } + else + { // Si no tiene cafes, muere + JA_PauseMusic(); + stopAllBalloons(10); + JA_PlaySound(playerCollisionSound); + screen->shake(); + JA_PlaySound(coffeeOutSound); + player->setAlive(false); + allPlayersAreDead() ? JA_StopMusic() : JA_ResumeMusic(); } } diff --git a/source/player.cpp b/source/player.cpp index 8eeaf13..f0e89a6 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -8,12 +8,9 @@ Player::Player(float x, int y, SDL_Renderer *renderer, std::vector te this->renderer = renderer; // Reserva memoria para los objetos - headSprite = new AnimatedSprite(texture[0], renderer, "", animations[0]); - bodySprite = new AnimatedSprite(texture[1], renderer, "", animations[1]); - legsSprite = new AnimatedSprite(texture[2], renderer, "", animations[2]); - deathSprite = new AnimatedSprite(texture[3], renderer, "", animations[3]); - fireSprite = new AnimatedSprite(texture[4], renderer, "", animations[4]); - fireSprite->getTexture()->setAlpha(224); + playerSprite = new AnimatedSprite(texture[0], renderer, "", animations[0]); + powerSprite = new AnimatedSprite(texture[1], renderer, "", animations[1]); + powerSprite->getTexture()->setAlpha(224); // Establece la posición inicial del jugador defaultPosX = posX = x; @@ -27,11 +24,8 @@ Player::Player(float x, int y, SDL_Renderer *renderer, std::vector te // Destructor Player::~Player() { - delete headSprite; - delete bodySprite; - delete legsSprite; - delete deathSprite; - delete fireSprite; + delete playerSprite; + delete powerSprite; } // Iniciador @@ -78,19 +72,11 @@ void Player::init() cooldown = 10; // Establece la posición del sprite - legsSprite->setPosX(posX); - legsSprite->setPosY(posY); - - bodySprite->setPosX(posX); - bodySprite->setPosY(posY); - - headSprite->setPosX(posX); - headSprite->setPosY(posY); + playerSprite->setPosX(posX); + playerSprite->setPosY(posY); // Selecciona un frame para pintar - legsSprite->setCurrentAnimation("stand"); - bodySprite->setCurrentAnimation("stand"); - headSprite->setCurrentAnimation("stand"); + playerSprite->setCurrentAnimation("stand"); } // Actua en consecuencia de la entrada recibida @@ -143,31 +129,25 @@ void Player::move() } // Actualiza la posición del sprite - legsSprite->setPosX(getPosX()); - legsSprite->setPosY(posY); + playerSprite->setPosX(getPosX()); + playerSprite->setPosY(posY); - bodySprite->setPosX(getPosX()); - bodySprite->setPosY(posY); - - headSprite->setPosX(getPosX()); - headSprite->setPosY(posY); - - fireSprite->setPosX(getPosX() - 2); - fireSprite->setPosY(posY - 10); + powerSprite->setPosX(getPosX() - 2); + powerSprite->setPosY(posY - 10); } else { - deathSprite->update(); + playerSprite->update(); // Si el cadaver abandona el area de juego por los laterales - if ((deathSprite->getPosX() < PLAY_AREA_LEFT) || (deathSprite->getPosX() + width > PLAY_AREA_RIGHT)) + if ((playerSprite->getPosX() < PLAY_AREA_LEFT) || (playerSprite->getPosX() + width > PLAY_AREA_RIGHT)) { // Restaura su posición - const float vx = deathSprite->getVelX(); - deathSprite->setPosX(deathSprite->getPosX() - vx); + const float vx = playerSprite->getVelX(); + playerSprite->setPosX(playerSprite->getPosX() - vx); // Rebota - deathSprite->setVelX(-vx); + playerSprite->setVelX(-vx); } } } @@ -183,27 +163,23 @@ void Player::render() { if (powerUp) { - fireSprite->render(); + powerSprite->render(); } - legsSprite->render(); - bodySprite->render(); - headSprite->render(); + playerSprite->render(); } } else { if (powerUp) { - fireSprite->render(); + powerSprite->render(); } - legsSprite->render(); - bodySprite->render(); - headSprite->render(); + playerSprite->render(); } } else { - deathSprite->render(); + playerSprite->render(); } } @@ -231,15 +207,6 @@ void Player::setFiringStatus(int status) void Player::setAnimation() { // Crea cadenas de texto para componer el nombre de la animación - std::string aBodyCoffees = ""; - std::string aHeadCoffees = ""; - if (coffees > 0) - { - aBodyCoffees = coffees == 1 ? "_1C" : "_2C"; - aHeadCoffees = "_1C"; - } - - const std::string aPowerUp = powerUp ? "_pwr" : ""; const std::string aWalking = statusWalking == PLAYER_STATUS_WALKING_STOP ? "stand" : "walk"; const std::string aFiring = statusFiring == PLAYER_STATUS_FIRING_UP ? "centershoot" : "sideshoot"; @@ -247,32 +214,29 @@ void Player::setAnimation() const SDL_RendererFlip flipFire = statusFiring == PLAYER_STATUS_FIRING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; // Establece la animación a partir de las cadenas - legsSprite->setCurrentAnimation(aWalking); - legsSprite->setFlip(flipWalk); - if (statusFiring == PLAYER_STATUS_FIRING_NO) + if (alive) { - // No esta disparando - bodySprite->setCurrentAnimation(aWalking + aBodyCoffees + aPowerUp); - bodySprite->setFlip(flipWalk); - headSprite->setCurrentAnimation(aWalking + aHeadCoffees + aPowerUp); - headSprite->setFlip(flipWalk); + if (statusFiring == PLAYER_STATUS_FIRING_NO) + { // No esta disparando + playerSprite->setCurrentAnimation(aWalking); + playerSprite->setFlip(flipWalk); + } + else + { // Está disparando + playerSprite->setCurrentAnimation(aWalking + "-" + aFiring); + playerSprite->setFlip(flipFire); + } } else { - // Está disparando - bodySprite->setCurrentAnimation(aFiring + aBodyCoffees + aPowerUp); - bodySprite->setFlip(flipFire); - headSprite->setCurrentAnimation(aFiring + aHeadCoffees + aPowerUp); - headSprite->setFlip(flipFire); + playerSprite->setCurrentAnimation("death"); } // Actualiza las animaciones de los sprites - legsSprite->animate(); - bodySprite->animate(); - headSprite->animate(); + playerSprite->animate(); - fireSprite->animate(); - fireSprite->setFlip(flipWalk); + powerSprite->setFlip(flipWalk); + powerSprite->animate(); } // Obtiene el valor de la variable @@ -338,7 +302,6 @@ void Player::update() updateCooldown(); updatePowerUpCounter(); updateInvulnerableCounter(); - updatePowerUpHeadOffset(); } // Obtiene la puntuación del jugador @@ -375,15 +338,9 @@ void Player::setAlive(bool value) if (!alive) { - deathSprite->setPosX(headSprite->getRect().x); - deathSprite->setPosY(headSprite->getRect().y); - deathSprite->setAccelY(0.2f); - deathSprite->setVelY(-6.6f); - deathSprite->setVelX(3.3f); - if (rand() % 2 == 0) - { - deathSprite->setVelX(-3.3f); - } + playerSprite->setAccelY(0.2f); + playerSprite->setVelY(-6.6f); + rand() % 2 == 0 ? playerSprite->setVelX(3.3f) : playerSprite->setVelX(-3.3f); } } @@ -402,27 +359,15 @@ void Player::setScoreMultiplier(float value) // Aumenta el valor de la variable hasta un máximo void Player::incScoreMultiplier() { - if (scoreMultiplier < 5.0f) - { - scoreMultiplier += 0.1f; - } - else - { - scoreMultiplier = 5.0f; - } + scoreMultiplier += 0.1f; + scoreMultiplier = std::min(scoreMultiplier, 5.0f); } // Decrementa el valor de la variable hasta un mínimo void Player::decScoreMultiplier() { - if (scoreMultiplier > 1.0f) - { - scoreMultiplier -= 0.1f; - } - else - { - scoreMultiplier = 1.0f; - } + scoreMultiplier -= 0.1f; + scoreMultiplier = std::max(scoreMultiplier, 1.0f); } // Obtiene el valor de la variable @@ -572,34 +517,14 @@ void Player::shiftColliders() // Obtiene el puntero a la textura con los gráficos de la animación de morir Texture *Player::getDeadTexture() { - return deathSprite->getTexture(); -} - -// Actualiza el valor de la variable -void Player::updatePowerUpHeadOffset() -{ - if (powerUp) - if (powerUpCounter < 300) - { - if (powerUpCounter % 6 > 2) - { - fireSprite->setEnabled(false); - } - else - { - fireSprite->setEnabled(true); - } - } + return playerSprite->getTexture(); } // Pone las texturas del jugador void Player::setPlayerTextures(std::vector texture) { - headSprite->setTexture(texture[0]); - bodySprite->setTexture(texture[1]); - legsSprite->setTexture(texture[2]); - deathSprite->setTexture(texture[3]); - fireSprite->setTexture(texture[4]); + playerSprite->setTexture(texture[0]); + powerSprite->setTexture(texture[1]); } // Activa o descativa el jugador diff --git a/source/player.h b/source/player.h index e7bc898..45c9358 100644 --- a/source/player.h +++ b/source/player.h @@ -29,12 +29,9 @@ class Player { private: // Objetos y punteros - SDL_Renderer *renderer; // El renderizador de la ventana - AnimatedSprite *headSprite; // Sprite para dibujar la cabeza - AnimatedSprite *bodySprite; // Sprite para dibujar el cuerpo - AnimatedSprite *legsSprite; // Sprite para dibujar las piernas - AnimatedSprite *deathSprite; // Sprite para dibujar el jugador derrotado - AnimatedSprite *fireSprite; // Sprite para dibujar el aura del jugador con el poder a tope + SDL_Renderer *renderer; // El renderizador de la ventana + AnimatedSprite *playerSprite; // Sprite para dibujar el jugador + AnimatedSprite *powerSprite; // Sprite para dibujar el aura del jugador con el poder a tope // Variables float posX; // Posicion en el eje X @@ -43,7 +40,7 @@ private: float defaultPosX; // Posición inicial para el jugador int defaultPosY; // Posición inicial para el jugador - int width; // Anchura + int width; // Anchura int height; // Altura float velX; // Cantidad de pixeles a desplazarse en el eje X @@ -52,22 +49,22 @@ private: float baseSpeed; // Velocidad base del jugador int cooldown; // Contador durante el cual no puede disparar - int score; // Puntos del jugador + int score; // Puntos del jugador float scoreMultiplier; // Multiplicador de puntos int statusWalking; // Estado del jugador - int statusFiring; // Estado del jugador + int statusFiring; // Estado del jugador - bool invulnerable; // Indica si el jugador es invulnerable + bool invulnerable; // Indica si el jugador es invulnerable int invulnerableCounter; // Contador para la invulnerabilidad - bool extraHit; // Indica si el jugador tiene un toque extra - int coffees; // Indica cuantos cafes lleva acumulados - bool powerUp; // Indica si el jugador tiene activo el modo PowerUp - int powerUpCounter; // Temporizador para el modo PowerUp - bool input; // Indica si puede recibir ordenes de entrada - circle_t collider; // Circulo de colisión del jugador - bool alive; // Indica si el jugador está vivo - bool enabled; // Indica si el jugador está activo + bool extraHit; // Indica si el jugador tiene un toque extra + int coffees; // Indica cuantos cafes lleva acumulados + bool powerUp; // Indica si el jugador tiene activo el modo PowerUp + int powerUpCounter; // Temporizador para el modo PowerUp + bool input; // Indica si puede recibir ordenes de entrada + circle_t collider; // Circulo de colisión del jugador + bool alive; // Indica si el jugador está vivo + bool enabled; // Indica si el jugador está activo // Actualiza el circulo de colisión a la posición del jugador void shiftColliders(); @@ -75,8 +72,6 @@ private: // Actualiza el valor de la variable void updateInvulnerableCounter(); - // Actualiza el valor de la variable - void updatePowerUpHeadOffset(); public: // Constructor