diff options
| author | Freya Murphy <freya@freyacat.org> | 2025-11-10 09:24:31 -0500 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2025-11-10 09:24:31 -0500 |
| commit | f9f8dbba005bd5658e4848f5272ea32524fa19da (patch) | |
| tree | 76a82c57fddbf75aad60adfc04b47697167c9080 /graphics | |
| parent | main: hallway color change (diff) | |
| download | DungeonCrawl-f9f8dbba005bd5658e4848f5272ea32524fa19da.tar.gz DungeonCrawl-f9f8dbba005bd5658e4848f5272ea32524fa19da.tar.bz2 DungeonCrawl-f9f8dbba005bd5658e4848f5272ea32524fa19da.zip | |
graphics: fix atlas rendering offset bug, and make minimap scalable past 48px
Diffstat (limited to 'graphics')
| -rw-r--r-- | graphics/src/render.rs | 170 |
1 files changed, 89 insertions, 81 deletions
diff --git a/graphics/src/render.rs b/graphics/src/render.rs index 1c936bd..8e5869a 100644 --- a/graphics/src/render.rs +++ b/graphics/src/render.rs @@ -9,7 +9,7 @@ use raylib::{ camera::Camera2D, color::Color, math::{Rectangle, Vector2}, - prelude::{RaylibDraw, RaylibMode2DExt, RaylibTextureModeExt}, + prelude::{RaylibDraw, RaylibMode2DExt, RaylibScissorModeExt, RaylibTextureModeExt}, texture::{RaylibTexture2D, RenderTexture2D, Texture2D}, }; @@ -269,7 +269,7 @@ impl Renderer { where R: RaylibDraw + RaylibMode2DExt, { - let camera = render_camera(dungeon); + let camera = dungeon.render_camera(); let mut rc = r.begin_mode2D(camera); self.draw_bg_tilemap(&mut rc); self.draw_entities(&mut rc, dungeon); @@ -425,8 +425,8 @@ impl Renderer { { r.draw_tilemap( &self.tilemap_fg, - 0, - 0, + 0u16, + 0u16, TILE_SIZE / TEXTURE_SIZE, WALL_HEIGHT, ); @@ -437,7 +437,7 @@ impl Renderer { where R: RaylibDraw, { - r.draw_tilemap(&self.tilemap_bg, 0, 0, TILE_SIZE / TEXTURE_SIZE, 0); + r.draw_tilemap(&self.tilemap_bg, 0u16, 0u16, TILE_SIZE / TEXTURE_SIZE, 0); } /// Draws the entities on the map @@ -469,12 +469,12 @@ impl Renderer { Direction::West => (1, 1), }; let dest_rec = rect! { - fx * size - size/2.0, - fy * size - size/2.0, + fx * size, + fy * size, size, size, }; - r.draw_inv_atlas(texture, (ax, ay), dest_rec.x, dest_rec.y, size, 0.0); + r.draw_atlas(texture, (ax, ay), dest_rec.x, dest_rec.y, size, 0.0); if self.debug { r.draw_rectangle_lines_ex(dest_rec, 1.0, Color::YELLOW); @@ -503,7 +503,7 @@ impl Renderer { /// Draw in game minimap fn draw_minimap<R>(&self, r: &mut R, dungeon: &Dungeon) where - R: RaylibDraw, + R: RaylibDraw + RaylibScissorModeExt, { const Y: u16 = UI_PADDING; @@ -511,23 +511,47 @@ impl Renderer { const TEXT_X: u16 = UI_PADDING; self.draw_text_vertical(r, b"MAP", TEXT_X, Y); - // Draw minimap in top left of UI bar + // Base coords for the minimap const MINIMAP_X: u16 = TEXT_X + FONT_SIZE + UI_PADDING; - r.draw_tilemap(&self.tilemap_mm, MINIMAP_X, Y, 1, 0); + const MAX_MINIMAP_SIZE: u16 = FONT_SIZE * 3; + const EXTRA_PIXELS: u16 = MAP_SIZE.saturating_sub(MAX_MINIMAP_SIZE) + 1; - // Draw minimap entity's - let mut draw_dot = |pos: Pos, color| { - let (x, y) = pos.xy(); - r.draw_pixel((MINIMAP_X + x).into(), (Y + y).into(), color); - }; + // Get the real coords of the minimap (offset) + let offset_x = (dungeon.player.entity.pos.x() / (MAP_SIZE / EXTRA_PIXELS)) + .saturating_sub(MAX_MINIMAP_SIZE / 2); + let offset_y = (dungeon.player.entity.pos.y() / (MAP_SIZE / EXTRA_PIXELS)) + .saturating_sub(MAX_MINIMAP_SIZE / 2); + let minimap_x = MINIMAP_X.cast_signed() - offset_x.cast_signed(); + let minimap_y = Y.cast_signed() - offset_y.cast_signed(); - // Draw enemy dots - for enemy in &dungeon.enemies { - draw_dot(enemy.pos, Color::RED); - } + // Draw in scissor mode incase the map size is too big + { + let mut rs = r.begin_scissor_mode( + MINIMAP_X.into(), + Y.into(), + MAX_MINIMAP_SIZE.into(), + MAX_MINIMAP_SIZE.into(), + ); + rs.draw_tilemap(&self.tilemap_mm, minimap_x, minimap_y, 1, 0); + + // Draw minimap entity's + let mut draw_dot = |pos: Pos, color| { + let (x, y) = pos.xy(); + rs.draw_pixel( + (minimap_x + x.cast_signed()).into(), + (minimap_y + y.cast_signed()).into(), + color, + ); + }; + + // Draw enemy dots + for enemy in &dungeon.enemies { + draw_dot(enemy.pos, Color::RED); + } - // Draw player dot - draw_dot(dungeon.player.entity.pos, Color::LIME); + // Draw player dot + draw_dot(dungeon.player.entity.pos, Color::LIME); + } } /// Draws the player's inventory @@ -558,7 +582,7 @@ impl Renderer { let slot_x = SLOTS_X + SLOT_LEN * idx; // Draw slot container - r.draw_inv_atlas( + r.draw_atlas( &self.textures.atlas, ATLAS_INV_CONTAINER, slot_x, @@ -597,7 +621,7 @@ impl Renderer { let damage = 0; // TODO: calc damage const TEXT_WIDTH: u16 = FONT_SIZE * 3 + UI_PADDING; - const ICON_WIDTH: u16 = FONT_SIZE + UI_PADDING; + const ICON_WIDTH: u16 = FONT_SIZE; const ICON_X: u16 = RENDER_WIDTH - TEXT_WIDTH - ICON_WIDTH; const TEXT_X: u16 = RENDER_WIDTH - TEXT_WIDTH; @@ -606,9 +630,9 @@ impl Renderer { r.draw_atlas( &self.textures.atlas, ATLAS_HEART_ICON, - ICON_X + UI_PADDING, - HEART_Y + UI_PADDING, - FONT_SIZE, + ICON_X, + HEART_Y, + ICON_WIDTH, 0.0, ); draw_text!(self, r, TEXT_X, HEART_Y, "x{health:02}"); @@ -618,9 +642,9 @@ impl Renderer { r.draw_atlas( &self.textures.atlas, ATLAS_DAMAGE_ICON, - ICON_X + UI_PADDING, - DAMAGE_Y + UI_PADDING, - FONT_SIZE, + ICON_X, + DAMAGE_Y, + ICON_WIDTH, 0.0, ); draw_text!(self, r, TEXT_X, DAMAGE_Y, "x{damage:02}"); @@ -696,7 +720,7 @@ impl Renderer { } let ax = char % 16; let ay = (char - 32) / 16; - r.draw_inv_atlas( + r.draw_atlas( &self.textures.font, (ax.into(), ay.into()), x, @@ -707,30 +731,35 @@ impl Renderer { } } -/// Returns the Raylib Camera setup with needed 2D position/transforms -fn render_camera(dungeon: &Dungeon) -> Camera2D { - /// The minimum position the camera is allowed to go - const CAMERA_MIN: Vector2 = vec2! { - RENDER_WIDTH/2, RENDER_HEIGHT/2 - UI_HEIGHT/2, - }; - /// The maximum position the camera is allowed to go - const CAMERA_MAX: Vector2 = vec2! { - MAP_SIZE * TILE_SIZE - RENDER_WIDTH/2, - MAP_SIZE * TILE_SIZE - RENDER_HEIGHT/2 - UI_HEIGHT/2, - }; +trait DungeonExt { + fn render_camera(&self) -> Camera2D; +} +impl DungeonExt for Dungeon { + /// Returns the Raylib Camera setup with needed 2D position/transforms + fn render_camera(&self) -> Camera2D { + /// The minimum position the camera is allowed to go + const CAMERA_MIN: Vector2 = vec2! { + RENDER_WIDTH/2, RENDER_HEIGHT/2 - UI_HEIGHT/2, + }; + /// The maximum position the camera is allowed to go + const CAMERA_MAX: Vector2 = vec2! { + MAP_SIZE * TILE_SIZE - RENDER_WIDTH/2, + MAP_SIZE * TILE_SIZE - RENDER_HEIGHT/2 - UI_HEIGHT/2, + }; - let pos = dungeon.camera(); - Camera2D { - target: Vector2::from(pos.xy()) - .scale_by(TILE_SIZE.into()) - .max(CAMERA_MIN) - .min(CAMERA_MAX), - offset: vec2! { - RENDER_WIDTH/2, - RENDER_HEIGHT/2 + UI_HEIGHT/2, - }, - rotation: 0.0, - zoom: 1.0, + let pos = self.camera(); + Camera2D { + target: Vector2::from(pos.xy()) + .scale_by(TILE_SIZE.into()) + .max(CAMERA_MIN) + .min(CAMERA_MAX), + offset: vec2! { + RENDER_WIDTH/2 - TILE_SIZE/2, + RENDER_HEIGHT/2 - TILE_SIZE/2 + UI_HEIGHT/2, + }, + rotation: 0.0, + zoom: 1.0, + } } } @@ -770,8 +799,8 @@ where TEXTURE_SIZE, }; let dest_rec = rect! { - x.into(), - y.into(), + x.into() + size_into/2.0, + y.into() + size_into/2.0, size_into, size_into, }; @@ -789,33 +818,12 @@ where ); } - /// Draw in INV element from an atlas - fn draw_inv_atlas( - &mut self, - tex: &Texture2D, - (ax, ay): (u16, u16), - x: impl Into<f32>, - y: impl Into<f32>, - size: impl Into<f32>, - rotation: impl Into<f32>, - ) { - let size_into = size.into(); - self.draw_atlas( - tex, - (ax, ay), - x.into() + size_into / 2.0, - y.into() + size_into / 2.0, - size_into, - rotation, - ); - } - /// Draw dungeon tiles helper function fn draw_tilemap( &mut self, tex: &RenderTexture2D, - x: u16, - y: u16, + x: impl Into<i32>, + y: impl Into<i32>, scale: u16, offset: u16, ) { @@ -828,8 +836,8 @@ where -height.cast_signed(), }; let dest_rec = rect! { - x, - y.cast_signed() - (offset * scale).cast_signed(), + x.into(), + y.into() - (offset * scale) as i32, width * scale, height * scale, }; |