Compare commits
2 Commits
da0d6e204a
...
33a865d059
| Author | SHA1 | Date | |
|---|---|---|---|
| 33a865d059 | |||
| ddb8e0423d |
@@ -1,5 +1,4 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::fmt::write;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum CellVariance {
|
pub enum CellVariance {
|
||||||
|
|||||||
20
src/main.rs
20
src/main.rs
@@ -9,12 +9,12 @@ use winit::{
|
|||||||
dpi::LogicalSize,
|
dpi::LogicalSize,
|
||||||
event::{Event, VirtualKeyCode},
|
event::{Event, VirtualKeyCode},
|
||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
window::{self, WindowBuilder},
|
window::WindowBuilder,
|
||||||
};
|
};
|
||||||
use winit_input_helper::WinitInputHelper;
|
use winit_input_helper::WinitInputHelper;
|
||||||
|
|
||||||
const WIDTH: u32 = 64;
|
const WIDTH: usize = 64;
|
||||||
const HEIGHT: u32 = 64;
|
const HEIGHT: usize = 64;
|
||||||
const SCALE_FACTOR: f64 = 10.0;
|
const SCALE_FACTOR: f64 = 10.0;
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
@@ -39,7 +39,7 @@ fn main() -> Result<(), Error> {
|
|||||||
let mut pixels = {
|
let mut pixels = {
|
||||||
let window_size = window.inner_size();
|
let window_size = window.inner_size();
|
||||||
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
||||||
Pixels::new(WIDTH, HEIGHT, surface_texture)?
|
Pixels::new(WIDTH as u32, HEIGHT as u32, surface_texture)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut stage = Stage::new(WIDTH as usize, HEIGHT as usize);
|
let mut stage = Stage::new(WIDTH as usize, HEIGHT as usize);
|
||||||
@@ -47,13 +47,11 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
let mut paused = false;
|
let mut paused = false;
|
||||||
|
|
||||||
let mut draw_state: Option<bool> = None;
|
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
if let Event::RedrawRequested(_) = event {
|
if let Event::RedrawRequested(_) = event {
|
||||||
stage.draw(pixels.frame_mut());
|
stage.draw(pixels.frame_mut());
|
||||||
|
|
||||||
if let Err(err) = pixels.render() {
|
if let Err(_) = pixels.render() {
|
||||||
debug_assert!(true, "Oops, I did it again.");
|
debug_assert!(true, "Oops, I did it again.");
|
||||||
|
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
@@ -80,9 +78,13 @@ fn main() -> Result<(), Error> {
|
|||||||
stage.scatter(stage::ScatterTypes::Random);
|
stage.scatter(stage::ScatterTypes::Random);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if input.key_pressed(VirtualKeyCode::H) {
|
||||||
|
stage.scatter(stage::ScatterTypes::HalfVertical);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle mouse. This is a bit involved since support some simple
|
// Handle mouse. This is a bit involved since support some simple
|
||||||
// line drawing (mostly because it makes nice looking patterns).
|
// line drawing (mostly because it makes nice looking patterns).
|
||||||
let (mouse_cell, mouse_prev_cell) = input
|
let (mouse_cell, _) = input
|
||||||
.mouse()
|
.mouse()
|
||||||
.map(|(mx, my)| {
|
.map(|(mx, my)| {
|
||||||
let (dx, dy) = input.mouse_diff();
|
let (dx, dy) = input.mouse_diff();
|
||||||
@@ -116,7 +118,7 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
// Resize the window
|
// Resize the window
|
||||||
if let Some(size) = input.window_resized() {
|
if let Some(size) = input.window_resized() {
|
||||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
if let Err(_) = pixels.resize_surface(size.width, size.height) {
|
||||||
debug_assert!(true, "Resize failed!");
|
debug_assert!(true, "Resize failed!");
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
|
|||||||
35
src/npc.rs
35
src/npc.rs
@@ -1,4 +1,4 @@
|
|||||||
use crate::{cell::CellVariance, direction::Direction};
|
use crate::{cell::{Cell, CellVariance}, direction::Direction, stage::{self, Stage}, HEIGHT, WIDTH};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NPC {
|
pub struct NPC {
|
||||||
@@ -46,33 +46,46 @@ impl NPC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bounce(&mut self) -> Direction {
|
pub fn into_cell(&self) -> Cell {
|
||||||
|
// TODO: Bad idea.
|
||||||
|
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();
|
||||||
|
|
||||||
// Get the current and next positions
|
// Get the current and next positions
|
||||||
let (curr_x, curr_y) = (self.pos_x as isize, self.pos_y as isize);
|
let (curr_x, curr_y) = (self.pos_x, self.pos_y);
|
||||||
let (next_x, next_y) = self.next_position();
|
let (next_x, next_y) = obstacle;
|
||||||
let mut next_direction = self.direction.clone();
|
let mut next_direction = self.direction.clone();
|
||||||
|
|
||||||
// Hit top from below || Hit bottom from above
|
// Hit top from below || Hit bottom from above
|
||||||
if curr_y < next_y || curr_y > next_y {
|
let hit_head = next_y > curr_y || curr_y > next_y;
|
||||||
|
|
||||||
|
// Hit right from left || Hit left from right
|
||||||
|
let hit_side = next_x > curr_x || curr_x > next_x;
|
||||||
|
|
||||||
|
if hit_head {
|
||||||
next_direction.y *= -1;
|
next_direction.y *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hit right from left || Hit left from right
|
// Hit right from left || Hit left from right
|
||||||
if next_x > curr_x || curr_x > next_x {
|
if hit_side {
|
||||||
next_direction.x *= -1;
|
next_direction.x *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the new bounce direction
|
// Return the new bounce direction
|
||||||
self.direction = next_direction;
|
self.direction = next_direction;
|
||||||
|
|
||||||
println!("Next: {:?}", self.direction);
|
let _ = self.pos_x.checked_add_signed(self.direction.x);
|
||||||
self.direction.clone()
|
let _ = self.pos_y.checked_add_signed(self.direction.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_position(&self) -> (isize, isize) {
|
pub fn next_position(&self) -> (usize, usize) {
|
||||||
(
|
(
|
||||||
(self.pos_x as isize + self.direction.x),
|
(self.pos_x as isize + self.direction.x).clamp(0, WIDTH.try_into().unwrap()) as usize,
|
||||||
(self.pos_y as isize + self.direction.y),
|
(self.pos_y as isize + self.direction.y).clamp(0, HEIGHT.try_into().unwrap()) as usize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/stage.rs
90
src/stage.rs
@@ -1,3 +1,6 @@
|
|||||||
|
use std::borrow::Borrow;
|
||||||
|
use std::cell;
|
||||||
|
|
||||||
use noise::utils::NoiseMapBuilder;
|
use noise::utils::NoiseMapBuilder;
|
||||||
use noise::utils::PlaneMapBuilder;
|
use noise::utils::PlaneMapBuilder;
|
||||||
use noise::BasicMulti;
|
use noise::BasicMulti;
|
||||||
@@ -9,13 +12,14 @@ use crate::cell::Cell;
|
|||||||
use crate::cell::CellVariance;
|
use crate::cell::CellVariance;
|
||||||
use crate::direction::Direction;
|
use crate::direction::Direction;
|
||||||
use crate::npc::NPC;
|
use crate::npc::NPC;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct Stage {
|
pub struct Stage {
|
||||||
cells: Vec<Cell>,
|
cells: Vec<Cell>,
|
||||||
|
|
||||||
/// Used for temporary work item. Replaces `cells` once done.
|
/// Used for temporary work item. Replaces `cells` once done.
|
||||||
cells_dup: Vec<Cell>,
|
cells_dup: Vec<Cell>,
|
||||||
npcs: Vec<NPC>,
|
npcs: Vec<NPC>,
|
||||||
npc_map: Vec<Option<Cell>>,
|
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
}
|
}
|
||||||
@@ -34,7 +38,6 @@ impl Stage {
|
|||||||
cells: vec![Cell::default(); size],
|
cells: vec![Cell::default(); size],
|
||||||
cells_dup: vec![Cell::default(); size],
|
cells_dup: vec![Cell::default(); size],
|
||||||
npcs: vec![],
|
npcs: vec![],
|
||||||
npc_map: vec![None; size],
|
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
}
|
}
|
||||||
@@ -132,34 +135,28 @@ impl Stage {
|
|||||||
pub fn draw(&mut self, screen: &mut [u8]) {
|
pub fn draw(&mut self, screen: &mut [u8]) {
|
||||||
debug_assert_eq!(screen.len(), 4 * self.cells.len());
|
debug_assert_eq!(screen.len(), 4 * self.cells.len());
|
||||||
|
|
||||||
// Draw NPCs
|
|
||||||
self.npc_map.fill(None);
|
|
||||||
for (i, npc) in self.npcs.iter().enumerate() {
|
|
||||||
let map_pos = npc.pos_x + npc.pos_y * self.width;
|
|
||||||
// let color = match npc.walk_on {
|
|
||||||
// CellVariance::DAY => [0x10, 0x41, 0x4F, 0xFF],
|
|
||||||
// CellVariance::NIGHT => [0xD3, 0xE3, 0xD3, 0xFF],
|
|
||||||
// _ => {
|
|
||||||
// panic!("This NPC shouldn't even exist!");
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
self.npc_map[map_pos] = Some(Cell::new(npc.obstructed_from[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw background
|
// Draw background
|
||||||
for (i, (mut c, pix)) in self
|
for (i, (c, pix)) in self
|
||||||
.cells
|
.cells
|
||||||
.iter()
|
.iter()
|
||||||
.zip(screen.chunks_exact_mut(4))
|
.zip(screen.chunks_exact_mut(4))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let npc_cell = self.npc_map.get(i).unwrap();
|
let mut cell: Cell = c.clone();
|
||||||
if let Some(npc_cell) = npc_cell {
|
|
||||||
c = &npc_cell;
|
let mut npc_cell: Option<NPC> = None;
|
||||||
|
for npc in self.npcs.iter() {
|
||||||
|
if npc.pos_x + npc.pos_y * self.width == i {
|
||||||
|
npc_cell = Some(npc.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let color = match c.variance {
|
// Draw NPCs
|
||||||
|
if let Some(npc_cell) = npc_cell {
|
||||||
|
cell = npc_cell.into_cell();
|
||||||
|
}
|
||||||
|
|
||||||
|
let color = match cell.variance {
|
||||||
CellVariance::VOID => [0x0, 0x0, 0x0, 0xFF],
|
CellVariance::VOID => [0x0, 0x0, 0x0, 0xFF],
|
||||||
CellVariance::DAY => [0xD3, 0xE3, 0xD3, 0xFF],
|
CellVariance::DAY => [0xD3, 0xE3, 0xD3, 0xFF],
|
||||||
CellVariance::NIGHT => [0x10, 0x41, 0x4F, 0xFF],
|
CellVariance::NIGHT => [0x10, 0x41, 0x4F, 0xFF],
|
||||||
@@ -174,60 +171,21 @@ impl Stage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
let mut hit_cells: Vec<(usize, usize)> = vec![];
|
// Process bounce logic
|
||||||
|
|
||||||
for npc in self.npcs.iter_mut() {
|
for npc in self.npcs.iter_mut() {
|
||||||
// if (npc.next_position().0 < 0 || npc.next_position().0 > self.width as isize) ||
|
let me = &self;
|
||||||
// (npc.next_position().1 < 0 || npc.next_position().1 > self.height as isize) {
|
npc.process_bounce(self);
|
||||||
// npc.bounce();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Check for collision with window borders
|
|
||||||
if npc.pos_x <= 0 || npc.pos_x >= self.width {
|
|
||||||
// Bounce off horizontally
|
|
||||||
npc.direction.x = -npc.direction.x;
|
|
||||||
// Move object back inside the window
|
|
||||||
npc.pos_x = npc.pos_x.clamp(0, self.width - 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if npc.pos_y <= 0 || npc.pos_y >= self.height {
|
|
||||||
// Bounce off vertically
|
|
||||||
npc.direction.y = -npc.direction.y;
|
|
||||||
// Move object back inside the window
|
|
||||||
npc.pos_y = npc.pos_y.clamp(0, self.height - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let index =
|
|
||||||
npc.next_position().0 as usize + npc.next_position().1 as usize * self.width;
|
|
||||||
let next_cell = self.cells_dup[index];
|
|
||||||
|
|
||||||
// If our next cell would be one that we collide with.
|
|
||||||
if npc.obstructed_from.contains(&next_cell.variance) {
|
|
||||||
npc.direction.invert();
|
|
||||||
hit_cells.push((npc.pos_x, npc.pos_y));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
npc.pos_x = npc.next_position().0 as usize;
|
|
||||||
npc.pos_y = npc.next_position().1 as usize;
|
|
||||||
|
|
||||||
// We can move freely for now.
|
|
||||||
self.npc_map[index] = Some(Cell::new(npc.obstructed_from[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write current background
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
for x in 0..self.width {
|
for x in 0..self.width {
|
||||||
let idx = x + y * self.width;
|
let idx = x + y * self.width;
|
||||||
// Write into scratch_cells, since we're still reading from `self.cells`
|
|
||||||
|
|
||||||
if hit_cells.contains(&(x, y)) {
|
// Write into scratch_cells, since we're still reading from `self.cells`
|
||||||
self.cells_dup[idx] = self.cells[idx].invert();
|
|
||||||
} else {
|
|
||||||
self.cells_dup[idx] = self.cells[idx];
|
self.cells_dup[idx] = self.cells[idx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::mem::swap(&mut self.cells_dup, &mut self.cells);
|
std::mem::swap(&mut self.cells_dup, &mut self.cells);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user