101 lines
3.4 KiB
C++
101 lines
3.4 KiB
C++
// bullet.cpp - Implementación de projectils de la ship
|
|
// © 2026 JailDesigner
|
|
|
|
#include "game/entities/bullet.hpp"
|
|
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
|
|
#include "core/audio/audio.hpp"
|
|
#include "core/defaults.hpp"
|
|
#include "core/entities/entity.hpp"
|
|
#include "core/graphics/shape_loader.hpp"
|
|
#include "core/rendering/shape_renderer.hpp"
|
|
#include "core/types.hpp"
|
|
#include "game/constants.hpp"
|
|
#include "game/entities/bullet_config.hpp"
|
|
#include "game/entities/bullet_registry.hpp"
|
|
|
|
Bullet::Bullet(Rendering::Renderer* renderer)
|
|
: Entity(renderer),
|
|
config_(&BulletRegistry::get()) {
|
|
brightness_ = Defaults::Brightness::BALA;
|
|
|
|
// Cinemàtiques pures: no col·lisionen al PhysicsWorld (body_.radius = 0).
|
|
// El gameplay (GameScene) gestiona els hits via checkCollisionSwept i la
|
|
// sortida del PLAYAREA.
|
|
body_.setMass(config_->physics.mass);
|
|
body_.radius = 0.0F;
|
|
body_.restitution = config_->physics.restitution;
|
|
body_.linear_damping = config_->physics.linear_damping;
|
|
body_.angular_damping = config_->physics.angular_damping;
|
|
|
|
shape_ = Graphics::ShapeLoader::load(config_->shape.path);
|
|
if (!shape_ || !shape_->isValid()) {
|
|
std::cerr << "[Bullet] Error: no s'ha pogut carregar " << config_->shape.path << '\n';
|
|
}
|
|
|
|
// Radi de col·lisió derivat del cercle circumscrit de la shape.
|
|
const float BOUNDING = (shape_ != nullptr) ? shape_->getBoundingRadius() : 0.0F;
|
|
collision_radius_ = BOUNDING * config_->shape.scale * config_->shape.collision_factor;
|
|
}
|
|
|
|
void Bullet::init() {
|
|
is_active_ = false;
|
|
center_ = {.x = 0.0F, .y = 0.0F};
|
|
prev_position_ = {.x = 0.0F, .y = 0.0F};
|
|
angle_ = 0.0F;
|
|
|
|
body_.position = Vec2{};
|
|
body_.velocity = Vec2{};
|
|
body_.angle = 0.0F;
|
|
body_.angular_velocity = 0.0F;
|
|
body_.clearAccumulators();
|
|
}
|
|
|
|
void Bullet::fire(const Vec2& position, float angle, uint8_t owner_id, float bullet_speed) {
|
|
is_active_ = true;
|
|
owner_id_ = owner_id;
|
|
|
|
center_ = position;
|
|
prev_position_ = position; // spawn: swept degenera a punt-cercle
|
|
angle_ = angle;
|
|
|
|
// Sincronizar el body físic: posició + velocitat cartesiana.
|
|
// angle - PI/2 perquè angle=0 apunta cap amunt (eje Y negatiu SDL).
|
|
body_.position = position;
|
|
body_.angle = angle;
|
|
const float DIR_X = std::cos(angle - (Constants::PI / 2.0F));
|
|
const float DIR_Y = std::sin(angle - (Constants::PI / 2.0F));
|
|
body_.velocity = Vec2{.x = DIR_X * bullet_speed, .y = DIR_Y * bullet_speed};
|
|
body_.angular_velocity = 0.0F;
|
|
body_.clearAccumulators();
|
|
|
|
Audio::get()->playSound(Defaults::Sound::LASER, Audio::Group::GAME);
|
|
}
|
|
|
|
void Bullet::update(float /*delta_time*/) {
|
|
// No-op: la desactivació per fora-de-zone viu a
|
|
// Systems::Collision::desactivateOutOfBoundsBullets() perquè així té accés
|
|
// al DebrisManager i pot generar el "trencament" visual de la bala alhora.
|
|
// El moviment l'integra PhysicsWorld; postUpdate sincronitza center_ i prev_position_.
|
|
}
|
|
|
|
void Bullet::postUpdate(float /*delta_time*/) {
|
|
prev_position_ = center_;
|
|
center_ = body_.position;
|
|
}
|
|
|
|
void Bullet::desactivar() {
|
|
is_active_ = false;
|
|
body_.velocity = Vec2{};
|
|
body_.angular_velocity = 0.0F;
|
|
}
|
|
|
|
void Bullet::draw() const {
|
|
if (is_active_ && shape_) {
|
|
Rendering::renderShape(renderer_, shape_, center_, angle_, 1.0F, 1.0F, brightness_, config_->colors.normal);
|
|
}
|
|
}
|