castle-game 0.1.24

2D destructible terrain strategy game
use specs::*;
use std::time::Duration;

use draw::*;
use terrain::*;
use geom::*;

#[derive(Component, Debug, Copy, Clone)]
pub struct Velocity {
    pub x: f64,
    pub y: f64
}

impl Velocity {
    pub fn new(x: f64, y: f64) -> Self {
        Velocity { x, y }
    }
}

pub struct DeltaTime(pub Duration);

impl DeltaTime {
    pub fn new(time: f64) -> Self {
        DeltaTime(Duration::from_millis((time * 1000.0) as u64))
    }

    pub fn to_seconds(&self) -> f64 {
        self.0.as_secs() as f64 + self.0.subsec_nanos() as f64 * 1e-9
    }
}

pub struct Gravity(pub f64);

pub struct ParticleSystem;
impl<'a> System<'a> for ParticleSystem {
    type SystemData = (Entities<'a>,
                       Fetch<'a, DeltaTime>,
                       Fetch<'a, Gravity>,
                       FetchMut<'a, Terrain>,
                       WriteStorage<'a, WorldPosition>,
                       WriteStorage<'a, Velocity>,
                       WriteStorage<'a, PixelParticle>);

    fn run(&mut self, (entities, dt, grav, mut terrain, mut pos, mut vel, mut par): Self::SystemData) {
        let grav = grav.0;
        let dt = dt.to_seconds();

        for (entity, pos, vel, par) in (&*entities, &mut pos, &mut vel, &mut par).join() {
            pos.0.x += vel.x * dt;
            pos.0.y += vel.y * dt;
            vel.y += grav * dt;

            let old_pos = par.pos;
            match terrain.line_collides(pos.0.as_i32(), (old_pos.x as i32, old_pos.y as i32)) {
                Some(point) => {
                    terrain.draw_pixel((point.0 as usize, point.1 as usize), par.color);
                    let _ = entities.delete(entity);
                },
                None => {
                    par.pos = pos.0.as_usize();
                    par.life -= dt;
                    if par.life < 0.0 {
                        let _ = entities.delete(entity);
                    }
                }
            }
        }
    }
}