From e0fa16cc8fdb54231cd78d6f85e8033e5df01085 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 2 Apr 2022 14:39:12 -0400 Subject: [PATCH] Map rendering! --- .../src/rendering/utilities/map_render.rs | 104 ++++++++++++++++-- game/game_logic/src/scenes/test_fox.rs | 49 ++++++++- 2 files changed, 138 insertions(+), 15 deletions(-) diff --git a/game/game_logic/src/rendering/utilities/map_render.rs b/game/game_logic/src/rendering/utilities/map_render.rs index 8a105177..b9822917 100644 --- a/game/game_logic/src/rendering/utilities/map_render.rs +++ b/game/game_logic/src/rendering/utilities/map_render.rs @@ -1,9 +1,14 @@ -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; use crate::asset_manager::{load_texture_from_internal_data, InternalData}; use nalgebra as na; use raylib::{ - camera::Camera2D, prelude::RaylibDrawHandle, texture::Texture2D, RaylibHandle, RaylibThread, + camera::Camera2D, + color::Color, + math::Vector2, + prelude::{RaylibDraw, RaylibDrawHandle, RaylibMode2D}, + texture::Texture2D, + RaylibHandle, RaylibThread, }; use tiled::{Loader, Map, ResourceCache, ResourcePath, ResourcePathBuf, Tileset}; @@ -69,7 +74,7 @@ impl ResourceCache for ProgramDataTileCache { #[derive(Debug)] pub struct MapRenderer { map: Map, - tile_textures: HashMap>, + tile_textures: HashMap, } impl MapRenderer { @@ -93,9 +98,9 @@ impl MapRenderer { let mut tile_textures = HashMap::new(); for tileset in map.tilesets() { for (idx, tile) in tileset.tiles() { - if let Some(image) = tile.data.image { + if let Some(image) = &tile.data.image { // We now have a path to an image - let image_path = image.source; + let image_path = image.source.clone(); // Load the texture let texture = load_texture_from_internal_data( @@ -106,10 +111,7 @@ impl MapRenderer { .unwrap(); // Store the texture in the cache - tile_textures - .entry(tileset.name) - .or_insert_with(HashMap::new) - .insert(idx, texture); + tile_textures.insert(image_path, texture); } } } @@ -125,5 +127,87 @@ impl MapRenderer { todo!() } - pub fn render_map(&self, draw_handle: &RaylibDrawHandle, camera: &Camera2D) {} + pub fn render_map(&self, draw_handle: &mut RaylibMode2D, camera: &Camera2D, show_debug_grid:bool) { + // Get the window corners in world space + let screen_width = draw_handle.get_screen_width(); + let screen_height = draw_handle.get_screen_height(); + let world_win_top_left = draw_handle.get_screen_to_world2D(Vector2::new(0.0, 0.0), camera); + let world_win_bottom_right = draw_handle.get_screen_to_world2D( + Vector2::new(screen_width as f32, screen_height as f32), + camera, + ); + + // Handle each layer from the bottom up + for layer in self.map.layers() { + // Handle different layer types + match layer.layer_type() { + tiled::LayerType::TileLayer(layer) => { + // Keep track of our sampler X and Y values + let mut sampler_x = 0; + let mut sampler_y = 0; + + // Get the tile width and height + let tile_width = 128; + let tile_height = 128; + + // Loop until we have covered all tiles on the screen + for y in (world_win_top_left.y as i64)..(world_win_bottom_right.y as i64) { + // Convert the pixel coordinates to tile coordinates + let tile_y = (y as f32 / tile_height as f32).floor() as i32; + + // If we are looking at a new tile, update the sampler + if sampler_y != tile_y { + sampler_y = tile_y; + + for x in + (world_win_top_left.x as i64)..(world_win_bottom_right.x as i64) + { + // Convert the pixel coordinates to tile coordinates + let tile_x = (x as f32 / tile_width as f32).floor() as i32; + // debug!("Tile: ({}, {})", tile_x, tile_y); + + // If we are looking at a new tile, update the sampler + if sampler_x != tile_x { + sampler_x = tile_x; + + // Get the tile at this coordinate + if let Some(tile) = layer.get_tile(sampler_x, sampler_y) { + // debug!("Tile: ({}, {})", tile_x, tile_y); + // Fetch the texture for this tile + let real_tile = tile.get_tile().unwrap(); + let texture = self + .tile_textures + .get(&real_tile.image.as_ref().unwrap().source) + .unwrap(); + + // Draw the tile + draw_handle.draw_texture( + texture, + tile_x * tile_width as i32, + tile_y * tile_height as i32, + Color::WHITE, + ); + } + + if show_debug_grid { + draw_handle.draw_rectangle_lines( + tile_x * tile_width as i32, + tile_y * tile_height as i32, + self.map.tile_width as i32, + self.map.tile_height as i32, + Color::RED, + ); + draw_handle.draw_pixel(x as i32, y as i32, Color::BLUE); + } + } + } + } + } + } + tiled::LayerType::ObjectLayer(_) => todo!(), + tiled::LayerType::ImageLayer(_) => todo!(), + tiled::LayerType::GroupLayer(_) => todo!(), + } + } + } } diff --git a/game/game_logic/src/scenes/test_fox.rs b/game/game_logic/src/scenes/test_fox.rs index 29911212..d9d1973e 100644 --- a/game/game_logic/src/scenes/test_fox.rs +++ b/game/game_logic/src/scenes/test_fox.rs @@ -1,18 +1,20 @@ //! This "scene" is used only for testing animation and resource loading //! It should be removed once the game is being worked on -use raylib::prelude::*; use nalgebra as na; +use raylib::prelude::*; use crate::{ - discord::DiscordChannel, global_resource_package::GlobalResources, + discord::DiscordChannel, + global_resource_package::GlobalResources, rendering::utilities::{anim_texture::AnimatedTexture, map_render::MapRenderer}, }; #[derive(Debug)] pub struct TestFoxScene { fox_animation: AnimatedTexture, - world_map: MapRenderer + world_map: MapRenderer, + camera: Camera2D, } impl TestFoxScene { @@ -22,9 +24,24 @@ impl TestFoxScene { let fox = AnimatedTexture::new(raylib_handle, thread, "chr", "testFox").unwrap(); // Load the map - let map_renderer = MapRenderer::new("map_gameMap.tmx").unwrap(); + let map_renderer = MapRenderer::new("map_gameMap.tmx", raylib_handle, thread).unwrap(); - Self { fox_animation: fox, world_map: map_renderer } + // Create a camera + let camera = Camera2D { + target: Vector2 { x: 0.0, y: 0.0 }, + offset: Vector2 { + x: raylib_handle.get_screen_width() as f32, + y: (raylib_handle.get_screen_height() as f32) * -0.5, + }, + rotation: 0.0, + zoom: 1.0, + }; + + Self { + fox_animation: fox, + world_map: map_renderer, + camera, + } } /// Handler for each frame @@ -50,5 +67,27 @@ impl TestFoxScene { None, None, ); + + // Allow the camera to be moved with wasd + if draw.is_key_down(KeyboardKey::KEY_W) { + self.camera.target.y -= 5.0; + } + if draw.is_key_down(KeyboardKey::KEY_S) { + self.camera.target.y += 5.0; + } + if draw.is_key_down(KeyboardKey::KEY_A) { + self.camera.target.x -= 5.0; + } + if draw.is_key_down(KeyboardKey::KEY_D) { + self.camera.target.x += 5.0; + } + + { + // Begin camera mode + let mut ctx2d = draw.begin_mode2D(self.camera); + + // Render the map + self.world_map.render_map(&mut ctx2d, &self.camera, true); + } } }