Working Purple Rain

main
zoomiti 4 years ago
commit 4d604add7a

1
.gitignore vendored

@ -0,0 +1 @@
/target

1592
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,18 @@
[package]
name = "purple_rain"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.19"
env_logger = "0.9.0"
log = "0.4.17"
pixels = "0.9.0"
rand = "0.8.5"
timer = "0.2.0"
winit = "0.26.1"
winit_input_helper = "0.12.0"

@ -0,0 +1,126 @@
use chrono::Duration;
use log::error;
use pixels::{Pixels, SurfaceTexture};
use rand::Rng;
use timer::Timer;
use winit::{
dpi::LogicalSize,
event::{Event, VirtualKeyCode},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
use winit_input_helper::WinitInputHelper;
const WIDTH: u32 = 400;
const HEIGHT: u32 = 300;
fn main() {
env_logger::init();
let event_loop = EventLoop::new();
let mut input = WinitInputHelper::new();
let window = {
let size = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
let scaled_size = LogicalSize::new(WIDTH as f64 * 3.0, HEIGHT as f64 * 3.0);
WindowBuilder::new()
.with_title("Purple Rain")
.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)
}
.unwrap();
let mut drops = Vec::new();
let mut rng = rand::thread_rng();
for _i in 0..200 {
drops.push(Drop {
x: (rng.gen_range(0..WIDTH as i32)),
y: (rng.gen_range(0..HEIGHT as i32)),
z: (rng.gen_range(1..20)),
})
}
let timer = Timer::new();
let guard = timer.schedule_repeating(Duration::milliseconds(10), move || {
window.request_redraw();
});
guard.ignore();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
if let Event::RedrawRequested(_) = event {
draw(&mut drops, pixels.get_frame());
if pixels
.render()
.map_err(|e| error!("pixels.render() failed: {}", e))
.is_err()
{
*control_flow = ControlFlow::Exit;
return;
}
}
if input.update(&event) {
if input.key_pressed(VirtualKeyCode::Escape) || input.key_pressed(VirtualKeyCode::Q) || input.quit() {
*control_flow = ControlFlow::Exit;
return;
} else if input.key_pressed(VirtualKeyCode::Space) {
//window.request_redraw();
}
// Resize the window
if let Some(size) = input.window_resized() {
pixels.resize_surface(size.width, size.height);
}
}
});
}
fn draw(drops: &mut Vec<Drop>, frame: &mut [u8]) {
let pixels = frame.chunks_exact_mut(4);
for pixel in pixels {
pixel.copy_from_slice(&[0xd3, 0xb7, 0xf7, 0xff]);
}
drops.iter_mut().for_each(|d| d.update());
for drop in drops {
let mut drawn = false;
for y in drop.y..(drop.y + drop.z) {
for x in drop.x..(drop.x + drop.z/4) {
let res = (y * (WIDTH as i32) * 4 + x * 4).try_into();
if res.is_ok() {
let i = res.unwrap();
if i < frame.len() {
drawn = true;
frame[i..i + 4].copy_from_slice(&[207, 100, 219, 0xff]);
}
}
}
}
if !drawn {
drop.y = -drop.z;
}
}
}
struct Drop {
x: i32,
y: i32,
z: i32,
}
impl Drop {
fn update(&mut self) {
self.y += std::cmp::max(self.z/4, 1);
}
}
Loading…