mirror of
https://github.com/ivabus/matrix
synced 2025-06-07 23:50:26 +03:00
192 lines
4.7 KiB
Rust
192 lines
4.7 KiB
Rust
use std::time::Instant;
|
|
|
|
use log::error;
|
|
use pixels::{PixelsBuilder, SurfaceTexture};
|
|
use winit::dpi::LogicalSize;
|
|
use winit::event::{Event, VirtualKeyCode};
|
|
use winit::event_loop::{ControlFlow, EventLoop};
|
|
use winit::window::{WindowBuilder, WindowButtons};
|
|
use winit_input_helper::WinitInputHelper;
|
|
|
|
use crate::structs::Line;
|
|
|
|
mod structs;
|
|
|
|
const WIDTH: u32 = 640;
|
|
const HEIGHT: u32 = 480;
|
|
const POLYGON: usize = 4;
|
|
// POLYGON >= 2
|
|
const CENTER_X: u32 = 320;
|
|
const CENTER_Y: u32 = 240;
|
|
const RADIUS: u32 = 100;
|
|
const PI: f64 = std::f64::consts::PI;
|
|
const DEFAULT_ANGLE: f64 = 0.;
|
|
|
|
impl Default for Line {
|
|
fn default() -> Self {
|
|
Line {
|
|
start_x: 0.,
|
|
start_y: 0.,
|
|
end_x: 0.,
|
|
end_y: 0.,
|
|
rotate_angle: 0.,
|
|
rotate_center_x: 0.,
|
|
rotate_center_y: 0.,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn create_polygon() -> [Line; POLYGON] {
|
|
let mut it: [Line; POLYGON] = [Line::default(); POLYGON];
|
|
let mut dots: Vec<(f64, f64)> = Vec::new();
|
|
for i in 0..POLYGON {
|
|
dots.push((
|
|
CENTER_X as f64 + RADIUS as f64 * (2. * PI * i as f64 / POLYGON as f64).cos(),
|
|
CENTER_Y as f64 + RADIUS as f64 * (2. * PI * i as f64 / POLYGON as f64).sin(),
|
|
));
|
|
}
|
|
for i in 0..POLYGON {
|
|
let next = if i + 1 == POLYGON {
|
|
0
|
|
} else {
|
|
i + 1
|
|
};
|
|
it[i] = Line::new(
|
|
dots[i].0,
|
|
dots[i].1,
|
|
dots[next].0,
|
|
dots[next].1,
|
|
DEFAULT_ANGLE,
|
|
CENTER_X as f64,
|
|
CENTER_Y as f64,
|
|
);
|
|
}
|
|
it
|
|
}
|
|
|
|
// Most based render, that goes by existing frame bitmap and just expands it to RGBA.
|
|
fn render(frame: &mut [u8], bitmap: &[[bool; WIDTH as usize]; HEIGHT as usize]) {
|
|
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
|
|
let x = i % WIDTH as usize;
|
|
let y = i / WIDTH as usize;
|
|
if bitmap[y][x] {
|
|
pixel.copy_from_slice(&[0xff, 0xff, 0xff, 0xff]);
|
|
} else {
|
|
pixel.copy_from_slice(&[0x00, 0x00, 0x00, 0xff]);
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
WindowBuilder::new()
|
|
.with_title("matrix_graphics")
|
|
.with_enabled_buttons(WindowButtons::CLOSE.union(WindowButtons::MINIMIZE))
|
|
.with_inner_size(size)
|
|
.with_min_inner_size(size)
|
|
.with_max_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);
|
|
PixelsBuilder::new(WIDTH, HEIGHT, surface_texture).enable_vsync(true).build().unwrap()
|
|
};
|
|
|
|
let mut objects = create_polygon();
|
|
|
|
let mut frame_count = 0;
|
|
let mut now = Instant::now();
|
|
|
|
let mut bitmap: [[bool; WIDTH as usize]; HEIGHT as usize] =
|
|
[[false; WIDTH as usize]; HEIGHT as usize];
|
|
event_loop.run(move |event, _, control_flow| {
|
|
if event == Event::MainEventsCleared {
|
|
render(pixels.get_frame_mut(), &bitmap);
|
|
if let Err(err) = pixels.render() {
|
|
error!("pixels.render() failed: {err}");
|
|
*control_flow = ControlFlow::Exit;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Handle input events
|
|
if input.update(&event) {
|
|
if input.key_pressed(VirtualKeyCode::Escape)
|
|
|| input.close_requested()
|
|
|| input.destroyed()
|
|
{
|
|
*control_flow = ControlFlow::Exit;
|
|
return;
|
|
}
|
|
if input.key_pressed(VirtualKeyCode::F) {
|
|
println!("Average FPS: {}", frame_count as f64 / now.elapsed().as_secs_f64());
|
|
frame_count = 0;
|
|
now = Instant::now();
|
|
}
|
|
if input.key_held(VirtualKeyCode::Equals) {
|
|
for i in &mut objects {
|
|
i.rotate_angle += std::f64::consts::PI / 360.;
|
|
}
|
|
}
|
|
if input.key_held(VirtualKeyCode::Space) {
|
|
for i in &mut objects {
|
|
i.rotate_angle = 0.;
|
|
}
|
|
}
|
|
if input.key_held(VirtualKeyCode::Minus) {
|
|
for i in &mut objects {
|
|
i.rotate_angle -= std::f64::consts::PI / 360.;
|
|
}
|
|
}
|
|
if input.key_held(VirtualKeyCode::Up) {
|
|
for i in &mut objects {
|
|
i.start_y -= 1.;
|
|
i.end_y -= 1.;
|
|
i.rotate_center_y -= 1.;
|
|
}
|
|
}
|
|
if input.key_held(VirtualKeyCode::Down) {
|
|
for i in &mut objects {
|
|
i.start_y += 1.;
|
|
i.end_y += 1.;
|
|
i.rotate_center_y += 1.;
|
|
}
|
|
}
|
|
if input.key_held(VirtualKeyCode::Left) {
|
|
for i in &mut objects {
|
|
i.start_x -= 1.;
|
|
i.end_x -= 1.;
|
|
i.rotate_center_x -= 1.;
|
|
}
|
|
}
|
|
if input.key_held(VirtualKeyCode::Right) {
|
|
for i in &mut objects {
|
|
i.start_x += 1.;
|
|
i.end_x += 1.;
|
|
i.rotate_center_x += 1.;
|
|
}
|
|
}
|
|
|
|
for i in &mut objects {
|
|
i.update();
|
|
}
|
|
bitmap = [[false; WIDTH as usize]; HEIGHT as usize];
|
|
for object in &objects {
|
|
let current_dots = object.get_points();
|
|
for (x, y) in current_dots {
|
|
if x >= 0 && y >= 0 && x < WIDTH as isize && y < HEIGHT as isize {
|
|
bitmap[y as usize][x as usize] = true;
|
|
}
|
|
}
|
|
}
|
|
frame_count += 1;
|
|
}
|
|
});
|
|
}
|