175 lines
3.4 KiB
C++
175 lines
3.4 KiB
C++
#include "item.h"
|
|
#include <stdlib.h> // Para rand
|
|
#include <algorithm> // Para clamp
|
|
#include "animated_sprite.h" // Para AnimatedSprite
|
|
#include "param.h" // Para Param, ParamGame, param
|
|
class Texture; // lines 6-6
|
|
|
|
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),
|
|
play_area_(play_area)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ItemType::COFFEE_MACHINE:
|
|
{
|
|
width_ = 28;
|
|
height_ = 37;
|
|
pos_x_ = ((static_cast<int>(x) + (play_area.w / 2)) % (play_area.w - width_ - 5)) + 2;
|
|
pos_y_ = -height_;
|
|
vel_x_ = 0.0f;
|
|
vel_y_ = -0.1f;
|
|
accel_y_ = 0.1f;
|
|
collider_.r = 10;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
width_ = 20;
|
|
height_ = 20;
|
|
pos_x_ = x;
|
|
pos_y_ = y;
|
|
vel_x_ = -1.0f + ((rand() % 5) * 0.5f);
|
|
vel_y_ = -4.0f;
|
|
accel_y_ = 0.2f;
|
|
collider_.r = width_ / 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Actualiza el sprite
|
|
shiftSprite();
|
|
shiftColliders();
|
|
}
|
|
|
|
void Item::alignTo(int x)
|
|
{
|
|
const float min_x = param.game.play_area.rect.x + 1;
|
|
const float max_x = play_area_.w - width_ - 1;
|
|
|
|
pos_x_ = x - (width_ / 2);
|
|
|
|
// Ajusta para que no quede fuera de la zona de juego
|
|
pos_x_ = std::clamp(pos_x_, min_x, max_x);
|
|
|
|
// Actualiza el sprite
|
|
shiftSprite();
|
|
shiftColliders();
|
|
}
|
|
|
|
void Item::render()
|
|
{
|
|
if (enabled_)
|
|
{
|
|
if (time_to_live_ > 200)
|
|
{
|
|
sprite_->render();
|
|
}
|
|
else if (time_to_live_ % 20 > 10)
|
|
{
|
|
sprite_->render();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Item::move()
|
|
{
|
|
floor_collision_ = false;
|
|
|
|
// Calcula la nueva posición
|
|
pos_x_ += vel_x_;
|
|
pos_y_ += vel_y_;
|
|
|
|
// Aplica las aceleraciones a la velocidad
|
|
vel_x_ += accel_x_;
|
|
vel_y_ += accel_y_;
|
|
|
|
// 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);
|
|
|
|
// Si toca el borde lateral, invierte la velocidad horizontal
|
|
if (pos_x_ == min_x || pos_x_ == max_x)
|
|
{
|
|
vel_x_ = -vel_x_;
|
|
}
|
|
|
|
// 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 la velocidad
|
|
vel_y_ = -vel_y_;
|
|
}
|
|
|
|
// Si colisiona con la parte inferior
|
|
if (pos_y_ > play_area_.h - height_)
|
|
{
|
|
// 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
|
|
shiftSprite();
|
|
shiftColliders();
|
|
}
|
|
|
|
void Item::disable() { enabled_ = false; }
|
|
|
|
void Item::update()
|
|
{
|
|
move();
|
|
sprite_->update();
|
|
updateTimeToLive();
|
|
}
|
|
|
|
void Item::updateTimeToLive()
|
|
{
|
|
if (time_to_live_ > 0)
|
|
{
|
|
time_to_live_--;
|
|
}
|
|
else
|
|
{
|
|
disable();
|
|
}
|
|
}
|
|
|
|
void Item::shiftColliders()
|
|
{
|
|
collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
|
|
collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
|
|
}
|
|
|
|
void Item::shiftSprite()
|
|
{
|
|
sprite_->setPosX(pos_x_);
|
|
sprite_->setPosY(pos_y_);
|
|
}
|