diff --git a/pirates/src/lib.rs b/pirates/src/lib.rs index 32da670..567d026 100644 --- a/pirates/src/lib.rs +++ b/pirates/src/lib.rs @@ -10,6 +10,7 @@ extern crate wee_alloc; static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; use lazy_static::lazy_static; +use na::Matrix2; use noise::PerlinBuf; use core::sync::atomic::{AtomicU32, Ordering}; use libm::{self, Libm}; @@ -69,6 +70,8 @@ static MAP: [u8; MAP_WIDTH * MAP_HEIGHT] = [ // should deflate to smaller than b static CAMERA: Mutex<[f32; 3]> = Mutex::new([0.0, 0.0, 4.0]); +static BOAT: Mutex = Mutex::new(Boat { x: 0.0, y: 0.0, theta: 0.0 }); + #[no_mangle] pub unsafe extern fn keyboard_input() { let keycode = KEYCODE[0]; @@ -94,6 +97,7 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) { }; let mut camera = CAMERA.lock(); + let mut boat = BOAT.lock(); //camera[0] += 1.0; @@ -111,6 +115,7 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) { let camera_vec = Vector2::new(camera[0],camera[1]); + // draw sea const half: Vector2 = Vector2::new(WIDTH as f32 / 2.0, HEIGHT as f32 / 2.0); for y in 0..HEIGHT { for x in 0..WIDTH { @@ -131,11 +136,71 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) { } } } + + // draw boat + + let rotation: f32 = boat.theta/RAD_TO_DEG; + + let cos = libm::cosf(rotation); + let sin = libm::sinf(rotation); + fn rotate(point: Vector2, cos: f32, sin: f32) -> Vector2 { + Vector2::new( + point.x * cos - point.y * sin, + point.x * sin + point.y * cos) + } + + const scale: f32 = 2.0; + + let mut p1 = Vector2::new(-0.5, 0.0)* scale; + let mut p2 = Vector2::new(0.5, 0.0)* scale; + let mut p3 = Vector2::new(0.0, -1.4)* scale; + p1 = (rotate(p1, cos, sin) - camera_vec) / camera[2]; + p2 = (rotate(p2, cos, sin) - camera_vec) / camera[2]; + p3 = (rotate(p3, cos, sin) - camera_vec) / camera[2]; + draw_tri(0xFF444444, buffer, p1+half, p2+half, p3+half); + let mut p1 = Vector2::new(0.0, -0.1)* scale; + let mut p2 = Vector2::new(0.2, 0.0)* scale; + let mut p3 = Vector2::new(0.0, -0.9)* scale; + p1 = (rotate(p1, cos, sin) - camera_vec) / camera[2]; + p2 = (rotate(p2, cos, sin) - camera_vec) / camera[2]; + p3 = (rotate(p3, cos, sin) - camera_vec) / camera[2]; + draw_tri(0xFFDDDDDD, buffer, p1+half, p2+half, p3+half); + + unsafe { blit_frame(); } //draw_text("hi from rust", 0,100,30); } +fn draw_tri(color: u32, buffer: &mut [u32; WIDTH*HEIGHT], p1: Vector2, p2: Vector2, p3: Vector2) { + let max_y = p1.y.max(p2.y).max(p3.y) as usize; + let max_x = p1.x.max(p2.x).max(p3.x) as usize; + let min_y = p1.y.min(p2.y).min(p3.y) as usize; + let min_x = p1.x.min(p2.x).min(p3.x) as usize; + + fn sign(p1: Vector2, p2: Vector2, p3: Vector2) -> f32 { + (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y) + } + + for y in min_y..max_y { + for x in min_x..max_x { + // https://stackoverflow.com/a/2049593 + let point = Vector2::new(x as f32, y as f32); + + let d1 = sign(point, p1, p2); + let d2 = sign(point, p2, p3); + let d3 = sign(point, p3, p1); + + let neg = (d1 < 0.0) || (d2 < 0.0) || (d3 < 0.0); + let pos = (d1 > 0.0) || (d2 > 0.0) || (d3 > 0.0); + if !(neg && pos) { + buffer[y*WIDTH + x] = color; + } + } + } + +} + fn sample_world(point: Vector2, rand: PerlinBuf) -> f32 { let offset = Vector2::new(64480.0, 7870.0); //240.0,240.0 @@ -159,6 +224,45 @@ enum Keys { Right = 39 } +const RAD_TO_DEG: f32 = 57.2058; +struct Boat { + x: f32, + y: f32, + theta: f32 +} + +impl Boat { + fn new(x: f32, y: f32, theta: f32) -> Boat { + Boat { x, y, theta } + } + + fn get_pos(self: &Self) -> Vector2 { + Vector2::new(self.x, self.y) + } + + fn set_pos(self: &mut Self, pos: Vector2) { + self.x = pos.x; + self.y = pos.y; + } + + fn get_velocity(self: &Self, wind_direction: f32) -> f32 { + let diff = 90.0 - libm::fabsf(self.theta % 360.0 - wind_direction); + let diff = libm::fabsf(diff); + diff * 0.5 + } + + fn go(self: &mut Self, velocity: f32) { + let cos = libm::cosf(self.theta/RAD_TO_DEG); + let sin = libm::sinf(self.theta/RAD_TO_DEG); + let pos = Vector2::new( + self.x * cos - self.y * sin, + self.x * sin + self.y * cos); + self.set_pos(pos); + } + +} + + #[cfg(test)] mod tests { use super::*;