//! Demonstrates various projection and matrix fiddling/testing. extern crate good_web_game as ggez; use ggez::event::{self, KeyCode, KeyMods}; use ggez::graphics::{self, Color, DrawMode}; use ggez::miniquad; use ggez::{Context, GameResult}; use glam::*; use std::env; use std::path; struct MainState { pos_x: f32, gridmesh: graphics::Mesh, angle: graphics::Image, screen_bounds: Vec, screen_bounds_idx: usize, } impl MainState { const GRID_INTERVAL: f32 = 100.0; const GRID_SIZE: usize = 10; const GRID_POINT_RADIUS: f32 = 5.0; fn new(ctx: &mut Context, quad_ctx: &mut miniquad::GraphicsContext) -> GameResult { let angle = graphics::Image::new(ctx, quad_ctx, "/angle.png")?; let gridmesh_builder = &mut graphics::MeshBuilder::new(); for x in 0..Self::GRID_SIZE { for y in 0..Self::GRID_SIZE { let fx = x as f32; let fy = y as f32; let fsize = Self::GRID_SIZE as f32; let point = Vec2::new(fx * Self::GRID_INTERVAL, fy * Self::GRID_INTERVAL); let color = graphics::Color::new(fx / fsize, 0.0, fy / fsize, 1.0); gridmesh_builder.circle( DrawMode::fill(), point, Self::GRID_POINT_RADIUS, 2.0, color, )?; } } let gridmesh = gridmesh_builder.build(ctx, quad_ctx)?; // An array of rects to cycle the screen coordinates through. let screen_bounds = vec![ graphics::Rect::new(0.0, 0.0, 800.0, 600.0), graphics::Rect::new(0.0, 600.0, 800.0, -600.0), ]; let screen_bounds_idx = 0; let s = MainState { pos_x: 0.0, gridmesh, angle, screen_bounds, screen_bounds_idx, }; Ok(s) } fn draw_coord_labels( &self, ctx: &mut Context, quad_ctx: &mut miniquad::GraphicsContext, ) -> GameResult { for x in 0..Self::GRID_SIZE { for y in 0..Self::GRID_SIZE { let point = Vec2::new( x as f32 * Self::GRID_INTERVAL, y as f32 * Self::GRID_INTERVAL, ); let s = format!("({}, {})", point.x, point.y); let t = graphics::Text::new(s); graphics::draw(ctx, quad_ctx, &t, (point,))? } } Ok(()) } } impl event::EventHandler for MainState { fn update( &mut self, _ctx: &mut Context, _quad_ctx: &mut miniquad::GraphicsContext, ) -> GameResult { self.pos_x = self.pos_x % 800.0 + 1.0; Ok(()) } fn draw(&mut self, ctx: &mut Context, quad_ctx: &mut miniquad::GraphicsContext) -> GameResult { graphics::clear(ctx, quad_ctx, [0.1, 0.2, 0.3, 1.0].into()); let origin = Vec2::ZERO; graphics::draw(ctx, quad_ctx, &self.gridmesh, (origin, Color::WHITE))?; let param = graphics::DrawParam::new() .dest(Vec2::new(400.0, 400.0)) .rotation(self.pos_x / 100.0) .offset(Vec2::new(0.5, 0.5)) .scale(Vec2::new(1.0, 1.0)); self.draw_coord_labels(ctx, quad_ctx)?; graphics::draw(ctx, quad_ctx, &self.angle, param)?; graphics::present(ctx, quad_ctx)?; Ok(()) } fn key_down_event( &mut self, ctx: &mut Context, _quad_ctx: &mut miniquad::GraphicsContext, keycode: KeyCode, _keymod: KeyMods, _repeat: bool, ) { if let event::KeyCode::Space = keycode { self.screen_bounds_idx = (self.screen_bounds_idx + 1) % self.screen_bounds.len(); graphics::set_screen_coordinates(ctx, self.screen_bounds[self.screen_bounds_idx]) .unwrap(); } } } pub fn main() -> GameResult { let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") { let mut path = path::PathBuf::from(manifest_dir); path.push("resources"); path } else { path::PathBuf::from("./resources") }; ggez::start( ggez::conf::Conf::default() .cache(Some(include_bytes!("resources.tar"))) .physical_root_dir(Some(resource_dir)), |context, quad_ctx| Box::new(MainState::new(context, quad_ctx).unwrap()), ) }