extern crate sdl2; extern crate std; extern crate rand; use super::player; use super::constants; pub trait StraightBullet: Positioned + Drawable { fn real_x(&self) -> f64; fn real_y(&self) -> f64; fn set_real_x(&mut self, real_x: f64); fn set_real_y(&mut self, real_y: f64); fn d_x(&self) -> f64; fn d_y(&self) -> f64; } pub struct PBullet { real_x: f64, real_y: f64, d_x: f64, d_y: f64, } impl StraightBullet for PBullet { fn real_x(&self) -> f64 { self.real_x } fn real_y(&self) -> f64 { self.real_y } fn set_real_x(&mut self, real_x: f64) { self.real_x = real_x; } fn set_real_y(&mut self, real_y: f64) { self.real_y = real_y; } fn d_x(&self) -> f64 { self.d_x } fn d_y(&self) -> f64 { self.d_y } } pub trait Bullet: Positioned + Drawable { fn act(&mut self); fn delete(&mut self); } impl Bullet for T { fn act(&mut self) { let real_x = self.real_x(); let d_x = self.d_x(); self.set_real_x(real_x + d_x); let real_y = self.real_y(); let d_y = self.d_y(); self.set_real_y(real_y + d_y); } fn delete(&mut self) { self.set_real_x(-10.); } } impl PBullet { pub fn new(x: i32, d_x: f64, y: i32, d_y: f64) -> PBullet { PBullet { real_x: x as f64, real_y: y as f64, d_x: d_x, d_y: d_y } } pub fn damage() -> f64 { 0.01 } } pub trait Enemy: Drawable { fn new() -> Self; fn act(&mut self, count: u64) -> Vec; fn health(&self) -> f64; fn set_health(&mut self, health: f64); } pub struct State { pub player: player::Player, pub enemies: Vec, pub bullets: Vec, pub player_bullets: Vec, pub count: u64, } impl, U> State { pub fn new() -> State { State { player: player::Player::new(), enemies: vec![T::new()], bullets: Vec::new(), count: 0, player_bullets: Vec::new() } } } fn dist(x1: i32, y1: i32, x2: i32, y2: i32) -> f64 { let xdist = x1 - x2; let ydist = y1 - y2; f64::sqrt((xdist*xdist + ydist*ydist) as f64) } pub trait Positioned { fn x(&self) -> i32; fn y(&self) -> i32; fn radius() -> u32; fn contains(&self, x: i32, y: i32) -> bool { let d = dist(self.x(), self.y(), x, y); d <= Self::radius() as f64 } fn overlaps(&self, other: &T) -> bool { let sx = self.x(); let ox = other.x(); let sy = self.y(); let oy = other.y(); let threshold = Self::radius() + T::radius(); if (sx - ox).abs() as u32 >= threshold || (sy - oy).abs() as u32 >= threshold { return false; } let dist = dist(sx, sy, ox, oy); dist < threshold as f64 } fn outside(&self) -> bool { let x = self.x(); let y = self.y(); x < 0 || x > constants::X_DIM as i32 || y < 0 || y > constants::Y_DIM as i32 } } impl Positioned for PBullet { fn x(&self) -> i32 { self.real_x.round() as i32 } fn y(&self) -> i32 { self.real_y.round() as i32 } fn radius() -> u32 { 10 } } pub trait Drawable : Positioned { fn center() -> (u32, u32); fn draw(&self, canvas: &mut sdl2::render::WindowCanvas, texture: &sdl2::render::Texture) { let tw = texture.query().width; let th = texture.query().height; let (cx, cy) = Self::center(); let x0 = self.x() - cx as i32; let y0 = self.y() - cy as i32; canvas.copy(&texture, None, Some(sdl2::rect::Rect::new(x0, y0, tw, th))).unwrap(); } } impl Drawable for PBullet { fn center() -> (u32, u32) { (16, 22) } }