Initial commit
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -14,3 +14,8 @@ Cargo.lock
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
|
||||
|
||||
# Added by cargo
|
||||
|
||||
/target
|
||||
|
||||
45
.vscode/launch.json
vendored
Normal file
45
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug executable 'DayNight'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"--bin=DayNight",
|
||||
"--package=DayNight"
|
||||
],
|
||||
"filter": {
|
||||
"name": "DayNight",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug unit tests in executable 'DayNight'",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"test",
|
||||
"--no-run",
|
||||
"--bin=DayNight",
|
||||
"--package=DayNight"
|
||||
],
|
||||
"filter": {
|
||||
"name": "DayNight",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "DayNight"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
pixels = "0.13.0"
|
||||
env_logger = "0.10"
|
||||
log = "0.4"
|
||||
winit = "0.28"
|
||||
winit_input_helper = "0.14"
|
||||
randomize = "5.0.0"
|
||||
getrandom = "0.2.15"
|
||||
byteorder = "1"
|
||||
noise = "0.9"
|
||||
23
src/cell.rs
Normal file
23
src/cell.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum CellVariance {
|
||||
VOID = 0,
|
||||
DAY = 1,
|
||||
NIGHT = 2
|
||||
}
|
||||
|
||||
impl Default for CellVariance {
|
||||
fn default() -> Self {
|
||||
Self::VOID
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Cell {
|
||||
pub variance: CellVariance
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
pub fn new(variance: CellVariance) -> Self {
|
||||
Self { variance }
|
||||
}
|
||||
}
|
||||
88
src/main.rs
Normal file
88
src/main.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
mod cell;
|
||||
mod stage;
|
||||
|
||||
use pixels::{Error, Pixels, SurfaceTexture};
|
||||
use stage::Stage;
|
||||
use winit::{
|
||||
dpi::LogicalSize,
|
||||
event::{Event, VirtualKeyCode},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::{self, WindowBuilder},
|
||||
};
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
|
||||
const WIDTH: u32 = 256;
|
||||
const HEIGHT: u32 = 256;
|
||||
const SCALE_FACTOR: f64 = 4.0;
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
env_logger::init();
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let mut input = WinitInputHelper::new();
|
||||
|
||||
let window = {
|
||||
let size: LogicalSize<f64> = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
|
||||
let scaled_size =
|
||||
LogicalSize::new(WIDTH as f64 * SCALE_FACTOR, HEIGHT as f64 * SCALE_FACTOR);
|
||||
|
||||
WindowBuilder::new()
|
||||
.with_title("Day and Night")
|
||||
.with_inner_size(scaled_size)
|
||||
.with_min_inner_size(size)
|
||||
.build(&event_loop)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let mut pixels = {
|
||||
let window_size = window.inner_size();
|
||||
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
||||
Pixels::new(WIDTH, HEIGHT, surface_texture)?
|
||||
};
|
||||
|
||||
let mut stage = Stage::new(WIDTH as usize, HEIGHT as usize);
|
||||
stage.scatter(stage::ScatterTypes::RANDOM);
|
||||
|
||||
let mut paused = false;
|
||||
|
||||
let mut draw_state: Option<bool> = None;
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
if let Event::RedrawRequested(_) = event {
|
||||
stage.draw(pixels.frame_mut());
|
||||
|
||||
if let Err(err) = pixels.render() {
|
||||
debug_assert!(true, "Oops, I did it again.");
|
||||
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if input.update(&event) {
|
||||
if input.key_pressed(VirtualKeyCode::Escape) || input.close_requested() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
||||
if input.key_pressed(VirtualKeyCode::R) {
|
||||
stage.scatter(stage::ScatterTypes::RANDOM);
|
||||
}
|
||||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
debug_assert!(true, "Resize failed!");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if !paused || input.key_pressed_os(VirtualKeyCode::Space) {
|
||||
stage.update();
|
||||
}
|
||||
|
||||
window.request_redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
106
src/stage.rs
Normal file
106
src/stage.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
use noise::core::value;
|
||||
use noise::core::value::value_2d;
|
||||
use noise::permutationtable::PermutationTable;
|
||||
use noise::utils::NoiseMapBuilder;
|
||||
use noise::utils::PlaneMapBuilder;
|
||||
use noise::BasicMulti;
|
||||
use noise::Fbm;
|
||||
use noise::Perlin;
|
||||
use noise::Seedable;
|
||||
use randomize::Gen32;
|
||||
use randomize::PCG32;
|
||||
|
||||
use crate::cell::Cell;
|
||||
use crate::cell::CellVariance;
|
||||
pub struct Stage {
|
||||
cells: Vec<Cell>,
|
||||
|
||||
/// Used for temporary work item. Replaces `cells` once done.
|
||||
cells_dup: Vec<Cell>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
pub enum ScatterTypes {
|
||||
RANDOM = 0,
|
||||
}
|
||||
|
||||
impl Stage {
|
||||
pub fn new(width: usize, height: usize) -> Self {
|
||||
assert!(width != 0 && height != 0);
|
||||
let size = width.checked_mul(height).expect("Given width is too big.");
|
||||
|
||||
Self {
|
||||
cells: vec![Cell::default(); size],
|
||||
cells_dup: vec![Cell::default(); size],
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a pseudorandom seed for the game's PRNG.
|
||||
fn generate_seed() -> (u64, u64) {
|
||||
use byteorder::{ByteOrder, NativeEndian};
|
||||
use getrandom::getrandom;
|
||||
|
||||
let mut seed = [0_u8; 16];
|
||||
|
||||
getrandom(&mut seed).expect("failed to getrandom");
|
||||
|
||||
(
|
||||
NativeEndian::read_u64(&seed[0..8]),
|
||||
NativeEndian::read_u64(&seed[8..16]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn scatter(&mut self, scatter: ScatterTypes) {
|
||||
match scatter {
|
||||
ScatterTypes::RANDOM => {
|
||||
let seed = Self::generate_seed();
|
||||
let mut rng: randomize::PCG32 = PCG32::new(seed.0, seed.1);
|
||||
|
||||
let basicmulti = BasicMulti::<Perlin>::new(rng.next_u32());
|
||||
|
||||
let plane = PlaneMapBuilder::new(basicmulti)
|
||||
.set_size(self.width, self.height)
|
||||
.set_x_bounds(-5.0, 5.0)
|
||||
.set_y_bounds(-5.0, 5.0)
|
||||
.build();
|
||||
|
||||
for y in 0..self.height {
|
||||
for x in 0..self.width {
|
||||
let mut variance = CellVariance::VOID;
|
||||
|
||||
let value = plane.get_value(x, y);
|
||||
if value <= 0.1 {
|
||||
variance = CellVariance::DAY;
|
||||
} else {
|
||||
variance = CellVariance::NIGHT;
|
||||
}
|
||||
|
||||
let cell = self.cells.get_mut(x + y * self.width).unwrap();
|
||||
*cell = Cell::new(variance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.update();
|
||||
}
|
||||
|
||||
pub fn draw(&self, screen: &mut [u8]) {
|
||||
debug_assert_eq!(screen.len(), 4 * self.cells.len());
|
||||
for (c, pix) in self.cells.iter().zip(screen.chunks_exact_mut(4)) {
|
||||
let color = match c.variance {
|
||||
CellVariance::VOID => [0x0, 0x0, 0x0, 0xFF],
|
||||
CellVariance::DAY => [0xD3, 0xE3, 0xD3, 0xFF],
|
||||
CellVariance::NIGHT => [0x10, 0x41, 0x4F, 0xFF],
|
||||
};
|
||||
pix.copy_from_slice(&color);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
std::mem::swap(&mut self.cells_dup, &mut self.cells);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user