Els items reboten al tocar el piso

This commit is contained in:
2024-11-20 21:55:55 +01:00
parent 77bf1d73b3
commit 8941072357
3 changed files with 168 additions and 160 deletions

View File

@@ -1,10 +1,10 @@
#include "item.h"
#include <algorithm> // para std::clamp
#include <stdlib.h> // para rand
#include "animated_sprite.h" // para SpriteAnimated
#include "param.h" // para param
class Texture;
// Constructor
Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
type_(type),
@@ -38,34 +38,26 @@ Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr
}
}
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
// Actualiza el sprite
shiftSprite();
shiftColliders();
}
// Centra el objeto en la posición X
void Item::alignTo(int x)
{
pos_x_ = static_cast<float>(x - (width_ / 2));
const float min_x = param.game.play_area.rect.x + 1;
const float max_x = play_area_.w - width_ - 1;
if (pos_x_ < param.game.play_area.rect.x)
{
pos_x_ = param.game.play_area.rect.x + 1;
}
else if (pos_x_ + width_ > play_area_.w)
{
pos_x_ = static_cast<float>(play_area_.w - width_ - 1);
}
pos_x_ = x - (width_ / 2);
// Posición X,Y del sprite
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
// Ajusta para que no quede fuera de la zona de juego
pos_x_ = std::clamp(pos_x_, min_x, max_x);
// Alinea el circulo de colisión con el objeto
// Actualiza el sprite
shiftSprite();
shiftColliders();
}
// Pinta el objeto en la pantalla
void Item::render()
{
if (enabled_)
@@ -81,7 +73,8 @@ void Item::render()
}
}
// Actualiza la posición y estados del objeto
#include <algorithm> // Necesario para std::clamp
void Item::move()
{
floor_collision_ = false;
@@ -94,129 +87,90 @@ void Item::move()
vel_x_ += accel_x_;
vel_y_ += accel_y_;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((pos_x_ < param.game.play_area.rect.x) || (pos_x_ + width_ > play_area_.w))
{
// Corregir posición
pos_x_ -= vel_x_;
// Comprueba los laterales de la zona de juego
const float min_x = param.game.play_area.rect.x;
const float max_x = play_area_.w - width_;
pos_x_ = std::clamp(pos_x_, min_x, max_x);
// Invertir sentido
// Si toca el borde lateral, invierte la velocidad horizontal
if (pos_x_ == min_x || pos_x_ == max_x)
{
vel_x_ = -vel_x_;
}
// Si se sale por arriba rebota (excepto la maquina de café)
// Si colisiona por arriba, rebota (excepto la máquina de café)
if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
{
// Corrige
pos_y_ = param.game.play_area.rect.y;
// Invierte el sentido
// Invierte la velocidad
vel_y_ = -vel_y_;
}
// Si el objeto se sale por la parte inferior
if (pos_y_ + height_ > play_area_.h)
// Si colisiona con la parte inferior
if (pos_y_ > play_area_.h - height_)
{
// Detiene el objeto
vel_y_ = 0;
vel_x_ = 0;
accel_x_ = 0;
accel_y_ = 0;
// Corrige la posición
pos_y_ = play_area_.h - height_;
if (type_ == ItemType::COFFEE_MACHINE)
{
// Si es una máquina de café, detiene el objeto
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
floor_collision_ = true;
}
else
{
// Si no es una máquina de café
if (vel_y_ < 1.0f)
{
// Si la velocidad vertical es baja, detiene el objeto
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
}
else
{
// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
vel_y_ *= -0.5f;
vel_x_ *= 0.75f;
}
}
}
// Actualiza la posición del sprite
sprite_->setPosX(int(pos_x_));
sprite_->setPosY(int(pos_y_));
shiftSprite();
shiftColliders();
}
// Pone a cero todos los valores del objeto
void Item::disable()
{
enabled_ = false;
}
void Item::disable() { enabled_ = false; }
// Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update()
{
move();
sprite_->update();
updateTimeToLive();
checkTimeToLive();
}
// Actualiza el contador
void Item::updateTimeToLive()
{
if (time_to_live_ > 0)
{
time_to_live_--;
}
}
// Comprueba si el objeto sigue vivo
void Item::checkTimeToLive()
{
if (time_to_live_ == 0)
else
{
disable();
}
}
// Obtiene del valor de la variable
float Item::getPosX()
{
return pos_x_;
}
// Obtiene del valor de la variable
float Item::getPosY()
{
return pos_y_;
}
// Obtiene del valor de la variable
int Item::getWidth()
{
return width_;
}
// Obtiene del valor de la variable
int Item::getHeight()
{
return height_;
}
// Obtiene del valor de la variable
ItemType Item::getType()
{
return type_;
}
// Obtiene el valor de la variable
bool Item::isEnabled()
{
return enabled_;
}
// Obtiene el circulo de colisión
Circle &Item::getCollider()
{
return collider_;
}
// Alinea el circulo de colisión con la posición del objeto
void Item::shiftColliders()
{
collider_.x = int(pos_x_ + (width_ / 2));
collider_.y = int(pos_y_ + (height_ / 2));
collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
}
// Informa si el objeto ha colisionado con el suelo
bool Item::isOnFloor()
void Item::shiftSprite()
{
return floor_collision_;
}
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
}

View File

@@ -9,93 +9,147 @@
#include "utils.h" // para Circle
class Texture;
// Tipos de objetos
/**
* @brief Tipos de objetos disponibles en el juego.
*
* Esta enumeración define los diferentes tipos de objetos que pueden existir en el juego,
* cada uno con un identificador único.
*/
enum class ItemType : int
{
DISK = 1,
GAVINA = 2,
PACMAR = 3,
CLOCK = 4,
COFFEE = 5,
COFFEE_MACHINE = 6,
NONE = 7,
DISK = 1, /**< Disco */
GAVINA = 2, /**< Gavina */
PACMAR = 3, /**< Pacman */
CLOCK = 4, /**< Reloj */
COFFEE = 5, /**< Café */
COFFEE_MACHINE = 6,/**< Máquina de café */
NONE = 7, /**< Ninguno */
};
// Clase Item
/**
* @brief Clase Item.
*
* Esta clase representa un objeto en el juego, con sus propiedades y métodos para gestionar su comportamiento.
*/
class Item
{
private:
// Objetos y punteros
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los graficos del objeto
std::unique_ptr<AnimatedSprite> sprite_; /**< Sprite con los gráficos del objeto */
// Variables
float pos_x_; // Posición X del objeto
float pos_y_; // Posición Y del objeto
int width_; // Ancho del objeto
int height_; // Alto del objeto
float vel_x_; // Velocidad en el eje X
float vel_y_; // Velocidad en el eje Y
float accel_x_ = 0.0f; // Aceleración en el eje X
float accel_y_; // Aceleración en el eje Y
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
ItemType type_; // Especifica el tipo de objeto que es
bool enabled_ = true; // Especifica si el objeto está habilitado
Circle collider_; // Circulo de colisión del objeto
SDL_Rect play_area_; // Rectangulo con la zona de juego
Uint16 time_to_live_ = 600; // Temporizador con el tiempo que el objeto está presente
float pos_x_; /**< Posición X del objeto */
float pos_y_; /**< Posición Y del objeto */
int width_; /**< Ancho del objeto */
int height_; /**< Alto del objeto */
float vel_x_; /**< Velocidad en el eje X */
float vel_y_; /**< Velocidad en el eje Y */
float accel_x_ = 0.0f; /**< Aceleración en el eje X */
float accel_y_; /**< Aceleración en el eje Y */
bool floor_collision_ = false; /**< Indica si el objeto colisiona con el suelo */
ItemType type_; /**< Especifica el tipo de objeto que es */
bool enabled_ = true; /**< Especifica si el objeto está habilitado */
Circle collider_; /**< Círculo de colisión del objeto */
SDL_Rect play_area_; /**< Rectángulo con la zona de juego */
Uint16 time_to_live_ = 600; /**< Temporizador con el tiempo que el objeto está presente */
// Alinea el circulo de colisión con la posición del objeto
/**
* @brief Alinea el círculo de colisión con la posición del objeto.
*
* Esta función ajusta la posición del círculo de colisión para que coincida con la posición del objeto.
* Actualiza las coordenadas X e Y del colisionador basándose en las coordenadas del objeto.
*/
void shiftColliders();
// Actualiza la posición y estados del objeto
/**
* @brief Coloca el sprite en la posición del objeto.
*
* Esta función ajusta la posición del sprite para que coincida con la posición del objeto.
* Actualiza las coordenadas X e Y del sprite basándose en las coordenadas del objeto.
*/
void shiftSprite();
/**
* @brief Actualiza la posición y estados del objeto.
*
* Esta función actualiza la posición del objeto basándose en su velocidad y aceleración.
* Controla las colisiones con los límites del área de juego, ajustando la posición y la velocidad en consecuencia.
* También actualiza la posición del sprite y el colisionador del objeto.
*/
void move();
// Actualiza el contador
/**
* @brief Actualiza el contador de tiempo de vida del objeto.
*
* Esta función decrementa el contador de tiempo de vida del objeto.
* Si el tiempo de vida es mayor a 0, se decrementa en 1.
* Si el tiempo de vida es 0 o menos, se desactiva el objeto llamando a la función `disable()`.
*/
void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
public:
// Constructor
/**
* @brief Constructor de la clase Item.
*
* Este constructor inicializa un objeto Item con el tipo especificado, posición inicial, área de juego, textura y animación.
*
* @param type El tipo de objeto (ItemType).
* @param x La posición X inicial del objeto.
* @param y La posición Y inicial del objeto.
* @param play_area El área de juego donde el objeto se moverá.
* @param texture La textura del objeto.
* @param animation La animación asociada al objeto.
*/
Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Destructor
/**
* @brief Destructor de la clase Item.
*
* Este destructor libera los recursos asociados con el objeto Item.
*/
~Item() = default;
// Centra el objeto en la posición X
/**
* @brief Centra el objeto en la posición X.
*
* Esta función ajusta la posición X del objeto para que esté centrado en la posición X especificada.
* Además, asegura que el objeto no se salga de los límites del área de juego.
*
* @param x La posición X en la que se desea centrar el objeto.
*/
void alignTo(int x);
// Pinta el objeto en la pantalla
/**
* @brief Pinta el objeto en la pantalla.
*
* Esta función renderiza el objeto en la pantalla si está habilitado.
* Si el tiempo de vida (`time_to_live_`) es mayor que 200, renderiza el sprite.
* Si el tiempo de vida es menor o igual a 200, renderiza el sprite de forma intermitente, basándose en un cálculo de módulo.
*/
void render();
// Pone a cero todos los valores del objeto
/**
* @brief Pone a cero todos los valores del objeto.
*
* Esta función desactiva el objeto estableciendo su estado `enabled_` a `false`.
*/
void disable();
// Actualiza al objeto a su posicion, animación y controla los contadores
/**
* @brief Actualiza el objeto a su posición, animación y controla los contadores.
*
* Esta función mueve el objeto, actualiza su animación y controla el contador de tiempo de vida.
* Llama a las funciones `move()`, `sprite_->update()` y `updateTimeToLive()`.
*/
void update();
// Obtiene del valor de la variable
float getPosX();
// Obtiene del valor de la variable
float getPosY();
// Obtiene del valor de la variable
int getWidth();
// Obtiene del valor de la variable
int getHeight();
// Obtiene del valor de la variable
ItemType getType();
// Obtiene el valor de la variable
bool isEnabled();
// Obtiene el circulo de colisión
Circle &getCollider();
// Informa si el objeto ha colisionado con el suelo
bool isOnFloor();
};
// Getters
float getPosX() const { return pos_x_; }
float getPosY() const { return pos_y_; }
int getWidth() const { return width_; }
int getHeight() const { return height_; }
ItemType getType() const { return type_; }
bool isEnabled() const { return enabled_; }
bool isOnFloor() const { return floor_collision_; }
Circle &getCollider() { return collider_; }
};

View File

@@ -54,7 +54,7 @@ void Player::init()
shiftColliders();
vel_x_ = 0;
vel_y_ = 0;
score_ = 999999;
score_ = 0;
score_multiplier_ = 1.0f;
cooldown_ = 10;
enter_name_->init();