#include "const.h" #include "player.h" // Constructor Player::Player(float x, int y, SDL_Renderer *renderer, std::vector texture, std::vector *> animations) { // Copia los punteros this->renderer = renderer; // Reserva memoria para los objetos headSprite = new AnimatedSprite(texture.at(0), renderer, "", animations.at(0)); bodySprite = new AnimatedSprite(texture.at(1), renderer, "", animations.at(1)); legsSprite = new AnimatedSprite(texture.at(2), renderer, "", animations.at(2)); deathSprite = new AnimatedSprite(texture.at(3), renderer, "", animations.at(3)); // Establece la posición inicial del jugador posX = x; posY = y; init(); } // Destructor Player::~Player() { delete headSprite; delete bodySprite; delete legsSprite; delete deathSprite; } // Iniciador void Player::init() { // Inicializa variables de estado alive = true; deathCounter = DEATH_COUNTER; statusWalking = PLAYER_STATUS_WALKING_STOP; statusFiring = PLAYER_STATUS_FIRING_NO; invulnerable = false; invulnerableCounter = PLAYER_INVULNERABLE_COUNTER; powerUp = false; powerUpCounter = PLAYER_POWERUP_COUNTER; extraHit = false; coffees = 0; input = true; // Establece la altura y el ancho del jugador width = 24; height = 24; // Establece el tamaño del circulo de colisión collider.r = 7; // Actualiza la posición del circulo de colisión shiftColliders(); // Establece la velocidad inicial velX = 0; velY = 0; // Establece la velocidad base baseSpeed = 1.5; // Establece la puntuación inicial score = 0; // Establece el multiplicador de puntos inicial scoreMultiplier = 1.0f; // Inicia el contador para la cadencia de disparo 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); // Selecciona un frame para pintar legsSprite->setCurrentAnimation("stand"); bodySprite->setCurrentAnimation("stand"); headSprite->setCurrentAnimation("stand"); } // Actua en consecuencia de la entrada recibida void Player::setInput(Uint8 input) { switch (input) { case INPUT_LEFT: velX = -baseSpeed; setWalkingStatus(PLAYER_STATUS_WALKING_LEFT); break; case INPUT_RIGHT: velX = baseSpeed; setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT); break; case INPUT_BUTTON_2: setFiringStatus(PLAYER_STATUS_FIRING_UP); break; case INPUT_BUTTON_1: setFiringStatus(PLAYER_STATUS_FIRING_LEFT); break; case INPUT_BUTTON_3: setFiringStatus(PLAYER_STATUS_FIRING_RIGHT); break; default: velX = 0; setWalkingStatus(PLAYER_STATUS_WALKING_STOP); break; } } // Mueve el jugador a la posición y animación que le corresponde void Player::move() { if (isAlive()) { // Mueve el jugador a derecha o izquierda posX += velX; // Si el jugador abandona el area de juego por los laterales if ((posX < PLAY_AREA_LEFT - 5) || (posX + width > PLAY_AREA_RIGHT + 5)) { // Restaura su posición posX -= velX; } // Actualiza la posición del sprite legsSprite->setPosX(getPosX()); legsSprite->setPosY(posY); bodySprite->setPosX(getPosX()); bodySprite->setPosY(posY); headSprite->setPosX(getPosX()); headSprite->setPosY(posY); } else { deathSprite->update(); // Si el cadaver abandona el area de juego por los laterales if ((deathSprite->getPosX() < PLAY_AREA_LEFT) || (deathSprite->getPosX() + width > PLAY_AREA_RIGHT)) { // Restaura su posición const float vx = deathSprite->getVelX(); deathSprite->setPosX(deathSprite->getPosX() - vx); // Rebota deathSprite->setVelX(-vx); } } } // Pinta el jugador en pantalla void Player::render() { if (isAlive()) { if (invulnerable) { if ((invulnerableCounter % 10) > 4) { legsSprite->render(); bodySprite->render(); headSprite->render(); } } else { legsSprite->render(); bodySprite->render(); headSprite->render(); } } else { deathSprite->render(); } } // Establece el estado del jugador cuando camina void Player::setWalkingStatus(Uint8 status) { // Si cambiamos de estado, reiniciamos la animación if (statusWalking != status) { statusWalking = status; // legsSprite->setCurrentFrame(0); } } // Establece el estado del jugador cuando dispara void Player::setFiringStatus(Uint8 status) { // Si cambiamos de estado, reiniciamos la animación if (statusFiring != status) { statusFiring = status; } } // Establece la animación correspondiente al estado 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"; const SDL_RendererFlip flipWalk = statusWalking == PLAYER_STATUS_WALKING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; 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) { // No esta disparando bodySprite->setCurrentAnimation(aWalking + aBodyCoffees); bodySprite->setFlip(flipWalk); headSprite->setCurrentAnimation(aWalking + aHeadCoffees + aPowerUp); headSprite->setFlip(flipWalk); } else { // Está disparando bodySprite->setCurrentAnimation(aFiring + aBodyCoffees); bodySprite->setFlip(flipFire); headSprite->setCurrentAnimation(aFiring + aHeadCoffees + aPowerUp); headSprite->setFlip(flipFire); } // Actualiza las animaciones de los sprites legsSprite->animate(); bodySprite->animate(); headSprite->animate(); } // Obtiene el valor de la variable int Player::getPosX() { return int(posX); } // Obtiene el valor de la variable int Player::getPosY() { return posY; } // Obtiene el valor de la variable int Player::getWidth() { return width; } // Obtiene el valor de la variable int Player::getHeight() { return height; } // Indica si el jugador puede disparar bool Player::canFire() { // Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador if (cooldown > 0) { return false; } else { return true; } } // Establece el valor de la variable void Player::setFireCooldown(int time) { cooldown = time; } // Actualiza el valor de la variable void Player::updateCooldown() { if (cooldown > 0) { cooldown--; if (powerUp) { cooldown--; } } else { setFiringStatus(PLAYER_STATUS_FIRING_NO); } } // Actualiza al jugador a su posicion, animación y controla los contadores void Player::update() { move(); setAnimation(); shiftColliders(); updateCooldown(); updatePowerUpCounter(); updateInvulnerableCounter(); updateDeathCounter(); updatePowerUpHeadOffset(); } // Obtiene la puntuación del jugador Uint32 Player::getScore() { return score; } // Asigna un valor a la puntuación del jugador void Player::setScore(Uint32 score) { this->score = score; } // Incrementa la puntuación del jugador void Player::addScore(Uint32 score) { this->score += score; } // Obtiene el valor de la variable bool Player::isAlive() { return alive; } // Establece el valor de la variable void Player::setAlive(bool value) { alive = value; if (!value) { deathSprite->setPos(headSprite->getRect()); deathSprite->setAccelY(0.2f); deathSprite->setVelY(-6.6f); deathSprite->setVelX(3.3f); if (rand() % 2 == 0) { deathSprite->setVelX(-3.3f); } } } // Obtiene el valor de la variable float Player::getScoreMultiplier() { return scoreMultiplier; } // Establece el valor de la variable void Player::setScoreMultiplier(float value) { scoreMultiplier = 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; } } // Decrementa el valor de la variable hasta un mínimo void Player::decScoreMultiplier() { if (scoreMultiplier > 1.0f) { scoreMultiplier -= 0.1f; } else { scoreMultiplier = 1.0f; } } // Obtiene el valor de la variable bool Player::isInvulnerable() { return invulnerable; } // Establece el valor de la variable void Player::setInvulnerable(bool value) { invulnerable = value; } // Obtiene el valor de la variable Uint16 Player::getInvulnerableCounter() { return invulnerableCounter; } // Establece el valor de la variable void Player::setInvulnerableCounter(Uint16 value) { invulnerableCounter = value; } // Actualiza el valor de la variable void Player::updateInvulnerableCounter() { if (invulnerable) { if (invulnerableCounter > 0) { invulnerableCounter--; } else { invulnerable = false; invulnerableCounter = PLAYER_INVULNERABLE_COUNTER; } } } // Actualiza el valor de la variable void Player::updateDeathCounter() { if (!alive) { if (deathCounter > 0) { deathCounter--; } } } // Obtiene el valor de la variable bool Player::isPowerUp() { return powerUp; } // Establece el valor de la variable void Player::setPowerUp(bool value) { powerUp = value; } // Obtiene el valor de la variable Uint16 Player::getPowerUpCounter() { return powerUpCounter; } // Establece el valor de la variable void Player::setPowerUpCounter(Uint16 value) { powerUpCounter = value; } // Actualiza el valor de la variable void Player::updatePowerUpCounter() { if ((powerUpCounter > 0) && (powerUp)) { powerUpCounter--; } else { powerUp = false; powerUpCounter = PLAYER_POWERUP_COUNTER; } } // Obtiene el valor de la variable bool Player::hasExtraHit() { return extraHit; } // Concede un toque extra al jugador void Player::giveExtraHit() { extraHit = true; coffees++; if (coffees > 2) { coffees = 2; } } // Quita el toque extra al jugador void Player::removeExtraHit() { if (coffees > 0) { coffees--; } if (coffees == 0) { extraHit = false; } invulnerable = true; invulnerableCounter = PLAYER_INVULNERABLE_COUNTER; } // Habilita la entrada de ordenes void Player::enableInput() { input = true; } // Deshabilita la entrada de ordenes void Player::disableInput() { input = false; } // Devuelve el numero de cafes actuales Uint8 Player::getCoffees() { return coffees; } // Obtiene el circulo de colisión circle_t &Player::getCollider() { return collider; } // Actualiza el circulo de colisión a la posición del jugador void Player::shiftColliders() { collider.x = int(posX + (width / 2)); collider.y = int(posY + (height / 2)); } // Obtiene el puntero a la textura con los gráficos de la animación de morir LTexture *Player::getDeadTexture() { return deathSprite->getTexture(); ; } // Obtiene el valor de la variable Uint16 Player::getDeathCounter() { return deathCounter; } // Actualiza el valor de la variable void Player::updatePowerUpHeadOffset() { if (!powerUp) { // powerUpHeadOffset = 0; } else { // powerUpHeadOffset = 96; if (powerUpCounter < 300) { if (powerUpCounter % 10 > 4) { // powerUpHeadOffset = 96; } else { // powerUpHeadOffset = 0; } } } } // Pone las texturas del jugador void Player::setPlayerTextures(std::vector texture) { headSprite->setTexture(texture.at(0)); bodySprite->setTexture(texture.at(1)); legsSprite->setTexture(texture.at(2)); deathSprite->setTexture(texture.at(3)); }