From 223119654b4835c270ce4215f156e3c6236833b8 Mon Sep 17 00:00:00 2001 From: natrixaeria Date: Thu, 19 Dec 2019 20:16:20 +0100 Subject: Initial commit --- src/gui.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/gui.rs (limited to 'src/gui.rs') diff --git a/src/gui.rs b/src/gui.rs new file mode 100644 index 0000000..b13891c --- /dev/null +++ b/src/gui.rs @@ -0,0 +1,123 @@ +use ggez::event::EventHandler; +use crate::game::{Game, Status, Field}; +use std::sync::{Mutex, Arc, atomic::AtomicU32}; + +pub struct Gui { + ctx: ggez::Context, + event_loop: ggez::event::EventsLoop, +} + +impl Gui { + pub fn new() -> Self { + let (mut ctx, event_loop) = + ggez::ContextBuilder::new("neo x", "natrixaeria") + .window_setup(ggez::conf::WindowSetup::default() + .vsync(true)) + .build().unwrap(); + Self { + ctx, event_loop, + } + } + + pub fn run(mut game: G) -> std::thread::JoinHandle<()> { + std::thread::spawn(|| Self::new().run_in_thread(game)) + } + + fn run_in_thread(&mut self, mut game: G) { + let status = Arc::new(Mutex::new(Some(game.status()))); + let jump = Arc::new(AtomicU32::new(0)); + let mut handler = GameEventHandler { status: Arc::clone(&status), size: game.size(), jump: Arc::clone(&jump) }; + std::thread::spawn(move || { + let mut speed = 85.0; + while let Some(new_status) = game.update() { + if jump.fetch_and(0, std::sync::atomic::Ordering::SeqCst) > 0 { + game.jump(); + } + if let Ok(mut lock) = status.lock() { + *lock = Some(new_status); + } else { break; } + std::thread::sleep(std::time::Duration::from_millis(speed as u64)); + speed *= 0.9992; + println!("{:04} | {}", game.get_points(), speed); + } + println!("Points: {}", game.get_points()); + { *status.lock().unwrap() = None; } + }); + match ggez::event::run(&mut self.ctx, &mut self.event_loop, &mut handler) { + Err(_) => (), + _ => (), + } + } +} + +struct GameEventHandler { + status: Arc>>, + size: (u32, u32), + jump: Arc, +} + +impl GameEventHandler { + fn draw_rect(&mut self, ctx: &mut ggez::Context, translation: [f32; 4], color: ggez::graphics::Color, draw_mode: &ggez::graphics::DrawParam) -> ggez::GameResult<()> { + let rect = ggez::graphics::Mesh::new_rectangle( + ctx, + ggez::graphics::DrawMode::fill(), + ggez::graphics::Rect::new(translation[0], translation[1], translation[2], translation[3]), + color + )?; + ggez::graphics::draw(ctx, &rect, *draw_mode) + } + + fn draw_field(&mut self, ctx: &mut ggez::Context, col: u32, row: u32, color: ggez::graphics::Color, draw_mode: &ggez::graphics::DrawParam) -> ggez::GameResult<()> { + let (w, h) = ggez::graphics::size(ctx); + let (rx, ry) = self.size; + let (u, v) = (w / (rx as f32), h / (ry as f32)); + let (u, v) = if u < v { (u, u) } else { (v, v) }; + let (x, y) = (col as f32 * u, row as f32 * v); + let translation = [ x, y, u, v ]; + self.draw_rect(ctx, translation, color, draw_mode) + } +} + +impl EventHandler for GameEventHandler { + fn update(&mut self, ctx: &mut ggez::Context) -> ggez::GameResult<()> { + Ok(()) + } + + fn draw(&mut self, ctx: &mut ggez::Context) -> ggez::GameResult<()> { + let status = { (*self.status.lock().unwrap()).clone() }; + if status.is_none() { + println!("exxiittt"); + ggez::event::quit(ctx); + return Err(ggez::error::GameError::ResourceLoadError(format!("ending app"))); + } + let status = status.unwrap(); + let bg = ggez::graphics::BLACK; + let draw_mode = ggez::graphics::DrawParam::new(); + ggez::graphics::clear(ctx, bg); + + let (cols, rows) = self.size; + for row in 0..rows { + for col in 0..cols { + let color = match status.fields[((rows - row - 1) + col * rows) as usize] { + Field::Air => continue, + Field::Wall => ggez::graphics::Color::from_rgb(100, 100, 100), + Field::Spike => ggez::graphics::Color::from_rgb(200, 50, 6), + }; + self.draw_field(ctx, col, row, color, &draw_mode)?; + } + } + + let player_color = ggez::graphics::Color::from_rgb(0, 180, 250); + let (x, y) = (status.player[0], status.player[1]); + if rows >= y + 1 { + self.draw_field(ctx, x, rows - y - 1, player_color, &draw_mode)?; + } + ggez::graphics::present(ctx) + } + + fn key_down_event(&mut self, _ctx: &mut ggez::Context, keycode: ggez::event::KeyCode, _keymods: ggez::event::KeyMods, _repeat: bool) { + if keycode == ggez::event::KeyCode::Space { + self.jump.store(1, std::sync::atomic::Ordering::SeqCst); + } + } +} -- cgit v1.2.3-54-g00ecf