From 59e840cc259094c4a87b938b776c2c77fbbdd647 Mon Sep 17 00:00:00 2001 From: Berack96 Date: Mon, 20 May 2024 22:32:09 +0200 Subject: [PATCH] Color to terminal --- src/es03_game/cell.rs | 18 ++++++++- src/es03_game/config.rs | 2 +- src/es03_game/entities.rs | 14 +++++++ src/es03_game/mod.rs | 84 +++++++++++++++++++++++++-------------- 4 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/es03_game/cell.rs b/src/es03_game/cell.rs index 97628f0..9265676 100644 --- a/src/es03_game/cell.rs +++ b/src/es03_game/cell.rs @@ -1,4 +1,7 @@ -use super::{entities::{Action, Direction, Entity}, floor::Floor}; +use super::{ + entities::{Action, Direction, Entity}, + floor::Floor, +}; use dyn_clone::{clone_trait_object, DynClone}; use rand::Rng; use serde::{Deserialize, Serialize}; @@ -45,7 +48,7 @@ impl Cell { match self { Cell::Entance => ' ', Cell::Exit => '¤', - Cell::Special(_) => '§', + Cell::Special(effect) => effect.as_char(), Cell::Wall => '█', Cell::Empty => ' ', } @@ -82,6 +85,10 @@ pub trait Effect: DynClone + core::fmt::Debug { /// Tramite l'entità si può anche accedere al piano dove si trova per /// poter modificare eventualmente qualcosa. fn apply_to(&self, entity: &mut Entity, floor: &mut Floor); + /// Ritorna un carattere che rappresenta l'effetto. + fn as_char(&self) -> char { + '?' + } } clone_trait_object!(Effect); @@ -99,6 +106,13 @@ impl Effect for InstantDamage { fn apply_to(&self, entity: &mut Entity, _floor: &mut Floor) { entity.apply_damage(self.0); } + fn as_char(&self) -> char { + if self.0 <= 0 { + '+' + } else { + '-' + } + } } /// Permettere di infliggere lo stato di confuzione ad una entità.\ diff --git a/src/es03_game/config.rs b/src/es03_game/config.rs index 1028c11..06a62d9 100644 --- a/src/es03_game/config.rs +++ b/src/es03_game/config.rs @@ -89,7 +89,7 @@ impl Default for Config { priority: 1, }, ConfigEffect { - effect: Box::new(InstantDamage(-20)), + effect: Box::new(InstantDamage(-10)), floors: 0..255, priority: 1, }, diff --git a/src/es03_game/entities.rs b/src/es03_game/entities.rs index b23647b..7696638 100644 --- a/src/es03_game/entities.rs +++ b/src/es03_game/entities.rs @@ -138,6 +138,16 @@ impl Entity { self.health } + /// Restituisce il valore della vita massima dell'entità.\ + pub fn get_health_max(&self) -> i32 { + self.health_max + } + + /// Restituisce il valore del nome dell'entità.\ + pub fn get_name(&self) -> &String { + &self.name + } + /// Applica il valore inserito come danno alla vita.\ /// Nel caso in cui il danno sia negativo allora verrà interpretato come cura.\ /// Nel caso in cui la vita sia negativa la logica sarà inversa.\ @@ -176,6 +186,10 @@ impl Entity { } self.compute_effects(floor); + if !self.is_alive() { + self.behavior.you_died(floor.get_limited_view_floor(self)); + return false + } true } diff --git a/src/es03_game/mod.rs b/src/es03_game/mod.rs index 307fa11..db53c94 100644 --- a/src/es03_game/mod.rs +++ b/src/es03_game/mod.rs @@ -1,7 +1,7 @@ use self::{ cell::Cell, config::Config, - entities::{Action, Behavior, Direction}, + entities::{Action, Behavior, Direction, Entity}, floor::FloorView, game::Dungeon, }; @@ -60,60 +60,84 @@ pub fn run_console(player: String, seed: u64) { } } -/// Implementazione di una possibile interfaccia console. +const COLOR_RESET: &str = "\x1b[0m"; +const COLOR_EFFECT: &str = "\x1b[95m"; +const COLOR_ENEMY: &str = "\x1b[38;5;1m"; +const COLOR_PLAYER: &str = "\x1b[38;5;166m"; +const COLOR_PLAYER_HEALTH: &str = "\x1b[31m"; + +/// Implementazione di una possibile interfaccia console.\ +/// Ha fin troppi metodi per far vedere in modo carino il gioco, ma comunque la parte importante +/// è l'implementazione del Behavior. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ConsoleInput; impl ConsoleInput { - fn print_floor(&self, floor: FloorView, other:String) { + /// todo!() add docs + fn print_floor(&self, floor: FloorView, other: String) { let mut term = console::Term::stdout(); let _ = term.clear_screen(); let _ = term.write_fmt(format_args!( - "{}{}\n{}\n", + "{}Floor lv.{:2} - {}\n{other}\n", Self::floor_as_string(&floor), - floor.entity, - other + floor.floor.get_level(), + Self::entity_as_string(floor.entity), )); } /// todo!() add docs + fn entity_as_string(entity: &Entity) -> String { + let times = 20; + let health_bar = (entity.get_health() * times) / entity.get_health_max(); + + let filled = "■".repeat(health_bar as usize); + let empty = " ".repeat((times - health_bar) as usize); + format!( + "{}: [{COLOR_PLAYER_HEALTH}{filled}{empty}{COLOR_RESET}] {:4}/{:4}", + entity.get_name(), + entity.get_health(), + entity.get_health_max() + ) + } + /// todo!() add docs fn floor_as_string(floor: &FloorView) -> String { let view = 5; let size = (2 * view) * 3; - let iter = floor.get_grid(view).flat_map(|iter| { - iter.flat_map(|view| { + let iter = floor.get_grid(view).map(|iter| { + iter.map(|view| { if let Some(e) = view.entity { - return [' ', e.direction.as_char(), ' '].into_iter(); + let color = if floor.entity.position == e.position { + COLOR_PLAYER + } else { + COLOR_ENEMY + }; + return format!("{} {} {COLOR_RESET}", color, e.direction.as_char()); } - let ch = view.cell.as_char(); + let cell = view.cell.as_char(); match view.cell { - Cell::Wall => [ch, ch, ch], - _ => [' ', ch, ' '], + Cell::Special(_) => format!("{COLOR_EFFECT} {cell} {COLOR_RESET}"), + Cell::Wall => format!("{cell}{cell}{cell}"), + _ => format!(" {cell} "), } - .into_iter() }) + .collect() }); Self::box_of(size, iter).collect() } /// todo!() add docs - fn box_of(size: usize, iter: impl Iterator) -> impl Iterator { - std::iter::once('╔') - .chain(std::iter::repeat('═').take(size + 2)) - .chain(['╗', '\n'].into_iter()) - .chain(iter.enumerate().flat_map(move |(i, c)| { - let modulo = i % size; - if modulo == 0 { - vec!['║', ' ', c] - } else if modulo == size - 1 { - vec![c, ' ', '║', '\n'] - } else { - vec![c] - } - .into_iter() + fn box_of(size: usize, iter: impl Iterator) -> impl Iterator { + std::iter::once("╔".to_string()) + .chain(std::iter::repeat("═".to_string()).take(size + 2)) + .chain(std::iter::once("╗\n".to_string())) + .chain(iter.map(|string| { + std::iter::once("║ ".to_string()) + .chain(std::iter::once(string)) + .chain(std::iter::once(" ║\n".to_string())) + .collect() })) - .chain(std::iter::once('╚')) - .chain(std::iter::repeat('═').take(size + 2)) - .chain(['╝', '\n'].into_iter()) + .chain(std::iter::once("╚".to_string())) + .chain(std::iter::repeat("═".to_string()).take(size + 2)) + .chain(std::iter::once("╝\n".to_string())) } } #[typetag::serde]