From 5e8139c883fd5ac08608bddd1b3efd0a6f26409a Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 17 Dec 2018 18:39:19 +0100 Subject: Encapsulate graphics functions to share a state with loaded resources --- src/graphics.rs | 225 ++++++++++++++++++++++++++++++-------------------------- src/main.rs | 8 +- 2 files changed, 125 insertions(+), 108 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index 422c884..8ccdbd3 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -11,7 +11,6 @@ use sfml::window::{ use sfml::graphics::{ RenderWindow, RenderTarget, - Drawable, Texture, Image, Color, @@ -23,125 +22,143 @@ use sfml::graphics::{ Transformable, }; + #[derive(RustEmbed)] #[folder = "res/maps"] pub struct MapAssets; +#[derive(Debug)] +pub struct Graphics { + window: RenderWindow, + running: bool, + // loaded resources + tilesets: HashMap, + textures: HashMap, +} -pub fn start() -> RenderWindow { - let default_window_size = (1280, 720); - let default_framerate = 80; +impl Graphics { + pub fn new() -> Graphics { + let default_window_size = (1280, 720); + let default_framerate = 80; + + let context_settings = ContextSettings { + antialiasing_level: 0, + ..Default::default() + }; + + let mut window = RenderWindow::new( + default_window_size, + "Subconscious", + Style::CLOSE, + &context_settings + ); + + window.set_framerate_limit(default_framerate); + window.set_vertical_sync_enabled(true); + + return Graphics { + window: window, + running: true, + tilesets: HashMap::new(), + textures: HashMap::new(), + }; + } - let context_settings = ContextSettings { - antialiasing_level: 0, - ..Default::default() - }; + pub fn is_running(self: &mut Self) -> bool { + return self.running; + } - let mut window = RenderWindow::new( - default_window_size, - "Subconscious", - Style::CLOSE, - &context_settings - ); + pub fn render(self: &mut Self, state: &crate::game::State) { + + // background + let bgcolor = match state.map.background_colour { + Some(color) => Color::rgb(color.red, color.green, color.blue), + None => Color::BLACK, + }; + + self.window.clear(&bgcolor); + + // render map + + // for each tile + for y in 0 .. state.map.height { + for x in 0 .. state.map.width { + // for each layer + for layer in &state.map.layers { + + let tmx_tile = layer.tiles[y as usize][x as usize]; + let tmx_tileset = state.map.get_tileset_by_gid(tmx_tile).unwrap(); + + // load tileset if not loaded yet + // TODO: load in a separate thread? + if !self.tilesets.contains_key(&tmx_tileset.first_gid) { + // TODO: replace with iter or error message + assert_eq!(tmx_tileset.images.len(), 1); + + // load tileset image + let tmx_image = &tmx_tileset.images[0]; + let asset = MapAssets::get(&tmx_image.source).unwrap(); + let image = Image::from_memory(asset.as_ref()).unwrap(); + + // load tiles (textures) + let tileset_width = tmx_image.width as u32 / tmx_tileset.tile_width; + let tileset_height = tmx_image.height as u32 / tmx_tileset.tile_height; + + for ty in 0 .. tileset_height { + for tx in 0 .. tileset_width { + let texture = Texture::from_image_with_rect( + &image, &Rect::new( + (tx * tmx_tileset.tile_width) as i32, + (ty * tmx_tileset.tile_height) as i32, + tmx_tileset.tile_width as i32, + tmx_tileset.tile_height as i32 + ) + ).unwrap(); + + // save tile texture + self.textures.insert( + tmx_tileset.first_gid + ty * tileset_width + tx, + texture + ); + } + } - window.set_framerate_limit(default_framerate); - window.set_vertical_sync_enabled(true); + // save tileset image + self.tilesets.insert(tmx_tileset.first_gid, image); + } - return window; -} + // draw! + // TODO: check map render order + let texture = self.textures.get(&tmx_tile).unwrap(); + let mut tile_rect = RectangleShape::with_texture(texture); -pub fn render(window: &mut RenderWindow, state: &crate::game::State) { - - // background - let bgcolor = match state.map.background_colour { - Some(color) => Color::rgb(color.red, color.green, color.blue), - None => Color::BLACK, - }; - - window.clear(&bgcolor); - - // render map - - // loaded textures - // TODO: cache outside of this function - let mut tilesets: HashMap = HashMap::new(); - let mut textures: HashMap = HashMap::new(); - - // for each tile - for y in 0 .. state.map.height { - for x in 0 .. state.map.width { - // for each layer - for layer in &state.map.layers { - - let tmx_tile = layer.tiles[y as usize][x as usize]; - let tmx_tileset = state.map.get_tileset_by_gid(tmx_tile).unwrap(); - - // load tileset if not loaded yet - // TODO: load in a separate thread? - if !tilesets.contains_key(&tmx_tileset.first_gid) { - // TODO: replace with iter or error message - assert_eq!(tmx_tileset.images.len(), 1); - - // load tileset image - let tmx_image = &tmx_tileset.images[0]; - let asset = MapAssets::get(&tmx_image.source).unwrap(); - let image = Image::from_memory(asset.as_ref()).unwrap(); - - // load tiles (textures) - let tileset_width = tmx_image.width as u32 / tmx_tileset.tile_width; - let tileset_height = tmx_image.height as u32 / tmx_tileset.tile_height; - - for ty in 0 .. tileset_height { - for tx in 0 .. tileset_width { - let texture = Texture::from_image_with_rect( - &image, &Rect::new( - (tx * tmx_tileset.tile_width) as i32, - (ty * tmx_tileset.tile_height) as i32, - tmx_tileset.tile_width as i32, - tmx_tileset.tile_height as i32 - ) - ).unwrap(); - - // save tile texture - textures.insert( - tmx_tileset.first_gid + ty * tileset_width + tx, - texture - ); - } - } + tile_rect.set_size(Vector2f { + x: tmx_tileset.tile_width as f32, + y: tmx_tileset.tile_height as f32 + }); - // save tileset image - tilesets.insert(tmx_tileset.first_gid, image); - } + tile_rect.set_position(Vector2f { + x: (x * tmx_tileset.tile_width) as f32, + y: (y * tmx_tileset.tile_height) as f32 + }); - // draw! - // TODO: check map render order - let texture = textures.get(&tmx_tile).unwrap(); - let mut tile_rect = RectangleShape::with_texture(texture); - - tile_rect.set_size(Vector2f { - x: tmx_tileset.tile_width as f32, - y: tmx_tileset.tile_height as f32 - }); - - tile_rect.set_position(Vector2f { - x: (x * tmx_tileset.tile_width) as f32, - y: (y * tmx_tileset.tile_height) as f32 - }); - - window.draw(&tile_rect); + self.window.draw(&tile_rect); + } } } - } - window.display(); -} + self.window.display(); + } -pub fn update(window: &mut RenderWindow) { - while let Some(ev) = window.poll_event() { - match ev { - Event::Closed => window.close(), - _ => {}, + pub fn update(self: &mut Self) { + while let Some(ev) = self.window.poll_event() { + match ev { + Event::Closed => { + self.window.close(); + self.running = false; + }, + _ => {}, + } } } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index b5190bf..7b2809c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,17 +32,17 @@ fn main() { let game_state = game_state_mutex.clone(); let graphics_thread = thread::spawn(move || { - let mut window = graphics::start(); + let mut graphics = graphics::Graphics::new(); - while window.is_open() { + while graphics.is_running() { // aquire state resource let game_state = match game_state.lock() { Ok(game_state) => game_state, Err(poisoned) => poisoned.into_inner(), }; - graphics::render(&mut window, &game_state); - graphics::update(&mut window); + graphics.render(&game_state); + graphics.update(); } { -- cgit v1.2.1