From 97435fbd4e0e083dc3c4c4f7ebb8d4bbd1088ab3 Mon Sep 17 00:00:00 2001 From: Nicolas Klier Date: Thu, 9 May 2024 00:44:04 +0200 Subject: [PATCH] Apparently the bounce is still broken. It always was. --- src/direction.rs | 4 +- src/npc.rs | 183 ++++++++++++++++++++++++++++++----------------- src/stage.rs | 14 ++-- 3 files changed, 129 insertions(+), 72 deletions(-) diff --git a/src/direction.rs b/src/direction.rs index 8351ff5..5316602 100644 --- a/src/direction.rs +++ b/src/direction.rs @@ -1,10 +1,10 @@ #[derive(Clone, Debug)] -pub struct Direction { +pub struct Coord { pub x: isize, pub y: isize } -impl Direction { +impl Coord { pub fn new(x: isize, y: isize) -> Self { Self { x, y } } diff --git a/src/npc.rs b/src/npc.rs index 100a193..83e1378 100644 --- a/src/npc.rs +++ b/src/npc.rs @@ -1,10 +1,26 @@ use std::cell; -use crate::{cell::{Cell, CellVariance}, direction::Direction, stage::{self, Stage}, HEIGHT, WIDTH}; +use crate::{ + cell::{Cell, CellVariance}, + direction::Coord, + stage::{self, Stage}, + HEIGHT, WIDTH, +}; + +#[derive(Clone, Debug, PartialEq)] +pub enum Direction { + TOP, /* 💪 */ + BOTTOM, /* 👉👈🥺 */ + LEFT, + RIGHT, +} #[derive(Clone, Debug)] pub struct Neighbour { - + pub cell: Cell, + pub direction: Direction, + pub pos_x: usize, + pub pos_y: usize, } #[derive(Clone, Debug)] @@ -13,11 +29,11 @@ pub struct NPC { pub obstructed_from: Vec, pub pos_x: usize, pub pos_y: usize, - pub direction: Direction, + pub direction: Coord, } impl NPC { - pub fn new_day(pos_x: usize, pos_y: usize, direction: Direction) -> Self { + pub fn new_day(pos_x: usize, pos_y: usize, direction: Coord) -> Self { Self { walk_on: CellVariance::DAY, obstructed_from: vec![CellVariance::NIGHT, CellVariance::VOID], @@ -27,7 +43,7 @@ impl NPC { } } - pub fn new_night(pos_x: usize, pos_y: usize, direction: Direction) -> Self { + pub fn new_night(pos_x: usize, pos_y: usize, direction: Coord) -> Self { Self { walk_on: CellVariance::NIGHT, obstructed_from: vec![CellVariance::DAY, CellVariance::VOID], @@ -42,77 +58,112 @@ impl NPC { Cell::new(self.obstructed_from[0]) } - pub fn process_bounce(&mut self, map: &Vec) { + pub fn process_bounce(&mut self, map: &Vec) -> Option { // Get the current and next positions - let (curr_x, curr_y) = (self.pos_x, self.pos_y); - let next: (Option, Option) = self.next_position(); - + let mut next_direction = self.direction.clone(); - - 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; - - // 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 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; - } - } - + // If we are here, we know that we hit something. + match self.check_neighborhood(map) { + None => { + self.move_next(); + return None; + } + Some(neighbour) => { + if neighbour.direction == Direction::LEFT || neighbour.direction == Direction::RIGHT + { + next_direction.x *= -1; + } else { + next_direction.y *= -1; + } - // 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; + // Return the new bounce direction + self.direction = next_direction; - if self.obstructed_from.contains(&variance_left) || self.obstructed_from.contains(&variance_right) { - next_direction.x *= -1; + self.move_next(); + + // Don't tell update function that we hit a void block, to avoid overriding it. + // We changed direction anyway. + if neighbour.cell.variance != CellVariance::VOID { + return Some(neighbour); + } + + None } } - - // 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; - - self.move_next(); } - fn perform_bounce(&mut self, next_x: usize) { + fn check_neighborhood(&self, map: &Vec) -> Option { + if self.pos_y == 0 && self.direction.y == -1 { + return Some(Neighbour { + cell: map[0], + direction: Direction::TOP, + pos_x: 0, + pos_y: 0, + }); + } + if self.pos_x == 0 && self.direction.x == -1 { + return Some(Neighbour { + cell: map[0], + direction: Direction::LEFT, + pos_x: 0, + pos_y: 0, + }); + } + + let left = (self.pos_x.checked_sub(1).unwrap_or(0), self.pos_y); + let right = (self.pos_x.checked_add(1).unwrap_or(0), self.pos_y); + let top = (self.pos_x, self.pos_y.checked_sub(1).unwrap_or(0)); + let bottom = (self.pos_x, (self.pos_y.checked_add(1).unwrap_or(0))); + + let cell_left = map.get(left.0 + left.1 * WIDTH).unwrap_or(&Cell { + variance: CellVariance::VOID, + }); + let cell_right = map.get(right.0 + right.1 * WIDTH).unwrap_or(&Cell { + variance: CellVariance::VOID, + }); + let cell_top = map.get(top.0 + top.1 * WIDTH).unwrap_or(&Cell { + variance: CellVariance::VOID, + }); + let cell_bottom = map.get(bottom.0 + bottom.1 * WIDTH).unwrap_or(&Cell { + variance: CellVariance::VOID, + }); + + if self.obstructed_from.contains(&cell_left.variance) { + return Some(Neighbour { + cell: cell_left.clone(), + direction: Direction::LEFT, + pos_x: left.0, + pos_y: left.1, + }); + } + if self.obstructed_from.contains(&cell_right.variance) { + return Some(Neighbour { + cell: cell_right.clone(), + direction: Direction::RIGHT, + pos_x: right.0, + pos_y: right.1, + }); + } + if self.obstructed_from.contains(&cell_top.variance) { + return Some(Neighbour { + cell: cell_top.clone(), + direction: Direction::TOP, + pos_x: top.0, + pos_y: top.1, + }); + } + if self.obstructed_from.contains(&cell_bottom.variance) { + return Some(Neighbour { + cell: cell_bottom.clone(), + direction: Direction::BOTTOM, + pos_x: bottom.0, + pos_y: bottom.1, + }); + } + + return None; } pub fn move_next(&mut self) { diff --git a/src/stage.rs b/src/stage.rs index 1fa1956..6f6311b 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -10,7 +10,7 @@ use randomize::PCG32; use crate::cell::Cell; use crate::cell::CellVariance; -use crate::direction::Direction; +use crate::direction::Coord; use crate::npc::NPC; #[derive(Debug, Clone)] @@ -116,10 +116,10 @@ impl Stage { let npc: NPC; match cell.variance { CellVariance::DAY => { - npc = NPC::new_day(pos_x, pos_y, Direction::new(-1, -1)); + npc = NPC::new_day(pos_x, pos_y, Coord::new(-1, -1)); } CellVariance::NIGHT => { - npc = NPC::new_night(pos_x, pos_y, Direction::new(-1, -1)); + npc = NPC::new_night(pos_x, pos_y, Coord::new(-1, -1)); } CellVariance::VOID => { // Ignore this stupid request. @@ -173,7 +173,13 @@ impl Stage { pub fn update(&mut self) { // Process bounce logic for npc in self.npcs.iter_mut() { - npc.process_bounce(&self.cells_dup); + match npc.process_bounce(&self.cells_dup) { + Some(n) => { + let c = self.cells[n.pos_x + n.pos_y * self.width]; + self.cells[n.pos_x + n.pos_y * self.width] = c.invert(); + }, + None => {} + } } // Write current background