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 "item.h"
#include <algorithm> // para std::clamp
#include <stdlib.h> // para rand #include <stdlib.h> // para rand
#include "animated_sprite.h" // para SpriteAnimated #include "animated_sprite.h" // para SpriteAnimated
#include "param.h" // para param #include "param.h" // para param
class Texture; 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) 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)), : sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
type_(type), 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_); // Actualiza el sprite
sprite_->setPosY(pos_y_); shiftSprite();
shiftColliders(); shiftColliders();
} }
// Centra el objeto en la posición X
void Item::alignTo(int 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_ = x - (width_ / 2);
{
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);
}
// Posición X,Y del sprite // Ajusta para que no quede fuera de la zona de juego
sprite_->setPosX(pos_x_); pos_x_ = std::clamp(pos_x_, min_x, max_x);
sprite_->setPosY(pos_y_);
// Alinea el circulo de colisión con el objeto // Actualiza el sprite
shiftSprite();
shiftColliders(); shiftColliders();
} }
// Pinta el objeto en la pantalla
void Item::render() void Item::render()
{ {
if (enabled_) 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() void Item::move()
{ {
floor_collision_ = false; floor_collision_ = false;
@@ -94,129 +87,90 @@ void Item::move()
vel_x_ += accel_x_; vel_x_ += accel_x_;
vel_y_ += accel_y_; vel_y_ += accel_y_;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido // Comprueba los laterales de la zona de juego
if ((pos_x_ < param.game.play_area.rect.x) || (pos_x_ + width_ > play_area_.w)) const float min_x = param.game.play_area.rect.x;
{ const float max_x = play_area_.w - width_;
// Corregir posición pos_x_ = std::clamp(pos_x_, min_x, max_x);
pos_x_ -= vel_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_; 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)) if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
{ {
// Corrige // Corrige
pos_y_ = param.game.play_area.rect.y; pos_y_ = param.game.play_area.rect.y;
// Invierte el sentido // Invierte la velocidad
vel_y_ = -vel_y_; vel_y_ = -vel_y_;
} }
// Si el objeto se sale por la parte inferior // Si colisiona con la parte inferior
if (pos_y_ + height_ > play_area_.h) if (pos_y_ > play_area_.h - height_)
{ {
// Detiene el objeto // Corrige la posición
vel_y_ = 0;
vel_x_ = 0;
accel_x_ = 0;
accel_y_ = 0;
pos_y_ = play_area_.h - height_; pos_y_ = play_area_.h - height_;
if (type_ == ItemType::COFFEE_MACHINE) 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; 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 // Actualiza la posición del sprite
sprite_->setPosX(int(pos_x_)); shiftSprite();
sprite_->setPosY(int(pos_y_));
shiftColliders(); 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() void Item::update()
{ {
move(); move();
sprite_->update(); sprite_->update();
updateTimeToLive(); updateTimeToLive();
checkTimeToLive();
} }
// Actualiza el contador
void Item::updateTimeToLive() void Item::updateTimeToLive()
{ {
if (time_to_live_ > 0) if (time_to_live_ > 0)
{ {
time_to_live_--; time_to_live_--;
} }
} else
{
// Comprueba si el objeto sigue vivo
void Item::checkTimeToLive()
{
if (time_to_live_ == 0)
disable(); 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() void Item::shiftColliders()
{ {
collider_.x = int(pos_x_ + (width_ / 2)); collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
collider_.y = int(pos_y_ + (height_ / 2)); collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
} }
// Informa si el objeto ha colisionado con el suelo void Item::shiftSprite()
bool Item::isOnFloor()
{ {
return floor_collision_; sprite_->setPosX(pos_x_);
} sprite_->setPosY(pos_y_);
}

View File

@@ -9,93 +9,147 @@
#include "utils.h" // para Circle #include "utils.h" // para Circle
class Texture; 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 enum class ItemType : int
{ {
DISK = 1, DISK = 1, /**< Disco */
GAVINA = 2, GAVINA = 2, /**< Gavina */
PACMAR = 3, PACMAR = 3, /**< Pacman */
CLOCK = 4, CLOCK = 4, /**< Reloj */
COFFEE = 5, COFFEE = 5, /**< Café */
COFFEE_MACHINE = 6, COFFEE_MACHINE = 6,/**< Máquina de café */
NONE = 7, 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 class Item
{ {
private: private:
// Objetos y punteros // 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 // Variables
float pos_x_; // Posición X del objeto float pos_x_; /**< Posición X del objeto */
float pos_y_; // Posición Y del objeto float pos_y_; /**< Posición Y del objeto */
int width_; // Ancho del objeto int width_; /**< Ancho del objeto */
int height_; // Alto del objeto int height_; /**< Alto del objeto */
float vel_x_; // Velocidad en el eje X float vel_x_; /**< Velocidad en el eje X */
float vel_y_; // Velocidad en el eje Y float vel_y_; /**< Velocidad en el eje Y */
float accel_x_ = 0.0f; // Aceleración en el eje X float accel_x_ = 0.0f; /**< Aceleración en el eje X */
float accel_y_; // Aceleración en el eje Y float accel_y_; /**< Aceleración en el eje Y */
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo bool floor_collision_ = false; /**< Indica si el objeto colisiona con el suelo */
ItemType type_; // Especifica el tipo de objeto que es ItemType type_; /**< Especifica el tipo de objeto que es */
bool enabled_ = true; // Especifica si el objeto está habilitado bool enabled_ = true; /**< Especifica si el objeto está habilitado */
Circle collider_; // Circulo de colisión del objeto Circle collider_; /**< Círculo de colisión del objeto */
SDL_Rect play_area_; // Rectangulo con la zona de juego 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 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(); 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(); 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(); void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
public: 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); 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; ~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); 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(); 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(); 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(); void update();
// Obtiene del valor de la variable // Getters
float getPosX(); float getPosX() const { return pos_x_; }
float getPosY() const { return pos_y_; }
// Obtiene del valor de la variable int getWidth() const { return width_; }
float getPosY(); int getHeight() const { return height_; }
ItemType getType() const { return type_; }
// Obtiene del valor de la variable bool isEnabled() const { return enabled_; }
int getWidth(); bool isOnFloor() const { return floor_collision_; }
Circle &getCollider() { return collider_; }
// 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();
};

View File

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