Color to terminal
This commit is contained in:
@@ -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à.\
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Item = char>) -> impl Iterator<Item = char> {
|
||||
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<Item = String>) -> impl Iterator<Item = String> {
|
||||
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]
|
||||
|
||||
Reference in New Issue
Block a user