use cgmath::{Deg, InnerSpace, Point3, Vector2}; use rapier2d::{ dynamics::{RigidBody, RigidBodyBuilder, RigidBodyHandle}, geometry::{ColliderBuilder, ColliderHandle}, }; use crate::util; use galactica_content as content; use galactica_render::ObjectSprite; /// A helper struct that contains parameters for a projectile /// TODO: decouple data from physics pub struct ProjectileBuilder { /// TODO pub rigid_body: RigidBodyBuilder, /// TODO pub collider: ColliderBuilder, /// TODO pub sprite_texture: content::TextureHandle, /// TODO pub lifetime: f32, /// TODO pub size: f32, /// TODO pub damage: f32, /// TODO pub faction: content::FactionHandle, } /// A single projectile in the world #[derive(Debug)] pub struct Projectile { /// TODO pub rigid_body: RigidBodyHandle, /// TODO pub collider: ColliderHandle, /// TODO pub sprite_texture: content::TextureHandle, /// TODO pub lifetime: f32, /// TODOd pub size: f32, /// TODO pub damage: f32, /// TODO pub faction: content::FactionHandle, } impl Projectile { /// Make a new projectile pub fn new(b: ProjectileBuilder, r: RigidBodyHandle, c: ColliderHandle) -> Self { Projectile { rigid_body: r, collider: c, sprite_texture: b.sprite_texture, lifetime: b.lifetime, size: b.size, damage: b.damage, faction: b.faction, } } /// Update this projectile's state after `t` seconds pub fn tick(&mut self, t: f32) { self.lifetime -= t; } /// Is this projectile expired? pub fn is_expired(&self) -> bool { return self.lifetime < 0.0; } /// Get this projectiles' sprite pub fn get_sprite(&self, r: &RigidBody) -> ObjectSprite { let pos = util::rigidbody_position(r); let rot = util::rigidbody_rotation(r); // Sprites point north at 0 degrees let ang: Deg = rot.angle(Vector2 { x: 1.0, y: 0.0 }).into(); ObjectSprite { texture: self.sprite_texture, pos: Point3 { x: pos.x, y: pos.y, z: 1.0, }, size: self.size, angle: -ang, children: None, } } }