b746578bc8
Sustituye en bloque las cabeceras de los archivos por una sola línea de copyright. Cero rastro de "Visente", "Sergi" o "1999" en el árbol del proyecto. Se eliminan también las variantes "© 2025 Port a C++20", "© 2025 Port a C++20 con SDL3" y "© 2025 Orni Attack" (con todas sus colas descriptivas como "Arquitectura de entidades" o "Sistema de física"), que en este punto eran ruido histórico. Aplicado con un par de sed (find -type f, excluyendo source/external y source/legacy): 1. \|^// © 1999 Visente i Sergi (versión Pascal)$|d 2. s|^// © 2025 (Port a C++20.*|Orni Attack.*)$|// © 2026 JailDesigner| Verificado: la única variante de cabecera tras el sweep es "// © 2026 JailDesigner". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
76 lines
2.9 KiB
C++
76 lines
2.9 KiB
C++
// rigid_body.hpp - Cuerpo rígido 2D para el sistema de física
|
|
// © 2026 JailDesigner
|
|
//
|
|
// Estructura POD-like que encapsula el estado físico de una entidad:
|
|
// posición, velocidad lineal/angular, masa, restitución y damping.
|
|
// El integrador es semi-implícito de Euler (estable para juegos arcade).
|
|
//
|
|
// Convenciones:
|
|
// - position: coordenadas lógicas (px), donde la entidad está en el mundo
|
|
// - angle: radianes; 0 apunta hacia arriba (eje Y negativo en SDL)
|
|
// - velocity: px/s en cartesianas (NO polares — adiós a cos/sin por entidad)
|
|
// - mass = 0 (inverse_mass = 0) representa un cuerpo estático (masa infinita)
|
|
// - restitution 0 = inelástico, 1 = elástico perfecto
|
|
// - linear_damping en s⁻¹ (fricción exponencial: v *= exp(-damping * dt))
|
|
|
|
#pragma once
|
|
|
|
#include "core/types.hpp"
|
|
|
|
namespace Physics {
|
|
|
|
struct RigidBody {
|
|
// --- Estado cinemático ---
|
|
Vec2 position{}; // Posición del centro (px)
|
|
Vec2 velocity{}; // Velocidad lineal (px/s)
|
|
float angle{0.0F}; // Orientación (rad)
|
|
float angular_velocity{0.0F}; // Velocidad angular (rad/s)
|
|
|
|
// --- Propiedades físicas ---
|
|
float mass{1.0F}; // Masa (kg, escala libre)
|
|
float inverse_mass{1.0F}; // 1/mass cacheado (0 = estático)
|
|
float restitution{0.5F}; // Elasticidad (0..1)
|
|
float linear_damping{0.0F}; // Fricción lineal (s⁻¹)
|
|
float angular_damping{0.0F}; // Fricción angular (s⁻¹)
|
|
float radius{0.0F}; // Radio de colisión (círculo)
|
|
|
|
// --- Fuerzas acumuladas (reseteadas tras cada integrate) ---
|
|
Vec2 force_accumulator{};
|
|
float torque_accumulator{0.0F};
|
|
|
|
// Configura la masa y precalcula inverse_mass.
|
|
// mass <= 0 marca el cuerpo como estático (inmovible por impulsos).
|
|
void setMass(float new_mass) {
|
|
mass = new_mass;
|
|
inverse_mass = (new_mass > 0.0F) ? 1.0F / new_mass : 0.0F;
|
|
}
|
|
|
|
// Marca el cuerpo como estático (paredes, obstáculos fijos).
|
|
void setStatic() {
|
|
mass = 0.0F;
|
|
inverse_mass = 0.0F;
|
|
velocity = Vec2{};
|
|
angular_velocity = 0.0F;
|
|
}
|
|
|
|
[[nodiscard]] auto isStatic() const -> bool { return inverse_mass == 0.0F; }
|
|
|
|
// Aplica una fuerza instantánea (acumulada para el siguiente integrate).
|
|
void applyForce(const Vec2& force) { force_accumulator += force; }
|
|
|
|
// Aplica un impulso (cambio inmediato de velocidad: Δv = J / m).
|
|
void applyImpulse(const Vec2& impulse) {
|
|
if (!isStatic()) {
|
|
velocity += impulse * inverse_mass;
|
|
}
|
|
}
|
|
|
|
// Resetea los acumuladores tras la integración.
|
|
void clearAccumulators() {
|
|
force_accumulator = Vec2{};
|
|
torque_accumulator = 0.0F;
|
|
}
|
|
};
|
|
|
|
} // namespace Physics
|