diff --git a/src/npc.rs b/src/npc.rs index 950f465..100a193 100644 --- a/src/npc.rs +++ b/src/npc.rs @@ -1,5 +1,12 @@ +use std::cell; + use crate::{cell::{Cell, CellVariance}, direction::Direction, stage::{self, Stage}, HEIGHT, WIDTH}; +#[derive(Clone, Debug)] +pub struct Neighbour { + +} + #[derive(Clone, Debug)] pub struct NPC { pub walk_on: CellVariance, @@ -10,26 +17,10 @@ pub struct NPC { } impl NPC { - pub fn new( - pos_x: usize, - pos_y: usize, - direction: Direction, - walk_on: CellVariance, - obstructed_from: Vec, - ) -> Self { - Self { - walk_on, - obstructed_from, - pos_x, - pos_y, - direction, - } - } - pub fn new_day(pos_x: usize, pos_y: usize, direction: Direction) -> Self { Self { walk_on: CellVariance::DAY, - obstructed_from: vec![CellVariance::NIGHT], + obstructed_from: vec![CellVariance::NIGHT, CellVariance::VOID], pos_x, pos_y, direction, @@ -39,7 +30,7 @@ impl NPC { pub fn new_night(pos_x: usize, pos_y: usize, direction: Direction) -> Self { Self { walk_on: CellVariance::NIGHT, - obstructed_from: vec![CellVariance::DAY], + obstructed_from: vec![CellVariance::DAY, CellVariance::VOID], pos_x, pos_y, direction, @@ -51,41 +42,95 @@ impl NPC { Cell::new(self.obstructed_from[0]) } - pub fn process_bounce(&mut self, mut stage: &Stage) { - println!("Calc bounce for {:?}", self); - let obstacle = self.next_position(); - + pub fn process_bounce(&mut self, map: &Vec) { // Get the current and next positions let (curr_x, curr_y) = (self.pos_x, self.pos_y); - let (next_x, next_y) = obstacle; + let next: (Option, Option) = self.next_position(); + let mut next_direction = self.direction.clone(); - // Hit top from below || Hit bottom from above - let hit_head = next_y > curr_y || curr_y > next_y; + let mut out_of_bounds_top = false; + let mut out_of_bounds_left = false; + let mut next_x: usize = 0; + let mut next_y: usize = 0; - // Hit right from left || Hit left from right - let hit_side = next_x > curr_x || curr_x > next_x; + // Both tuples of `next` will be none if they are out of bounds. + if next.0.is_some() && next.1.is_some() { + (next_x, next_y) = (next.0.unwrap(), next.1.unwrap()); - if hit_head { - next_direction.y *= -1; + // If we stay on our stage + if (next_x <= WIDTH - 1 && next_y <= HEIGHT - 1) { + let Cell { variance } = map.get(next_x + next_y * WIDTH).unwrap(); + + if !self.obstructed_from.contains(variance) { + // If our next cell is not obstructing us, nor is out of screen (see above) then we don't + // need to bounce around and can simply move to the next position. + self.move_next(); + + return; + } + } + } else { + if next.0.is_none() { + out_of_bounds_left = true; + } else { + out_of_bounds_top = true; + } } - // Hit right from left || Hit left from right - if hit_side { + // If we are here, we know that we hit something. + + // Check our left and right + if out_of_bounds_left { next_direction.x *= -1; + } else { + let variance_left = map.get((self.pos_x.checked_sub(1).unwrap_or(0)) + self.pos_y * WIDTH).unwrap_or(&Cell { variance: CellVariance::VOID }).variance; + let variance_right = map.get((self.pos_x.checked_add(1).unwrap_or(0)) + self.pos_y * WIDTH).unwrap_or(&Cell { variance: CellVariance::VOID }).variance; + + if self.obstructed_from.contains(&variance_left) || self.obstructed_from.contains(&variance_right) { + next_direction.x *= -1; + } } + // Check top and bottom + if out_of_bounds_top { + next_direction.y *= -1; + } else { + let variance_top = map.get(self.pos_x + (self.pos_y.checked_sub(1).unwrap_or(0)) * WIDTH).unwrap_or(&Cell { variance: CellVariance::VOID }).variance; + let variance_bottom = map.get(self.pos_x + (self.pos_y.checked_add(1).unwrap_or(0)) * WIDTH).unwrap_or(&Cell { variance: CellVariance::VOID }).variance; + + if self.obstructed_from.contains(&variance_top) || self.obstructed_from.contains(&variance_bottom) { + next_direction.y *= -1; + } + } + + // Return the new bounce direction self.direction = next_direction; - let _ = self.pos_x.checked_add_signed(self.direction.x); - let _ = self.pos_y.checked_add_signed(self.direction.y); + self.move_next(); } - pub fn next_position(&self) -> (usize, usize) { + fn perform_bounce(&mut self, next_x: usize) { + + } + + pub fn move_next(&mut self) { + let mov_x = self.pos_x.checked_add_signed(self.direction.x); + let mov_y = self.pos_y.checked_add_signed(self.direction.y); + + if mov_x.is_none() || mov_y.is_none() { + println!("Illegal move prevented"); + } else { + self.pos_x = mov_x.unwrap(); + self.pos_y = mov_y.unwrap(); + } + } + + pub fn next_position(&self) -> (Option, Option) { ( - (self.pos_x as isize + self.direction.x).clamp(0, WIDTH.try_into().unwrap()) as usize, - (self.pos_y as isize + self.direction.y).clamp(0, HEIGHT.try_into().unwrap()) as usize + (self.pos_x.checked_add_signed(self.direction.x)), + (self.pos_y.checked_add_signed(self.direction.y)), ) } } diff --git a/src/stage.rs b/src/stage.rs index e337c47..1fa1956 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -173,8 +173,7 @@ impl Stage { pub fn update(&mut self) { // Process bounce logic for npc in self.npcs.iter_mut() { - let me = &self; - npc.process_bounce(self); + npc.process_bounce(&self.cells_dup); } // Write current background