From e64742a1596444dc6e5fe3ae0bae2325e079c1c0 Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Thu, 11 Apr 2024 14:15:59 +0200 Subject: [PATCH] Placeholder castle --- Cargo.lock | 4 +- assets/images/castle.png | Bin 0 -> 23114 bytes src/main.rs | 200 ++++++++++++++++++++++++--------------- src/rect_helper.rs | 71 ++++++++------ 4 files changed, 165 insertions(+), 110 deletions(-) create mode 100644 assets/images/castle.png diff --git a/Cargo.lock b/Cargo.lock index 95c29e1..99eb40e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1599,9 +1599,9 @@ checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] diff --git a/assets/images/castle.png b/assets/images/castle.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf7ef0dfe9fc73c82c7bf7f5c13c1feb9586920 GIT binary patch literal 23114 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�-s9c5*yn1(Pa?*CgGQ_kn7>w}j{59d2%Ukq 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 literal 0 HcmV?d00001 diff --git a/src/main.rs b/src/main.rs index b7455e3..4b80158 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,8 @@ #![allow( clippy::cast_possible_truncation, clippy::cast_sign_loss, - clippy::too_many_lines + clippy::too_many_lines, + clippy::module_name_repetitions )] mod card; @@ -24,15 +25,48 @@ use player::{Player, Stats}; fn main() { nannou::app(Model::init) .update(update) - .loop_mode(LoopMode::RefreshSync) + .loop_mode(LoopMode::Wait) .run(); } +struct Textures { + ant: wgpu::Texture, + castle: wgpu::Texture, +} + +impl Textures { + fn load(app: &App) -> Self { + let ant = wgpu::Texture::from_image( + app, + &image::load_from_memory_with_format( + include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/images/ant.png" + )), + ImageFormat::Png, + ) + .expect("Failed to load image"), + ); + let castle = wgpu::Texture::from_image( + app, + &image::load_from_memory_with_format( + include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/images/castle.png" + )), + ImageFormat::Png, + ) + .expect("Failed to load image"), + ); + Self { ant, castle } + } +} + struct Model { // Store the window ID so we can refer to this specific window later if needed. window: WindowId, font: Font, - texture: wgpu::Texture, + textures: Textures, ups: f64, just_clicked: RwLock, red_hand: RwLock<[Card; HAND_CARD_COUNT]>, @@ -53,20 +87,9 @@ impl Model { .build() .unwrap(); - let texture = wgpu::Texture::from_image( - app, - &image::load_from_memory_with_format( - include_bytes!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/assets/images/ant.png" - )), - ImageFormat::Png, - ) - .expect("Failed to load image"), - ); Self { window, - texture, + textures: Textures::load(app), font: Font::from_bytes(include_bytes!(concat!( env!("CARGO_MANIFEST_DIR"), "/assets/fonts/Monocraft/Monocraft-NF.ttf" @@ -136,56 +159,88 @@ const HAND_CARD_COUNT: usize = 8; const HAND_ASPECT_WIDTH: f32 = 1f32; const HAND_ASPECT_HEIGHT: f32 = 2f32; // Draw the state of your `Model` into the given `Frame` here. - -fn player_panel( - draw: &Draw, - bounds: Rect, - player_stats: &RwLock, - player: Player, - font: Font, -) { - let rect = Rect::from_x_y_w_h(bounds.x(), bounds.y(), 1f32, 5f32).fit_into(&bounds); - let rect = match player { - Player::Red => rect.align_right_of(bounds), - Player::Black => rect.align_left_of(bounds), +fn player_panel(model: &Model, draw: &Draw, bounds: Rect, player: Player) { + let part_bounds = bounds.part_horizontal(match player { + Player::Red => 0.8, + Player::Black => 0.2, + }); + let [castle_bounds, status_bounds] = match player { + Player::Red => part_bounds, + Player::Black => [part_bounds[1], part_bounds[0]], }; - let player_stats = player_stats.read().expect("player stats poisoned"); + let castle_bounds = castle_bounds.top_part(0.7); + let castle_rect = Rect::from_x_y_w_h( + castle_bounds.x(), + castle_bounds.y(), + model.textures.castle.width() as f32, + model.textures.castle.height() as f32, + ) + .fit_into(castle_bounds); + draw.texture(&model.textures.castle) + .xy(castle_rect.xy()) + .wh(castle_rect.wh()) + .finish(); + let status_rect = status_bounds + .align_left_of(status_bounds) + .align_middle_y_of(status_bounds); + + let player_stats = *model + .stats_of(player) + .read() + .expect("player stats poisoned"); let status = match player { - Player::Red => format!( - "{:<3} Builders\n{:<5} Bricks\n{:<3} Soldiers\n{:<4} Weapons\n{:<7} Magi\n{:<3} Crystals\n{:<5} Castle\n{:<6} Fence", - player_stats.builders, - player_stats.bricks, - player_stats.soldiers, - player_stats.weapons, - player_stats.magi, - player_stats.crystals, - player_stats.castle, - player_stats.fence, - ), - Player::Black => format!( - "Builders {:>3}\nBricks {:>5}\nSoldiers {:>3}\nWeapons {:>4}\nMagi {:>7}\nCrystals {:>3}\nCastle {:>5}\nFence {:>6}", - player_stats.builders, - player_stats.bricks, - player_stats.soldiers, - player_stats.weapons, - player_stats.magi, - player_stats.crystals, - player_stats.castle, - player_stats.fence, - ) - }; - drop(player_stats); + Player::Red => format!( + "{:<3} Builders\n{:<5} Bricks\n{:<3} Soldiers\n{:<4} Weapons\n{:<7} Magi\n{:<3} Crystals\n{:<5} Castle\n{:<6} Fence", + player_stats.builders, + player_stats.bricks, + player_stats.soldiers, + player_stats.weapons, + player_stats.magi, + player_stats.crystals, + player_stats.castle, + player_stats.fence, + ), + Player::Black => format!( + "Builders {:>3}\nBricks {:>5}\nSoldiers {:>3}\nWeapons {:>4}\nMagi {:>7}\nCrystals {:>3}\nCastle {:>5}\nFence {:>6}", + player_stats.builders, + player_stats.bricks, + player_stats.soldiers, + player_stats.weapons, + player_stats.magi, + player_stats.crystals, + player_stats.castle, + player_stats.fence, + ) + }; + let character_size = model + .font + .glyph('A') + .standalone() + .get_data() + .expect("No glyph found") + .extents + .unwrap(); + let character_width = character_size.width(); + let character_height = character_size.height(); + + let character_aspect_ratio = character_width as f32 / character_height as f32; + + let font_size = f32::min( + status_bounds.w() / 12f32 / character_aspect_ratio, + status_bounds.h() / 8f32, + ) as u32; + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let drawing = draw .text(&status) - .xy(rect.xy()) - .wh(rect.wh()) + .xy(status_rect.xy()) + .wh(status_rect.wh()) .color(WHITE) - .font_size((rect.h() * 0.02f32).trunc() as u32) + .font_size(font_size) .align_text_middle_y() - .font(font) + .font(model.font.clone()) .color(match player { Player::Red => RED, Player::Black => WHITE, @@ -213,14 +268,14 @@ fn hand( HAND_CARD_COUNT as f32 * HAND_ASPECT_WIDTH, HAND_ASPECT_HEIGHT, ) - .fit_into(&bounds) + .fit_into(bounds) .align_bottom_of(bounds); let current_player = *model .current_player .read() .expect("current player poisoned"); - for (idx, rect) in hand_rect + for (idx, &rect) in hand_rect .split_horizontal::() .iter() .enumerate() @@ -239,11 +294,11 @@ fn hand( let image_rect = Rect::from_x_y_w_h( rect.x(), rect.y(), - model.texture.width() as f32, - model.texture.height() as f32, + model.textures.ant.width() as f32, + model.textures.ant.height() as f32, ) .fit_into(rect) - .align_bottom_of(*rect); + .align_bottom_of(rect); draw.text(&format!( "{:?}\n{}{}", @@ -275,7 +330,7 @@ fn hand( .font(model.font.clone()) .finish(); - draw.texture(&model.texture) + draw.texture(&model.textures.ant) .xy(image_rect.xy()) .wh(image_rect.wh()) .finish(); @@ -339,22 +394,11 @@ fn view(app: &App, model: &Model, frame: Frame) { let window_rect = window.rect(); - let player_one_bounds = window_rect.left_part(0.2); - player_panel( - &draw, - player_one_bounds, - model.stats_of(Player::Black), - Player::Black, - model.font.clone(), - ); - let player_two_bounds = window_rect.right_part(0.2); - player_panel( - &draw, - player_two_bounds, - model.stats_of(Player::Red), - Player::Red, - model.font.clone(), - ); + let [player_one_rect, player_two_rect] = window_rect.split_horizontal::<2>(); + let player_one_bounds = player_one_rect; + player_panel(model, &draw, player_one_bounds, Player::Black); + let player_two_bounds = player_two_rect; + player_panel(model, &draw, player_two_bounds, Player::Red); let hand_bounds = window_rect.bottom_part(0.3); hand( diff --git a/src/rect_helper.rs b/src/rect_helper.rs index f4aa051..2ffd505 100644 --- a/src/rect_helper.rs +++ b/src/rect_helper.rs @@ -1,28 +1,31 @@ -use nannou::geom::Rect; +use nannou::{geom::Rect, math::num_traits::Float}; -pub trait RectHelper { - fn fit_into(&self, bounds: &Rect) -> Rect; +pub trait RectHelper { + fn fit_into(self, bounds: Rect) -> Rect; - fn bottom_half(&self) -> Rect; - fn bottom_part(&self, part: f32) -> Rect; + fn bottom_half(self) -> Rect; + fn bottom_part(self, part: S) -> Rect; - fn top_half(&self) -> Rect; - fn top_part(&self, part: f32) -> Rect; + fn top_half(self) -> Rect; + fn top_part(self, part: S) -> Rect; - fn left_half(&self) -> Rect; - fn left_part(&self, part: f32) -> Rect; + fn left_half(self) -> Rect; + fn left_part(self, part: S) -> Rect; - fn right_half(&self) -> Rect; - fn right_part(&self, part: f32) -> Rect; + fn right_half(self) -> Rect; + fn right_part(self, part: S) -> Rect; - fn split_horizontal(&self) -> [Rect; N]; - fn split_vertical(&self) -> [Rect; N]; - fn split_horizontal_vec(&self, num: usize) -> Vec>; - fn split_vertical_vec(&self, num: usize) -> Vec>; + fn part_horizontal(self, part: S) -> [Rect; 2]; + fn part_vertical(self, part: S) -> [Rect; 2]; + + fn split_horizontal(self) -> [Rect; N]; + fn split_vertical(self) -> [Rect; N]; + fn split_horizontal_vec(self, num: usize) -> Vec>; + fn split_vertical_vec(self, num: usize) -> Vec>; } -impl RectHelper for Rect { - fn fit_into(&self, bounds: &Rect) -> Self { +impl RectHelper for Rect { + fn fit_into(self, bounds: Self) -> Self { let content_aspect_ratio = self.w() / self.h(); let bounds_aspect_ratio = bounds.w() / bounds.h(); @@ -43,11 +46,11 @@ impl RectHelper for Rect { } } - fn bottom_half(&self) -> Self { + fn bottom_half(self) -> Self { Self::from_corners(self.mid_left(), self.bottom_right()) } - fn bottom_part(&self, part: f32) -> Self { + fn bottom_part(self, part: f32) -> Self { debug_assert!((0f32..=1f32).contains(&part)); Self::from_corner_points( [self.left(), self.bottom()], @@ -55,11 +58,11 @@ impl RectHelper for Rect { ) } - fn top_half(&self) -> Self { + fn top_half(self) -> Self { Self::from_corners(self.top_left(), self.mid_right()) } - fn top_part(&self, part: f32) -> Self { + fn top_part(self, part: f32) -> Self { debug_assert!((0f32..=1f32).contains(&part)); Self::from_corner_points( [self.left(), self.top()], @@ -67,11 +70,11 @@ impl RectHelper for Rect { ) } - fn left_half(&self) -> Self { + fn left_half(self) -> Self { Self::from_corners(self.top_left(), self.mid_bottom()) } - fn left_part(&self, part: f32) -> Self { + fn left_part(self, part: f32) -> Self { debug_assert!((0f32..=1f32).contains(&part)); Self::from_corner_points( [self.left(), self.bottom()], @@ -79,11 +82,11 @@ impl RectHelper for Rect { ) } - fn right_half(&self) -> Self { - Self::from_corners(self.top_left(), self.mid_bottom()) + fn right_half(self) -> Self { + Self::from_corners(self.mid_top(), self.bottom_right()) } - fn right_part(&self, part: f32) -> Self { + fn right_part(self, part: f32) -> Self { debug_assert!((0f32..=1f32).contains(&part)); Self::from_corner_points( [self.right(), self.bottom()], @@ -91,8 +94,16 @@ impl RectHelper for Rect { ) } + fn part_horizontal(self, part: f32) -> [Self; 2] { + [self.left_part(part), self.right_part(1f32 - part)] + } + + fn part_vertical(self, part: f32) -> [Self; 2] { + [self.bottom_part(part), self.top_part(1f32 - part)] + } + #[allow(clippy::cast_precision_loss)] - fn split_horizontal(&self) -> [Self; N] { + fn split_horizontal(self) -> [Self; N] { let mut subdivisions = [unsafe { std::mem::zeroed() }; N]; let subdivided_width = self.w() / N as f32; @@ -108,7 +119,7 @@ impl RectHelper for Rect { } #[allow(clippy::cast_precision_loss)] - fn split_horizontal_vec(&self, num: usize) -> Vec { + fn split_horizontal_vec(self, num: usize) -> Vec { let mut subdivisions = Vec::with_capacity(num); let subdivided_width = self.w() / num as f32; @@ -124,7 +135,7 @@ impl RectHelper for Rect { } #[allow(clippy::cast_precision_loss)] - fn split_vertical(&self) -> [Self; N] { + fn split_vertical(self) -> [Self; N] { let mut subdivisions = [unsafe { std::mem::zeroed() }; N]; let subdivided_height = self.h() / N as f32; @@ -140,7 +151,7 @@ impl RectHelper for Rect { } #[allow(clippy::cast_precision_loss)] - fn split_vertical_vec(&self, num: usize) -> Vec { + fn split_vertical_vec(self, num: usize) -> Vec { let mut subdivisions = Vec::with_capacity(num); let subdivided_height = self.h() / num as f32;