use eframe::egui; use egui::{Align2, FontId, Key, Pos2, Rect, vec2}; mod game; use game::{GameState, Glyph}; const CELL_W: f32 = 14.0; const CELL_H: f32 = 20.0; fn main() -> eframe::Result<()> { let options = eframe::NativeOptions::default(); eframe::run_native( "Viberogue", options, Box::new(|_cc| Ok(Box::new(App::new()))), ) } struct App { state: GameState, } impl App { fn new() -> Self { Self { state: GameState::new() } } } impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { ctx.input(|i| { if i.key_pressed(Key::ArrowUp) { self.state.try_move( 0, -1); } if i.key_pressed(Key::ArrowDown) { self.state.try_move( 0, 1); } if i.key_pressed(Key::ArrowLeft) { self.state.try_move(-1, 0); } if i.key_pressed(Key::ArrowRight) { self.state.try_move( 1, 0); } }); egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| { egui::MenuBar::new().ui(ui, |ui| { ui.menu_button("File", |ui| { if ui.button("Exit").clicked() { ctx.send_viewport_cmd(egui::ViewportCommand::Close); } }); }); }); egui::CentralPanel::default().show(ctx, |ui| { let board = &self.state.board; let origin = ui.available_rect_before_wrap().min; let painter = ui.painter(); for y in 0..board.height { for x in 0..board.width { let (glyph, _) = board.get(x, y); draw_glyph(painter, origin, x, y, glyph); } } let player_glyph = Glyph::player(); draw_glyph( painter, origin, self.state.player.x as usize, self.state.player.y as usize, &player_glyph, ); }); ctx.request_repaint(); } } fn draw_glyph(painter: &egui::Painter, origin: Pos2, x: usize, y: usize, glyph: &Glyph) { let tl = origin + vec2(x as f32 * CELL_W, y as f32 * CELL_H); let rect = Rect::from_min_size(tl, vec2(CELL_W, CELL_H)); let center = rect.center(); painter.rect_filled(rect, 0.0, glyph.bg); painter.text(center, Align2::CENTER_CENTER, glyph.ch, FontId::monospace(CELL_H), glyph.fg); }