Initial commit

This commit is contained in:
2024-05-07 21:39:27 +02:00
parent ef9dab7593
commit 12e6760fb5
6 changed files with 284 additions and 0 deletions

5
.gitignore vendored
View File

@@ -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
View 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
View 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
View 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
View 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
View 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);
}
}