Fix bouncing
This commit is contained in:
117
src/npc.rs
117
src/npc.rs
@@ -1,5 +1,12 @@
|
|||||||
|
use std::cell;
|
||||||
|
|
||||||
use crate::{cell::{Cell, CellVariance}, direction::Direction, stage::{self, Stage}, HEIGHT, WIDTH};
|
use crate::{cell::{Cell, CellVariance}, direction::Direction, stage::{self, Stage}, HEIGHT, WIDTH};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Neighbour {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NPC {
|
pub struct NPC {
|
||||||
pub walk_on: CellVariance,
|
pub walk_on: CellVariance,
|
||||||
@@ -10,26 +17,10 @@ pub struct NPC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NPC {
|
impl NPC {
|
||||||
pub fn new(
|
|
||||||
pos_x: usize,
|
|
||||||
pos_y: usize,
|
|
||||||
direction: Direction,
|
|
||||||
walk_on: CellVariance,
|
|
||||||
obstructed_from: Vec<CellVariance>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
walk_on,
|
|
||||||
obstructed_from,
|
|
||||||
pos_x,
|
|
||||||
pos_y,
|
|
||||||
direction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_day(pos_x: usize, pos_y: usize, direction: Direction) -> Self {
|
pub fn new_day(pos_x: usize, pos_y: usize, direction: Direction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
walk_on: CellVariance::DAY,
|
walk_on: CellVariance::DAY,
|
||||||
obstructed_from: vec![CellVariance::NIGHT],
|
obstructed_from: vec![CellVariance::NIGHT, CellVariance::VOID],
|
||||||
pos_x,
|
pos_x,
|
||||||
pos_y,
|
pos_y,
|
||||||
direction,
|
direction,
|
||||||
@@ -39,7 +30,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: Direction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
walk_on: CellVariance::NIGHT,
|
walk_on: CellVariance::NIGHT,
|
||||||
obstructed_from: vec![CellVariance::DAY],
|
obstructed_from: vec![CellVariance::DAY, CellVariance::VOID],
|
||||||
pos_x,
|
pos_x,
|
||||||
pos_y,
|
pos_y,
|
||||||
direction,
|
direction,
|
||||||
@@ -51,41 +42,95 @@ impl NPC {
|
|||||||
Cell::new(self.obstructed_from[0])
|
Cell::new(self.obstructed_from[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_bounce(&mut self, mut stage: &Stage) {
|
pub fn process_bounce(&mut self, map: &Vec<Cell>) {
|
||||||
println!("Calc bounce for {:?}", self);
|
|
||||||
let obstacle = self.next_position();
|
|
||||||
|
|
||||||
// Get the current and next positions
|
// Get the current and next positions
|
||||||
let (curr_x, curr_y) = (self.pos_x, self.pos_y);
|
let (curr_x, curr_y) = (self.pos_x, self.pos_y);
|
||||||
let (next_x, next_y) = obstacle;
|
let next: (Option<usize>, Option<usize>) = self.next_position();
|
||||||
|
|
||||||
let mut next_direction = self.direction.clone();
|
let mut next_direction = self.direction.clone();
|
||||||
|
|
||||||
// Hit top from below || Hit bottom from above
|
let mut out_of_bounds_top = false;
|
||||||
let hit_head = next_y > curr_y || curr_y > next_y;
|
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
|
// Both tuples of `next` will be none if they are out of bounds.
|
||||||
let hit_side = next_x > curr_x || curr_x > next_x;
|
if next.0.is_some() && next.1.is_some() {
|
||||||
|
(next_x, next_y) = (next.0.unwrap(), next.1.unwrap());
|
||||||
|
|
||||||
if hit_head {
|
// If we stay on our stage
|
||||||
next_direction.y *= -1;
|
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 we are here, we know that we hit something.
|
||||||
if hit_side {
|
|
||||||
|
// Check our left and right
|
||||||
|
if out_of_bounds_left {
|
||||||
next_direction.x *= -1;
|
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
|
// Return the new bounce direction
|
||||||
self.direction = next_direction;
|
self.direction = next_direction;
|
||||||
|
|
||||||
let _ = self.pos_x.checked_add_signed(self.direction.x);
|
self.move_next();
|
||||||
let _ = self.pos_y.checked_add_signed(self.direction.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<usize>, Option<usize>) {
|
||||||
(
|
(
|
||||||
(self.pos_x as isize + self.direction.x).clamp(0, WIDTH.try_into().unwrap()) as usize,
|
(self.pos_x.checked_add_signed(self.direction.x)),
|
||||||
(self.pos_y as isize + self.direction.y).clamp(0, HEIGHT.try_into().unwrap()) as usize
|
(self.pos_y.checked_add_signed(self.direction.y)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,8 +173,7 @@ impl Stage {
|
|||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
// Process bounce logic
|
// Process bounce logic
|
||||||
for npc in self.npcs.iter_mut() {
|
for npc in self.npcs.iter_mut() {
|
||||||
let me = &self;
|
npc.process_bounce(&self.cells_dup);
|
||||||
npc.process_bounce(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write current background
|
// Write current background
|
||||||
|
|||||||
Reference in New Issue
Block a user