use std::{ env, path, time::{Duration, Instant}, }; // --- fn inform_release_mode() { if cfg!(debug_assertions) && env::var("yes_i_really_want_debug_mode").is_err() { eprintln!( "Note: Release mode will improve performance greatly.\n \ e.g. use `cargo run --example spritebatch --release`" ); } } // --- #[test] fn vxdraw_sprites() { use cgmath::{Matrix4, Rad, Vector3}; use vxdraw::{dyntex, void_logger, Color, ShowWindow, VxDraw}; let mut vx = VxDraw::new(void_logger(), ShowWindow::Custom(800, 600)); vx.set_clear_color(Color::Rgba(26, 61, 77, 255)); inform_release_mode(); let tile = vx.dyntex().add_layer( &dyntex::ImgData::PNGBytes(include_bytes!["../images/tile.png"]), &dyntex::LayerOptions::new(), ); for _ in 0..150 * 1500 { vx.dyntex().add(&tile, dyntex::Sprite::default()); } let cycle = 10_000; let begin = Instant::now(); let mut tick = 0; loop { let before = Instant::now(); let persp = vx.perspective_projection(); let time = ((Instant::now() - begin).as_secs_f32() * 1000.0) as u32; let mut dyntex = vx.dyntex(); dyntex.set_translation_all(&tile, |id| { ( (id / 150) as f32 / 150.0 * 2.0 - 1.0, (id % 150) as f32 / 150.0 * 2.0 - 1.0, ) }); dyntex.set_scale_all(&tile, |_| { ((time % cycle * 2) as f32 / cycle as f32 * 6.28) .cos() .abs() / 150.0 }); dyntex.set_rotation_all(&tile, |_| { Rad(-2.0 * ((time % cycle) as f32 / cycle as f32 * 6.28)) }); vx.set_perspective( persp * Matrix4::from_translation(Vector3::new( ((time % cycle) as f32 / cycle as f32 * 6.28).cos() * 50.0 / 800.0 - 350.0 / 800.0, ((time % cycle) as f32 / cycle as f32 * 6.28).sin() * 50.0 / 600.0 - 450.0 / 600.0, 0.0, )) * Matrix4::from_angle_z(Rad((time % cycle) as f32 / cycle as f32 * 6.28)) * Matrix4::from_scale( ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0, ), ); vx.draw_frame(); let after = Instant::now(); std::thread::sleep(std::time::Duration::new(0, 3_000_000)); tick += 1; if tick % 100 == 0 { println!("Draw time: {} ", (after - before).as_secs_f32()); } } } #[test] fn ggez_sprites() { use ggez::{ conf::WindowSetup, event, graphics, nalgebra::{Point2, Vector2}, timer, Context, GameResult, }; struct MainState { spritebatch: graphics::spritebatch::SpriteBatch, } impl MainState { fn new(ctx: &mut Context) -> GameResult { let image = graphics::Image::new(ctx, "/tile.png").unwrap(); let batch = graphics::spritebatch::SpriteBatch::new(image); let s = MainState { spritebatch: batch }; Ok(s) } } impl event::EventHandler for MainState { fn update(&mut self, ctx: &mut Context) -> GameResult { if timer::ticks(ctx) % 100 == 0 { println!("Delta frame time: {:?} ", timer::delta(ctx)); println!("Average FPS: {}", timer::fps(ctx)); } Ok(()) } fn draw(&mut self, ctx: &mut Context) -> GameResult { graphics::clear(ctx, graphics::BLACK); let time = (timer::duration_to_f64(timer::time_since_start(ctx)) * 1000.0) as u32; let cycle = 10_000; for x in 0..150 { for y in 0..250 { let x = x as f32; let y = y as f32; let p = graphics::DrawParam::new() .dest(Point2::new(x * 10.0, y * 10.0)) .scale(Vector2::new( ((time % cycle * 2) as f32 / cycle as f32 * 6.28) .cos() .abs() * 0.0625, ((time % cycle * 2) as f32 / cycle as f32 * 6.28) .cos() .abs() * 0.0625, )) .rotation(-2.0 * ((time % cycle) as f32 / cycle as f32 * 6.28)); self.spritebatch.add(p); } } let param = graphics::DrawParam::new() .dest(Point2::new( ((time % cycle) as f32 / cycle as f32 * 6.28).cos() * 50.0 - 350.0, ((time % cycle) as f32 / cycle as f32 * 6.28).sin() * 50.0 - 450.0, )) .scale(Vector2::new( ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0, ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0, )) .rotation((time % cycle) as f32 / cycle as f32 * 6.28) .offset(Point2::new(750.0, 750.0)); graphics::draw(ctx, &self.spritebatch, param)?; self.spritebatch.clear(); graphics::present(ctx)?; Ok(()) } } inform_release_mode(); let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") { let mut path = path::PathBuf::from(manifest_dir); path.push("images"); path } else { path::PathBuf::from("./images") }; let cb = ggez::ContextBuilder::new("ggez", "benchmark-test") .window_setup(WindowSetup { vsync: false, ..WindowSetup::default() }) .add_resource_path(resource_dir); let (ctx, event_loop) = &mut cb.build().unwrap(); let state = &mut MainState::new(ctx).unwrap(); event::run(ctx, event_loop, state).unwrap(); }