new rendering system
This commit is contained in:
parent
357ef6c8e2
commit
bf70ab9154
30
src/cell.rs
30
src/cell.rs
|
@ -1,18 +1,42 @@
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
use std::ops::BitAnd;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum CellType {
|
pub enum CellType {
|
||||||
Empty = 0,
|
Empty = 0,
|
||||||
Sand,
|
Sand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum MovementType {
|
pub enum MovementType {
|
||||||
None = 0b0000_0000,
|
None = 0b0000_0000,
|
||||||
Down = 0b0000_0001,
|
Down = 0b0000_0001,
|
||||||
|
// 000
|
||||||
|
// 1X1
|
||||||
|
// 000
|
||||||
Side = 0b0000_0010,
|
Side = 0b0000_0010,
|
||||||
|
// 000
|
||||||
|
// 0X0
|
||||||
|
// 111
|
||||||
DownSide = 0b0000_0011,
|
DownSide = 0b0000_0011,
|
||||||
}
|
}
|
||||||
|
impl BitAnd for MovementType {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
// rhs is the "right-hand side" of the expression `a & b`
|
||||||
|
fn bitand(self, rhs: Self) -> Self::Output {
|
||||||
|
let a = self as u8 & rhs as u8;
|
||||||
|
use MovementType::*;
|
||||||
|
match a {
|
||||||
|
0 => None,
|
||||||
|
1 => Down,
|
||||||
|
2 => Side,
|
||||||
|
3 => DownSide,
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
pub cell_type: CellType,
|
pub cell_type: CellType,
|
||||||
pub movement_type: MovementType,
|
pub movement_type: MovementType,
|
||||||
|
|
229
src/engine.rs
229
src/engine.rs
|
@ -1,23 +1,48 @@
|
||||||
use std::io::Empty;
|
|
||||||
|
|
||||||
use minifb::{Key, Window, WindowOptions};
|
use minifb::{Key, Window, WindowOptions};
|
||||||
|
|
||||||
const WIDTH: usize = 800;
|
const WIDTH: usize = 800;
|
||||||
const HEIGHT: usize = 600;
|
const HEIGHT: usize = 600;
|
||||||
|
|
||||||
use crate::{materials::*, rand::Random, world::World};
|
use crate::{
|
||||||
|
cell::{Cell, CellType, MovementType},
|
||||||
|
materials::*,
|
||||||
|
rand::Random,
|
||||||
|
tile::{Tile, PLAYER},
|
||||||
|
world::{in_bounds, xy_to_i, World},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Inventory {
|
||||||
|
current_selected: usize,
|
||||||
|
left_hand_side: [Cell; 10],
|
||||||
|
right_hand_side: [Cell; 10],
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
pub window: Window,
|
pub window: Window,
|
||||||
pub front_buffer: Vec<u32>,
|
pub front_buffer: Vec<u32>,
|
||||||
pub brush_size: usize,
|
pub brush_size: usize,
|
||||||
pub random: Random,
|
|
||||||
|
inventory: Inventory,
|
||||||
|
|
||||||
pub world: World,
|
pub world: World,
|
||||||
|
|
||||||
|
tiles: Vec<Tile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let inventory = Inventory {
|
||||||
|
current_selected: 0,
|
||||||
|
left_hand_side: [
|
||||||
|
SAND_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL,
|
||||||
|
EMPTY_CELL, EMPTY_CELL, EMPTY_CELL,
|
||||||
|
],
|
||||||
|
right_hand_side: [
|
||||||
|
EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL, EMPTY_CELL,
|
||||||
|
EMPTY_CELL, EMPTY_CELL, EMPTY_CELL,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
window: Window::new(
|
window: Window::new(
|
||||||
"Rising Sands :P | Hit ESC to exit",
|
"Rising Sands :P | Hit ESC to exit",
|
||||||
|
@ -30,14 +55,13 @@ impl Engine {
|
||||||
}),
|
}),
|
||||||
front_buffer: vec![0; WIDTH * HEIGHT],
|
front_buffer: vec![0; WIDTH * HEIGHT],
|
||||||
brush_size: 1,
|
brush_size: 1,
|
||||||
random: Random::new(0),
|
|
||||||
world: World::new(),
|
world: World::new(),
|
||||||
|
inventory,
|
||||||
|
tiles: vec![PLAYER],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
self.clear();
|
|
||||||
|
|
||||||
self.window.set_target_fps(60);
|
self.window.set_target_fps(60);
|
||||||
|
|
||||||
while self.window.is_open() {
|
while self.window.is_open() {
|
||||||
|
@ -52,33 +76,34 @@ impl Engine {
|
||||||
self.brush_size = self.brush_size.saturating_sub(1);
|
self.brush_size = self.brush_size.saturating_sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: something wrong here?
|
self.handle_mouse();
|
||||||
if self.window.get_mouse_down(minifb::MouseButton::Left) {
|
|
||||||
// TODO: Swap to mm::Discard and handle the mouse outside of the window
|
|
||||||
let pos = self.window.get_mouse_pos(minifb::MouseMode::Clamp).unwrap();
|
|
||||||
let half = self.brush_size / 2;
|
|
||||||
|
|
||||||
let mouse_x = pos.0 as usize - half;
|
// TODO: make a self.handle_player_movement() to handle the player movement stuff
|
||||||
let mouse_y = pos.1 as usize - half;
|
// BUG: panics when player moves partially off screen.
|
||||||
|
if self.window.is_key_down(Key::A) {
|
||||||
for x in 0..self.brush_size {
|
self.tiles[0].x -= 1;
|
||||||
for y in 0..self.brush_size {
|
}
|
||||||
self.set_cell(mouse_x + x, mouse_y + y, SAND);
|
if self.window.is_key_down(Key::D) {
|
||||||
}
|
self.tiles[0].x += 1;
|
||||||
}
|
}
|
||||||
|
if self.window.is_key_down(Key::W) {
|
||||||
|
self.tiles[0].y -= 1;
|
||||||
|
}
|
||||||
|
if self.window.is_key_down(Key::S) {
|
||||||
|
self.tiles[0].y += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.window.get_mouse_down(minifb::MouseButton::Right) {
|
for tile in &self.tiles {
|
||||||
// TODO: Swap to mm::Discard and handle the mouse outside of the window
|
for x in 0..8 {
|
||||||
let pos = self.window.get_mouse_pos(minifb::MouseMode::Clamp).unwrap();
|
for y in 0..8 {
|
||||||
let half = self.brush_size / 2;
|
if in_bounds(x, y) {
|
||||||
|
// what happens if the cell is already full?
|
||||||
|
let material = tile.values[y][x];
|
||||||
|
|
||||||
let mouse_x = pos.0 as usize - half;
|
if material != EMPTY_CELL {
|
||||||
let mouse_y = pos.1 as usize - half;
|
self.world.set_xy(x + tile.x, tile.y + y, material);
|
||||||
|
}
|
||||||
for x in 0..self.brush_size {
|
}
|
||||||
for y in 0..self.brush_size {
|
|
||||||
self.set_cell(mouse_x + x, mouse_y + y, EMPTY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,64 +111,120 @@ impl Engine {
|
||||||
for x in 0..WIDTH {
|
for x in 0..WIDTH {
|
||||||
for y in 0..HEIGHT {
|
for y in 0..HEIGHT {
|
||||||
let index = xy_to_i(x, y);
|
let index = xy_to_i(x, y);
|
||||||
let cell = self.front_buffer[index];
|
let cell = self.world.cells[index];
|
||||||
|
let cell_move = cell.movement_type;
|
||||||
if cell == SAND {
|
use MovementType::*;
|
||||||
let down = self.is_empty(x, y + 1);
|
match cell_move {
|
||||||
let random = self.random.random_bool();
|
None => {}
|
||||||
let left = self.is_empty(x - 1, y + 1) && random;
|
Down => self.world.move_down(x, y),
|
||||||
let right = self.is_empty(x + 1, y + 1) ^ left;
|
Side => todo!(),
|
||||||
|
DownSide => self.world.move_down_side(x, y),
|
||||||
if down {
|
|
||||||
self.set_cell(x, y + 1, SAND)
|
|
||||||
} else if left {
|
|
||||||
self.set_cell(x - 1, y + 1, SAND)
|
|
||||||
} else if right {
|
|
||||||
self.set_cell(x + 1, y + 1, SAND)
|
|
||||||
}
|
|
||||||
|
|
||||||
if down || left || right {
|
|
||||||
self.set_cell(x, y, EMPTY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.world.commit_cells();
|
||||||
|
|
||||||
|
for x in 0..WIDTH {
|
||||||
|
for y in 0..HEIGHT {
|
||||||
|
let index = xy_to_i(x, y);
|
||||||
|
let cell = self.world.cells[index];
|
||||||
|
|
||||||
|
self.front_buffer[index] = cell.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let pos = self.window.get_mouse_pos(minifb::MouseMode::Discard);
|
||||||
|
if pos.is_some() {
|
||||||
|
let pos = pos.unwrap();
|
||||||
|
let half = self.brush_size / 2;
|
||||||
|
|
||||||
|
let mouse_x = pos.0 as usize - half;
|
||||||
|
let mouse_y = pos.1 as usize - half;
|
||||||
|
|
||||||
|
for x in 0..self.brush_size {
|
||||||
|
if in_bounds(mouse_x + x, mouse_y) {
|
||||||
|
let index = xy_to_i(mouse_x + x, mouse_y);
|
||||||
|
self.front_buffer[index] = 0x00_ff_ff_ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for x in 0..self.brush_size {
|
||||||
|
if in_bounds(mouse_x + x, mouse_y + self.brush_size) {
|
||||||
|
let index = xy_to_i(mouse_x + x, mouse_y + self.brush_size);
|
||||||
|
self.front_buffer[index] = 0x00_ff_ff_ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for y in 0..self.brush_size {
|
||||||
|
if in_bounds(mouse_x, mouse_y + y) {
|
||||||
|
let index = xy_to_i(mouse_x, mouse_y + y);
|
||||||
|
self.front_buffer[index] = 0x00_ff_ff_ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for y in 0..self.brush_size {
|
||||||
|
if in_bounds(mouse_x + self.brush_size, mouse_y + y) {
|
||||||
|
let index = xy_to_i(mouse_x + self.brush_size, mouse_y + y);
|
||||||
|
self.front_buffer[index] = 0x00_ff_ff_ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for x in 0..self.brush_size {
|
||||||
|
// for y in 0..self.brush_size {
|
||||||
|
// if in_bounds(mouse_x + x, mouse_y + y) {
|
||||||
|
// let index = xy_to_i(mouse_x + x, mouse_y + y);
|
||||||
|
// self.front_buffer[index] = 0x00_ff_ff_ff;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Handle this.
|
// TODO Handle this.
|
||||||
self.window
|
self.window
|
||||||
.update_with_buffer(&self.front_buffer, WIDTH, HEIGHT)
|
.update_with_buffer(&self.front_buffer, WIDTH, HEIGHT)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
for tile in &self.tiles {
|
||||||
|
for x in 0..8 {
|
||||||
|
for y in 0..8 {
|
||||||
|
// x += tile.x;
|
||||||
|
// y += tile.y;
|
||||||
|
|
||||||
|
if in_bounds(x, y) {
|
||||||
|
// what happens if the cell is already full?
|
||||||
|
self.world.set_xy(x + tile.x, tile.y + y, EMPTY_CELL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Engine {
|
pub fn handle_mouse(&mut self) {
|
||||||
fn is_empty(&mut self, x: usize, y: usize) -> bool {
|
let material = if self.window.get_mouse_down(minifb::MouseButton::Left) {
|
||||||
let index = xy_to_i(x, y);
|
self.inventory.left_hand_side[self.inventory.current_selected]
|
||||||
if index >= self.front_buffer.len() {
|
} else if self.window.get_mouse_down(minifb::MouseButton::Right) {
|
||||||
false
|
self.inventory.right_hand_side[self.inventory.current_selected]
|
||||||
} else {
|
} else {
|
||||||
self.front_buffer[index] == EMPTY
|
return;
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn set_cell(&mut self, x: usize, y: usize, mat: u32) {
|
// TODO: Swap to MouseMode::Discard and handle the mouse outside of the window
|
||||||
let index = xy_to_i(x, y);
|
let pos = self.window.get_mouse_pos(minifb::MouseMode::Discard);
|
||||||
if index >= self.front_buffer.len() {
|
if pos.is_some() {
|
||||||
} else {
|
let pos = pos.unwrap();
|
||||||
self.front_buffer[index] = mat;
|
let half = self.brush_size / 2;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self) {
|
let mouse_x = pos.0 as usize - half;
|
||||||
for x in 0..WIDTH {
|
let mouse_y = pos.1 as usize - half;
|
||||||
for y in 0..HEIGHT {
|
|
||||||
let index = xy_to_i(x, y);
|
for x in 0..self.brush_size {
|
||||||
self.front_buffer[index] = EMPTY;
|
for y in 0..self.brush_size {
|
||||||
|
if in_bounds(mouse_x + x, mouse_y + y) {
|
||||||
|
self.world.set_xy(mouse_x + x, mouse_y + y, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xy_to_i(x: usize, y: usize) -> usize {
|
|
||||||
x + WIDTH * y
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ mod cell;
|
||||||
mod engine;
|
mod engine;
|
||||||
mod materials;
|
mod materials;
|
||||||
mod rand;
|
mod rand;
|
||||||
|
mod tile;
|
||||||
mod world;
|
mod world;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,2 +1,22 @@
|
||||||
|
use crate::cell::Cell;
|
||||||
|
use crate::cell::CellType::*;
|
||||||
|
use crate::cell::MovementType::*;
|
||||||
|
|
||||||
pub const EMPTY: u32 = 0x00_00_00;
|
pub const EMPTY: u32 = 0x00_00_00;
|
||||||
|
|
||||||
pub const SAND: u32 = 0xFF_99_50;
|
pub const SAND: u32 = 0xFF_99_50;
|
||||||
|
|
||||||
|
pub const EMPTY_CELL: Cell = Cell {
|
||||||
|
cell_type: Empty,
|
||||||
|
movement_type: None,
|
||||||
|
color: 0x0,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SAND_CELL: Cell = Cell {
|
||||||
|
cell_type: Sand,
|
||||||
|
movement_type: DownSide,
|
||||||
|
color: 0xFF_99_50,
|
||||||
|
};
|
||||||
|
|
||||||
|
//SAND_START_COLOR_RANGE = 0x00_f6_D7_B0
|
||||||
|
//SAND_END_COLOR_RANGE = 0x00_e1_bf_92
|
||||||
|
|
|
@ -18,4 +18,12 @@ impl Random {
|
||||||
pub fn random_bool(&mut self) -> bool {
|
pub fn random_bool(&mut self) -> bool {
|
||||||
self.rng.gen_bool(0.5)
|
self.rng.gen_bool(0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn color_range(&mut self, start: u32, end: u32) -> u32 {
|
||||||
|
if start == end {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
self.rng.gen_range(start..=end)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
33
src/tile.rs
Normal file
33
src/tile.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
use crate::{cell::Cell, materials::EMPTY_CELL};
|
||||||
|
|
||||||
|
pub struct Tile {
|
||||||
|
pub x: usize,
|
||||||
|
pub y: usize,
|
||||||
|
pub values: [[Cell; 8]; 8],
|
||||||
|
}
|
||||||
|
|
||||||
|
const SKIN: Cell = Cell {
|
||||||
|
cell_type: crate::cell::CellType::Sand,
|
||||||
|
movement_type: crate::cell::MovementType::None,
|
||||||
|
color: 0x00_Fe_9f_13,
|
||||||
|
};
|
||||||
|
|
||||||
|
const EYE: Cell = Cell {
|
||||||
|
cell_type: crate::cell::CellType::Sand,
|
||||||
|
movement_type: crate::cell::MovementType::None,
|
||||||
|
color: 0x00_00_5e_be,
|
||||||
|
};
|
||||||
|
|
||||||
|
const NORMAL_ROW: [Cell; 8] = [
|
||||||
|
EMPTY_CELL, EMPTY_CELL, SKIN, SKIN, SKIN, SKIN, EMPTY_CELL, EMPTY_CELL,
|
||||||
|
];
|
||||||
|
const EYE_ROW: [Cell; 8] = [
|
||||||
|
EMPTY_CELL, EMPTY_CELL, EYE, SKIN, SKIN, EYE, EMPTY_CELL, EMPTY_CELL,
|
||||||
|
];
|
||||||
|
pub const PLAYER: Tile = Tile {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
values: [
|
||||||
|
NORMAL_ROW, EYE_ROW, NORMAL_ROW, NORMAL_ROW, NORMAL_ROW, NORMAL_ROW, NORMAL_ROW, NORMAL_ROW,
|
||||||
|
],
|
||||||
|
};
|
83
src/world.rs
83
src/world.rs
|
@ -1,23 +1,26 @@
|
||||||
use crate::cell::{Cell, MovementType};
|
use crate::cell::{Cell, MovementType};
|
||||||
|
|
||||||
use crate::cell::CellType::Empty;
|
use crate::cell::CellType::Empty;
|
||||||
use crate::engine::xy_to_i;
|
use crate::materials::{EMPTY, EMPTY_CELL};
|
||||||
use crate::materials::EMPTY;
|
use crate::rand::Random;
|
||||||
|
|
||||||
const WIDTH: usize = 800;
|
const WIDTH: usize = 800;
|
||||||
const HEIGHT: usize = 600;
|
const HEIGHT: usize = 600;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Change {
|
pub struct Change {
|
||||||
x_from: usize,
|
x_from: usize,
|
||||||
x_to: usize,
|
x_to: usize,
|
||||||
y_from: usize,
|
y_from: usize,
|
||||||
y_to: usize,
|
y_to: usize,
|
||||||
}
|
}
|
||||||
|
// #[derive(Ord)]
|
||||||
pub struct World {
|
pub struct World {
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub cells: Vec<Cell>,
|
pub cells: Vec<Cell>,
|
||||||
changes: Vec<Change>,
|
changes: Vec<Change>,
|
||||||
|
pub random: Random,
|
||||||
}
|
}
|
||||||
impl World {
|
impl World {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -33,6 +36,7 @@ impl World {
|
||||||
WIDTH * HEIGHT
|
WIDTH * HEIGHT
|
||||||
],
|
],
|
||||||
changes: vec![],
|
changes: vec![],
|
||||||
|
random: Random::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +72,74 @@ impl World {
|
||||||
self.changes.push(change);
|
self.changes.push(change);
|
||||||
}
|
}
|
||||||
// Takes the changes to the world and applies them.
|
// Takes the changes to the world and applies them.
|
||||||
pub fn commit_cells() {}
|
pub fn commit_cells(&mut self) {
|
||||||
|
let mut changes_length: usize = self.changes.len();
|
||||||
|
if changes_length == 0 {
|
||||||
|
// println!("WARN: Empty changes.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut cell_index = 0;
|
||||||
|
// while cell_index <= changes_length {
|
||||||
|
// let cell = &self.changes[cell_index];
|
||||||
|
// let first_cell = self.get_xy(cell.x_from, cell.y_from);
|
||||||
|
// if first_cell.cell_type != Empty {
|
||||||
|
// self.changes[cell_index] = *self.changes.last().unwrap();
|
||||||
|
// let _ = self.changes.pop();
|
||||||
|
|
||||||
|
// // m_changes.pop_back();
|
||||||
|
// changes_length -= 1;
|
||||||
|
// }
|
||||||
|
// cell_index += 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Sort the changes.
|
||||||
|
self.changes.sort();
|
||||||
|
|
||||||
|
let changes_length: usize = self.changes.len();
|
||||||
|
|
||||||
|
// TODO: Apply these changes in random order
|
||||||
|
for index in 0..changes_length {
|
||||||
|
let dst_x = self.changes[index].x_to;
|
||||||
|
let dst_y = self.changes[index].y_to;
|
||||||
|
|
||||||
|
let src_x = self.changes[index].x_from;
|
||||||
|
let src_y = self.changes[index].y_from;
|
||||||
|
|
||||||
|
let cell = self.get_xy(src_x, src_y);
|
||||||
|
|
||||||
|
self.set_xy(dst_x, dst_y, cell);
|
||||||
|
|
||||||
|
self.set_xy(src_x, src_y, EMPTY_CELL);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.changes = vec![];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl World {
|
||||||
|
pub fn move_down(&mut self, x: usize, y: usize) {
|
||||||
|
if self.is_empty(x, y + 1) {
|
||||||
|
self.move_cell(x, y, x, y + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn move_down_side(&mut self, x: usize, y: usize) {
|
||||||
|
let mut down_left = self.is_empty(x - 1, y + 1);
|
||||||
|
let mut down_right = self.is_empty(x + 1, y + 1);
|
||||||
|
let down = self.is_empty(x, y + 1);
|
||||||
|
|
||||||
|
if down_left && down_right {
|
||||||
|
down_left = self.random.random_bool();
|
||||||
|
down_right = down_right != down_left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if down_left {
|
||||||
|
self.move_cell(x, y, x - 1, y + 1);
|
||||||
|
} else if down_right {
|
||||||
|
self.move_cell(x, y, x + 1, y + 1);
|
||||||
|
} else if down {
|
||||||
|
self.move_cell(x, y, x, y + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_bounds(x: usize, y: usize) -> bool {
|
pub fn in_bounds(x: usize, y: usize) -> bool {
|
||||||
|
@ -77,3 +148,7 @@ pub fn in_bounds(x: usize, y: usize) -> bool {
|
||||||
|
|
||||||
x_in_bounds && y_in_bounds
|
x_in_bounds && y_in_bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn xy_to_i(x: usize, y: usize) -> usize {
|
||||||
|
x + WIDTH * y
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue