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 dyn_clone::{clone_trait_object, DynClone};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -45,7 +48,7 @@ impl Cell {
|
|||||||
match self {
|
match self {
|
||||||
Cell::Entance => ' ',
|
Cell::Entance => ' ',
|
||||||
Cell::Exit => '¤',
|
Cell::Exit => '¤',
|
||||||
Cell::Special(_) => '§',
|
Cell::Special(effect) => effect.as_char(),
|
||||||
Cell::Wall => '█',
|
Cell::Wall => '█',
|
||||||
Cell::Empty => ' ',
|
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
|
/// Tramite l'entità si può anche accedere al piano dove si trova per
|
||||||
/// poter modificare eventualmente qualcosa.
|
/// poter modificare eventualmente qualcosa.
|
||||||
fn apply_to(&self, entity: &mut Entity, floor: &mut Floor);
|
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);
|
clone_trait_object!(Effect);
|
||||||
|
|
||||||
@@ -99,6 +106,13 @@ impl Effect for InstantDamage {
|
|||||||
fn apply_to(&self, entity: &mut Entity, _floor: &mut Floor) {
|
fn apply_to(&self, entity: &mut Entity, _floor: &mut Floor) {
|
||||||
entity.apply_damage(self.0);
|
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à.\
|
/// Permettere di infliggere lo stato di confuzione ad una entità.\
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ impl Default for Config {
|
|||||||
priority: 1,
|
priority: 1,
|
||||||
},
|
},
|
||||||
ConfigEffect {
|
ConfigEffect {
|
||||||
effect: Box::new(InstantDamage(-20)),
|
effect: Box::new(InstantDamage(-10)),
|
||||||
floors: 0..255,
|
floors: 0..255,
|
||||||
priority: 1,
|
priority: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -138,6 +138,16 @@ impl Entity {
|
|||||||
self.health
|
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.\
|
/// 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 il danno sia negativo allora verrà interpretato come cura.\
|
||||||
/// Nel caso in cui la vita sia negativa la logica sarà inversa.\
|
/// Nel caso in cui la vita sia negativa la logica sarà inversa.\
|
||||||
@@ -176,6 +186,10 @@ impl Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.compute_effects(floor);
|
self.compute_effects(floor);
|
||||||
|
if !self.is_alive() {
|
||||||
|
self.behavior.you_died(floor.get_limited_view_floor(self));
|
||||||
|
return false
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use self::{
|
use self::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
config::Config,
|
config::Config,
|
||||||
entities::{Action, Behavior, Direction},
|
entities::{Action, Behavior, Direction, Entity},
|
||||||
floor::FloorView,
|
floor::FloorView,
|
||||||
game::Dungeon,
|
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)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct ConsoleInput;
|
pub struct ConsoleInput;
|
||||||
impl ConsoleInput {
|
impl ConsoleInput {
|
||||||
|
/// todo!() add docs
|
||||||
fn print_floor(&self, floor: FloorView, other: String) {
|
fn print_floor(&self, floor: FloorView, other: String) {
|
||||||
let mut term = console::Term::stdout();
|
let mut term = console::Term::stdout();
|
||||||
let _ = term.clear_screen();
|
let _ = term.clear_screen();
|
||||||
let _ = term.write_fmt(format_args!(
|
let _ = term.write_fmt(format_args!(
|
||||||
"{}{}\n{}\n",
|
"{}Floor lv.{:2} - {}\n{other}\n",
|
||||||
Self::floor_as_string(&floor),
|
Self::floor_as_string(&floor),
|
||||||
floor.entity,
|
floor.floor.get_level(),
|
||||||
other
|
Self::entity_as_string(floor.entity),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// todo!() add docs
|
/// 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 {
|
fn floor_as_string(floor: &FloorView) -> String {
|
||||||
let view = 5;
|
let view = 5;
|
||||||
let size = (2 * view) * 3;
|
let size = (2 * view) * 3;
|
||||||
let iter = floor.get_grid(view).flat_map(|iter| {
|
let iter = floor.get_grid(view).map(|iter| {
|
||||||
iter.flat_map(|view| {
|
iter.map(|view| {
|
||||||
if let Some(e) = view.entity {
|
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 {
|
match view.cell {
|
||||||
Cell::Wall => [ch, ch, ch],
|
Cell::Special(_) => format!("{COLOR_EFFECT} {cell} {COLOR_RESET}"),
|
||||||
_ => [' ', ch, ' '],
|
Cell::Wall => format!("{cell}{cell}{cell}"),
|
||||||
|
_ => format!(" {cell} "),
|
||||||
}
|
}
|
||||||
.into_iter()
|
|
||||||
})
|
})
|
||||||
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
Self::box_of(size, iter).collect()
|
Self::box_of(size, iter).collect()
|
||||||
}
|
}
|
||||||
/// todo!() add docs
|
/// todo!() add docs
|
||||||
fn box_of(size: usize, iter: impl Iterator<Item = char>) -> impl Iterator<Item = char> {
|
fn box_of(size: usize, iter: impl Iterator<Item = String>) -> impl Iterator<Item = String> {
|
||||||
std::iter::once('╔')
|
std::iter::once("╔".to_string())
|
||||||
.chain(std::iter::repeat('═').take(size + 2))
|
.chain(std::iter::repeat("═".to_string()).take(size + 2))
|
||||||
.chain(['╗', '\n'].into_iter())
|
.chain(std::iter::once("╗\n".to_string()))
|
||||||
.chain(iter.enumerate().flat_map(move |(i, c)| {
|
.chain(iter.map(|string| {
|
||||||
let modulo = i % size;
|
std::iter::once("║ ".to_string())
|
||||||
if modulo == 0 {
|
.chain(std::iter::once(string))
|
||||||
vec!['║', ' ', c]
|
.chain(std::iter::once(" ║\n".to_string()))
|
||||||
} else if modulo == size - 1 {
|
.collect()
|
||||||
vec![c, ' ', '║', '\n']
|
|
||||||
} else {
|
|
||||||
vec![c]
|
|
||||||
}
|
|
||||||
.into_iter()
|
|
||||||
}))
|
}))
|
||||||
.chain(std::iter::once('╚'))
|
.chain(std::iter::once("╚".to_string()))
|
||||||
.chain(std::iter::repeat('═').take(size + 2))
|
.chain(std::iter::repeat("═".to_string()).take(size + 2))
|
||||||
.chain(['╝', '\n'].into_iter())
|
.chain(std::iter::once("╝\n".to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[typetag::serde]
|
#[typetag::serde]
|
||||||
|
|||||||
Reference in New Issue
Block a user