use crate::math::{Position, Size, Color};
use std::collections::HashMap;
pub type EntityId = u32;
pub trait Component: std::fmt::Debug + 'static {}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Transform {
pub position: Position,
pub rotation: f32,
pub scale: Size,
}
impl Transform {
pub fn new(position: Position) -> Self {
Self {
position,
rotation: 0.0,
scale: Size::new(1.0, 1.0),
}
}
pub fn with_scale(mut self, scale: Size) -> Self {
self.scale = scale;
self
}
pub fn with_rotation(mut self, rotation: f32) -> Self {
self.rotation = rotation;
self
}
}
impl Component for Transform {}
#[derive(Debug, Clone, PartialEq)]
pub struct Sprite {
pub color: Color,
pub size: Size,
pub visible: bool,
}
impl Sprite {
pub fn new(color: Color, size: Size) -> Self {
Self {
color,
size,
visible: true,
}
}
pub fn colored_square(color: Color, size: f32) -> Self {
Self::new(color, Size::new(size, size))
}
pub fn white_square(size: f32) -> Self {
Self::colored_square(Color::WHITE, size)
}
}
impl Component for Sprite {}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Velocity {
pub velocity: Position,
}
impl Velocity {
pub fn new(x: f32, y: f32) -> Self {
Self {
velocity: Position::new(x, y),
}
}
pub fn zero() -> Self {
Self::new(0.0, 0.0)
}
}
impl Component for Velocity {}
#[derive(Debug)]
pub struct EntityManager {
next_id: EntityId,
entities: Vec<EntityId>,
transforms: HashMap<EntityId, Transform>,
sprites: HashMap<EntityId, Sprite>,
velocities: HashMap<EntityId, Velocity>,
}
impl EntityManager {
pub fn new() -> Self {
Self {
next_id: 1,
entities: Vec::new(),
transforms: HashMap::new(),
sprites: HashMap::new(),
velocities: HashMap::new(),
}
}
pub fn create_entity(&mut self) -> EntityId {
let id = self.next_id;
self.next_id += 1;
self.entities.push(id);
id
}
pub fn remove_entity(&mut self, id: EntityId) {
self.entities.retain(|&e| e != id);
self.transforms.remove(&id);
self.sprites.remove(&id);
self.velocities.remove(&id);
}
pub fn add_transform(&mut self, id: EntityId, transform: Transform) {
self.transforms.insert(id, transform);
}
pub fn add_sprite(&mut self, id: EntityId, sprite: Sprite) {
self.sprites.insert(id, sprite);
}
pub fn add_velocity(&mut self, id: EntityId, velocity: Velocity) {
self.velocities.insert(id, velocity);
}
pub fn get_transform_mut(&mut self, id: EntityId) -> Option<&mut Transform> {
self.transforms.get_mut(&id)
}
pub fn get_transform(&self, id: EntityId) -> Option<&Transform> {
self.transforms.get(&id)
}
pub fn get_sprite(&self, id: EntityId) -> Option<&Sprite> {
self.sprites.get(&id)
}
pub fn get_velocity_mut(&mut self, id: EntityId) -> Option<&mut Velocity> {
self.velocities.get_mut(&id)
}
pub fn get_velocity(&self, id: EntityId) -> Option<&Velocity> {
self.velocities.get(&id)
}
pub fn get_renderable_entities(&self) -> Vec<(EntityId, &Transform, &Sprite)> {
let mut result = Vec::new();
for &id in &self.entities {
if let (Some(transform), Some(sprite)) = (self.transforms.get(&id), self.sprites.get(&id)) {
if sprite.visible {
result.push((id, transform, sprite));
}
}
}
result
}
pub fn update_physics(&mut self, delta_time: f32) {
let entity_ids: Vec<EntityId> = self.entities.clone();
for id in entity_ids {
if let (Some(velocity), Some(transform)) = (
self.velocities.get(&id),
self.transforms.get_mut(&id)
) {
transform.position += velocity.velocity * delta_time;
}
}
}
pub fn entities(&self) -> &[EntityId] {
&self.entities
}
}
impl Default for EntityManager {
fn default() -> Self {
Self::new()
}
}