#include "const.h" #include "player.h" // Constructor Player::Player(float x, int y, std::vector texture, std::vector *> animations) { // Reserva memoria para los objetos playerSprite = new AnimatedSprite(texture[0], "", animations[0]); powerSprite = new AnimatedSprite(texture[1], "", animations[1]); powerSprite->getTexture()->setAlpha(224); // Establece la posición inicial del jugador defaultPosX = posX = x; defaultPosY = posY = y; // Establece los offsets para el sprite de PowerUp powerUpDespX = (powerSprite->getWidth() - playerSprite->getWidth()) / 2; powerSprite->setPosY(y - (powerSprite->getHeight() - playerSprite->getHeight())); // Inicializa variables // enabled = false; statusPlaying = PLAYER_STATUS_WAITING; scoreBoardPanel = 0; name = ""; init(); } // Destructor Player::~Player() { delete playerSprite; delete powerSprite; } // Iniciador void Player::init() { // Inicializa variables de estado posX = defaultPosX; posY = defaultPosY; statusPlaying = PLAYER_STATUS_PLAYING; statusWalking = PLAYER_STATUS_WALKING_STOP; statusFiring = PLAYER_STATUS_FIRING_NO; invulnerable = true; invulnerableCounter = PLAYER_INVULNERABLE_COUNTER; powerUp = false; powerUpCounter = PLAYER_POWERUP_COUNTER; extraHit = false; coffees = 0; input = true; continueTicks = 0; continueCounter = 9; width = 30; height = 30; collider.r = 9; shiftColliders(); velX = 0; velY = 0; baseSpeed = 1.5; score = 0; scoreMultiplier = 1.0f; cooldown = 10; // Establece la posición del sprite playerSprite->setPosX(posX); playerSprite->setPosY(posY); // Selecciona un frame para pintar playerSprite->setCurrentAnimation("stand"); } // Actua en consecuencia de la entrada recibida void Player::setInput(int 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_fire_center: setFiringStatus(PLAYER_STATUS_FIRING_UP); break; case input_fire_left: setFiringStatus(PLAYER_STATUS_FIRING_LEFT); break; case input_fire_right: 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 (isPlaying()) { // 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 playerSprite->setPosX(getPosX()); playerSprite->setPosY(posY); powerSprite->setPosX(getPosX() - powerUpDespX); } else { playerSprite->update(); // Si el cadaver abandona el area de juego por los laterales if ((playerSprite->getPosX() < PLAY_AREA_LEFT) || (playerSprite->getPosX() + width > PLAY_AREA_RIGHT)) { // Restaura su posición const float vx = playerSprite->getVelX(); playerSprite->setPosX(playerSprite->getPosX() - vx); // Rebota playerSprite->setVelX(-vx); } } } // Pinta el jugador en pantalla void Player::render() { if (powerUp && isPlaying()) { if (powerUpCounter > (PLAYER_POWERUP_COUNTER / 4) || powerUpCounter % 20 > 4) { powerSprite->render(); } } playerSprite->render(); } // Establece el estado del jugador cuando camina void Player::setWalkingStatus(int status) { // Si cambiamos de estado, reiniciamos la animación if (statusWalking != status) { statusWalking = status; } } // Establece el estado del jugador cuando dispara void Player::setFiringStatus(int 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 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 if (isPlaying()) { 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 { playerSprite->setCurrentAnimation("death"); } // Actualiza las animaciones de los sprites playerSprite->animate(); // powerSprite->setFlip(flipWalk); powerSprite->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 return cooldown > 0 ? false : 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(); updateInvulnerable(); updateContinueCounter(); } // Obtiene la puntuación del jugador int 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) { if (isPlaying()) { this->score += score; } } // Indica si el jugador está jugando bool Player::isPlaying() { return statusPlaying == PLAYER_STATUS_PLAYING; } // Indica si el jugador está continuando bool Player::isContinue() { return statusPlaying == PLAYER_STATUS_CONTINUE; } // Indica si el jugador está esperando bool Player::isWaiting() { return statusPlaying == PLAYER_STATUS_WAITING; } // Establece el estado del jugador en el juego void Player::setStatusPlaying(int value) { statusPlaying = value; switch (statusPlaying) { case PLAYER_STATUS_PLAYING: init(); break; case PLAYER_STATUS_CONTINUE: // Activa la animación de morir playerSprite->setAccelY(0.2f); playerSprite->setVelY(-6.6f); rand() % 2 == 0 ? playerSprite->setVelX(3.3f) : playerSprite->setVelX(-3.3f); // Inicializa el contador de continuar continueTicks = SDL_GetTicks(); continueCounter = 9; break; case PLAYER_STATUS_WAITING: break; default: break; } } // Obtiene el estado del jugador en el juego int Player::getStatusPlaying() { return statusPlaying; } // 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() { scoreMultiplier += 0.1f; scoreMultiplier = std::min(scoreMultiplier, 5.0f); } // Decrementa el valor de la variable hasta un mínimo void Player::decScoreMultiplier() { scoreMultiplier -= 0.1f; scoreMultiplier = std::max(scoreMultiplier, 1.0f); } // Obtiene el valor de la variable bool Player::isInvulnerable() { return invulnerable; } // Establece el valor del estado void Player::setInvulnerable(bool value) { invulnerable = value; invulnerableCounter = invulnerable ? PLAYER_INVULNERABLE_COUNTER : 0; } // Obtiene el valor de la variable int Player::getInvulnerableCounter() { return invulnerableCounter; } // Establece el valor de la variable void Player::setInvulnerableCounter(int value) { invulnerableCounter = value; } // Monitoriza el estado void Player::updateInvulnerable() { if (invulnerable) { if (invulnerableCounter > 0) { invulnerableCounter--; invulnerableCounter % 8 > 3 ? playerSprite->getTexture()->setPalette(coffees) : playerSprite->getTexture()->setPalette(3); } else { setInvulnerable(false); playerSprite->getTexture()->setPalette(coffees); } } } // Obtiene el valor de la variable bool Player::isPowerUp() { return powerUp; } // Establece el valor de la variable void Player::setPowerUp() { powerUp = true; powerUpCounter = PLAYER_POWERUP_COUNTER; } // Obtiene el valor de la variable int Player::getPowerUpCounter() { return powerUpCounter; } // Establece el valor de la variable void Player::setPowerUpCounter(int 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; if (coffees < 2) { coffees++; playerSprite->getTexture()->setPalette(coffees); } } // Quita el toque extra al jugador void Player::removeExtraHit() { if (coffees > 0) { coffees--; setInvulnerable(true); playerSprite->getTexture()->setPalette(coffees); } extraHit = coffees == 0 ? false : true; } // Habilita la entrada de ordenes void Player::enableInput() { input = true; } // Deshabilita la entrada de ordenes void Player::disableInput() { input = false; } // Devuelve el número de cafes actuales int 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)); } // Pone las texturas del jugador void Player::setPlayerTextures(std::vector texture) { playerSprite->setTexture(texture[0]); powerSprite->setTexture(texture[1]); } // Obtiene el valor de la variable int Player::getContinueCounter() { return continueCounter; } // Actualiza el contador de continue void Player::updateContinueCounter() { if (statusPlaying == PLAYER_STATUS_CONTINUE) { const Uint32 ticksSpeed = 1000; if (SDL_GetTicks() - continueTicks > ticksSpeed) { decContinueCounter(); } } } // Le asigna un panel en el marcador al jugador void Player::setScoreBoardPanel(int panel) { scoreBoardPanel = panel; } // Obtiene el valor de la variable int Player::getScoreBoardPanel() { return scoreBoardPanel; } // Decrementa el contador de continuar void Player::decContinueCounter() { continueTicks = SDL_GetTicks(); continueCounter--; if (continueCounter < 0) { setStatusPlaying(PLAYER_STATUS_WAITING); } } // Establece el nombre del jugador void Player::setName(std::string name) { this->name = name; } // Obtiene el nombre del jugador std::string Player::getName() { return name; }