diff --git a/game/dist/assets/env/env_testObject/env_testObject.json b/game/dist/assets/env/env_testObject/env_testObject.json index 1e1cbfa6..0655307a 100644 --- a/game/dist/assets/env/env_testObject/env_testObject.json +++ b/game/dist/assets/env/env_testObject/env_testObject.json @@ -6,15 +6,7 @@ "top_texture": { "file_path": "assets/env/env_testObject/env_testObjectTop.png" }, - "footprint": [ - { - "position": [ - 0, - 0 - ], - "radius": 256.0 - } - ], + "footprint_radius": 128.0, "physics_colliders": [ { "position": [ diff --git a/game/game_logic/src/model/world_object.rs b/game/game_logic/src/model/world_object.rs index ffad27a3..2a540451 100644 --- a/game/game_logic/src/model/world_object.rs +++ b/game/game_logic/src/model/world_object.rs @@ -37,7 +37,8 @@ pub struct WorldObject { /// The object's top texture pub top_texture: Option, /// colliders describing the object's footprint - pub footprint: Vec, + // pub footprint: Vec, + pub footprint_radius: Option, /// Colliders for physics pub physics_colliders: Vec, /// Temperature @@ -54,7 +55,7 @@ pub struct WorldObjectRef { pub kind: String, /// Object name pub name: String, - /// Object position. 1,1 being up and to the right + /// Object position (tile-space *not* pixel-space). 1,1 being up and to the right pub position: na::Vector2, /// Object rotation, positive is clockwise pub rotation_radians: f32, diff --git a/game/game_logic/src/rendering/utilities/anim_texture.rs b/game/game_logic/src/rendering/utilities/anim_texture.rs index bbe593de..42bc7dc7 100644 --- a/game/game_logic/src/rendering/utilities/anim_texture.rs +++ b/game/game_logic/src/rendering/utilities/anim_texture.rs @@ -5,7 +5,7 @@ use nalgebra::Vector2; use raylib::{ color::Color, math::Rectangle, - prelude::{RaylibDraw, RaylibDrawHandle}, + prelude::{RaylibDraw, RaylibDrawHandle, RaylibMode2D}, texture::Texture2D, RaylibHandle, RaylibThread, }; @@ -127,7 +127,7 @@ impl AnimatedTexture { #[profiling::function] pub fn render_frame_by_index( &self, - draw_handle: &mut RaylibDrawHandle, + draw_handle: &mut RaylibMode2D, index: usize, position: Vector2, percent_scale: Option>, @@ -186,7 +186,7 @@ impl AnimatedTexture { /// Render the animation based on timestamp pub fn render_automatic( &mut self, - draw_handle: &mut RaylibDrawHandle, + draw_handle: &mut RaylibMode2D, position: Vector2, percent_scale: Option>, origin: Option>, @@ -216,4 +216,11 @@ impl AnimatedTexture { warn!("We somehow got a frame index of None"); } } + + pub fn size(&self) -> Vector2{ + Vector2::new( + self.texture.width as f32, + self.texture.height as f32, + ) + } } diff --git a/game/game_logic/src/rendering/utilities/map_render.rs b/game/game_logic/src/rendering/utilities/map_render.rs index c89c70e4..858571bd 100644 --- a/game/game_logic/src/rendering/utilities/map_render.rs +++ b/game/game_logic/src/rendering/utilities/map_render.rs @@ -131,19 +131,30 @@ impl MapRenderer { }) } - pub fn sample_friction_at(&self, position: na::Vector2) -> f32 { + pub fn sample_friction_at(&self, world_position: na::Vector2) -> f32 { + // Convert to a tile position + let tile_position = na::Vector2::new( + (world_position.x / 128.0).floor() as i32, + (world_position.y / 128.0).floor() as i32, + ); todo!() } - pub fn sample_temperature_at(&self, position: na::Vector2) -> f32 { + pub fn sample_temperature_at(&self, world_position: na::Vector2) -> f32 { + // Convert to a tile position + let tile_position = na::Vector2::new( + (world_position.x / 128.0).floor() as i32, + (world_position.y / 128.0).floor() as i32, + ); todo!() } pub fn render_map( - &self, + &mut self, draw_handle: &mut RaylibMode2D, camera: &Camera2D, show_debug_grid: bool, + player_position: na::Vector2, ) { // Get the window corners in world space let screen_width = draw_handle.get_screen_width(); @@ -206,6 +217,108 @@ impl MapRenderer { ); } + // Check if there is an object at this tile + for obj_ref in &self.world_objects.object_references { + if obj_ref.position.x == sampler_x as f32 + && obj_ref.position.y == sampler_y as f32 + { + // Get access to the actual object definition + let object_key = + format!("{}:{}", obj_ref.kind, obj_ref.name); + let obj_def = self + .world_objects + .object_definitions + .get(&object_key) + .unwrap(); + + // We need to render the base layer of the object + if obj_def.bottom_texture.animated.unwrap_or(false) { + let tex = self + .world_objects + .bottom_animated_textures + .get_mut(&object_key) + .unwrap(); + tex.render_automatic( + draw_handle, + obj_ref.position - (tex.size() / 2.0), + None, + None, + Some(obj_ref.rotation_radians), + None, + ); + } else { + let tex = self + .world_objects + .bottom_static_textures + .get_mut(&object_key) + .unwrap(); + let p: Vector2 = obj_ref.position.into(); + draw_handle.draw_texture_ex( + &tex, + p - Vector2::new( + tex.width as f32 / 2.0, + tex.height as f32 / 2.0, + ), + obj_ref.rotation_radians, + 1.0, + Color::WHITE, + ); + } + + // If needed we can render the top layer of the object + if let Some(top_texture) = &obj_def.top_texture { + // We need to detect if the player is in the footprint of the object + let mut tint = Color::WHITE; + if let Some(footprint_radius) = + obj_def.footprint_radius + { + let player_dist_to_object = + (obj_ref.position - player_position).norm(); + // debug!( + // "Player dist to object: {}", + // player_dist_to_object + // ); + if player_dist_to_object <= footprint_radius { + tint.a = 128; + } + } + + if top_texture.animated.unwrap_or(false) { + let tex = self + .world_objects + .top_animated_textures + .get_mut(&object_key) + .unwrap(); + tex.render_automatic( + draw_handle, + obj_ref.position - (tex.size() / 2.0), + None, + None, + Some(obj_ref.rotation_radians), + Some(tint), + ); + } else { + let tex = self + .world_objects + .top_static_textures + .get_mut(&object_key) + .unwrap(); + let p: Vector2 = obj_ref.position.into(); + draw_handle.draw_texture_ex( + &tex, + p - Vector2::new( + tex.width as f32 / 2.0, + tex.height as f32 / 2.0, + ), + obj_ref.rotation_radians, + 1.0, + tint, + ); + } + } + } + } + if show_debug_grid { draw_handle.draw_rectangle_lines( tile_x * tile_width as i32, diff --git a/game/game_logic/src/scenes/test_fox.rs b/game/game_logic/src/scenes/test_fox.rs index 38bfdb06..a4d19043 100644 --- a/game/game_logic/src/scenes/test_fox.rs +++ b/game/game_logic/src/scenes/test_fox.rs @@ -36,8 +36,8 @@ impl TestFoxScene { 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, + x: raylib_handle.get_screen_width() as f32 * 0.5, + y: (raylib_handle.get_screen_height() as f32) * 0.5, }, rotation: 0.0, zoom: 1.0, @@ -64,15 +64,15 @@ impl TestFoxScene { // Clear the screen draw.clear_background(Color::WHITE); - // Render the fox - self.fox_animation.render_automatic( - &mut draw, - na::Vector2::new(0.0, 0.0), - None, - None, - None, - None, - ); + // // Render the fox + // self.fox_animation.render_automatic( + // &mut draw, + // na::Vector2::new(0.0, 0.0), + // None, + // None, + // None, + // None, + // ); // Allow the camera to be moved with wasd if draw.is_key_down(KeyboardKey::KEY_W) { @@ -93,7 +93,19 @@ impl TestFoxScene { let mut ctx2d = draw.begin_mode2D(self.camera); // Render the map - self.world_map.render_map(&mut ctx2d, &self.camera, true); + self.world_map.render_map( + &mut ctx2d, + &self.camera, + true, + na::Vector2::new(self.camera.target.x, self.camera.target.y).into(), + ); } + + draw.draw_circle( + draw.get_screen_width() / 2, + draw.get_screen_height() / 2, + 4.0, + Color::RED, + ); } }