summaryrefslogtreecommitdiff
path: root/src/gui.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui.rs')
-rw-r--r--src/gui.rs123
1 files changed, 123 insertions, 0 deletions
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<G: Game + 'static>(mut game: G) -> std::thread::JoinHandle<()> {
+ std::thread::spawn(|| Self::new().run_in_thread(game))
+ }
+
+ fn run_in_thread<G: Game + 'static>(&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<Mutex<Option<Status>>>,
+ size: (u32, u32),
+ jump: Arc<AtomicU32>,
+}
+
+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);
+ }
+ }
+}