We've got color (finally)!
This commit is contained in:
parent
daafe3b023
commit
c6868a7a01
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -108,6 +108,7 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"specs",
|
"specs",
|
||||||
"specs-derive",
|
"specs-derive",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -506,6 +507,26 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tuple_utils"
|
name = "tuple_utils"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
|
@ -13,3 +13,4 @@ rand = "0.8.4"
|
||||||
grid = "0.6.0"
|
grid = "0.6.0"
|
||||||
float-ord = "0.3.2"
|
float-ord = "0.3.2"
|
||||||
pathfinding = "3"
|
pathfinding = "3"
|
||||||
|
thiserror = "1"
|
||||||
|
|
92
src/io.rs
Normal file
92
src/io.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
//! Pancurses boilerplate code.
|
||||||
|
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
|
use pancurses::{
|
||||||
|
endwin, has_colors, init_pair, initscr, noecho, start_color, ColorPair, Window, COLORS,
|
||||||
|
COLOR_PAIRS,
|
||||||
|
};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Initializes the terminal to accept user input, and creates a new
|
||||||
|
/// Window.
|
||||||
|
pub fn init_window() -> Window {
|
||||||
|
// Create a new window over the terminal.
|
||||||
|
let window = initscr();
|
||||||
|
|
||||||
|
// Enable keypad mode (off by default for historical reasons), so
|
||||||
|
// we can read special keycodes other than just characters.
|
||||||
|
window.keypad(true);
|
||||||
|
|
||||||
|
// Disable echoing so the user doesn't see flickering in the
|
||||||
|
// upper-left corner of the screen when they type a character.
|
||||||
|
noecho();
|
||||||
|
|
||||||
|
// // Set up a color palette. TODO
|
||||||
|
// init_colors().unwrap();
|
||||||
|
let c = init_colors();
|
||||||
|
if let Err(e) = c {
|
||||||
|
endwin();
|
||||||
|
println!("{}", e);
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
window
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cleans everything up and exits the game.
|
||||||
|
pub fn quit() -> ! {
|
||||||
|
endwin();
|
||||||
|
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The colors on a terminal.
|
||||||
|
#[allow(unused)]
|
||||||
|
pub enum Color {
|
||||||
|
Black = 0,
|
||||||
|
Red = 1,
|
||||||
|
Green = 2,
|
||||||
|
Brown = 3,
|
||||||
|
Blue = 4,
|
||||||
|
Magenta = 5,
|
||||||
|
Cyan = 6,
|
||||||
|
White = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
enum ColorError {
|
||||||
|
#[error("colors not supported")]
|
||||||
|
NoColors,
|
||||||
|
|
||||||
|
#[error("too few colors (have {0}, need 8)")]
|
||||||
|
NotEnoughColors(u32),
|
||||||
|
|
||||||
|
#[error("too few color slots (have {0}, need 8)")]
|
||||||
|
NotEnoughSlots(u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_colors() -> Result<(), ColorError> {
|
||||||
|
assert_eq!(start_color(), 0);
|
||||||
|
if !has_colors() {
|
||||||
|
Err(ColorError::NoColors)
|
||||||
|
} else if COLORS() < 8 {
|
||||||
|
Err(ColorError::NotEnoughColors(COLORS() as _))
|
||||||
|
} else if COLOR_PAIRS() < 8 {
|
||||||
|
Err(ColorError::NotEnoughSlots(COLOR_PAIRS() as _))
|
||||||
|
} else {
|
||||||
|
for n in 0..8 {
|
||||||
|
init_pair(n, n, Color::Black as _);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_color(win: &Window, c: Color) {
|
||||||
|
// This gets called for every single character; could be a
|
||||||
|
// performance bottleneck depending on how ncurses implements it.
|
||||||
|
if has_colors() {
|
||||||
|
win.attron(ColorPair(c as _));
|
||||||
|
}
|
||||||
|
}
|
11
src/level.rs
11
src/level.rs
|
@ -4,10 +4,7 @@ use pancurses::Window;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{components::{CharRender, Position}, io::{Color, set_color}, rooms};
|
||||||
components::{CharRender, Position},
|
|
||||||
rooms,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The size of a dungeon level, in tiles.
|
/// The size of a dungeon level, in tiles.
|
||||||
pub const LEVEL_SIZE: (usize, usize) = (80, 24);
|
pub const LEVEL_SIZE: (usize, usize) = (80, 24);
|
||||||
|
@ -108,6 +105,12 @@ impl DungeonLevel {
|
||||||
for y in 0..LEVEL_SIZE.1 {
|
for y in 0..LEVEL_SIZE.1 {
|
||||||
win.mv(y as _, 0);
|
win.mv(y as _, 0);
|
||||||
for x in 0..LEVEL_SIZE.0 {
|
for x in 0..LEVEL_SIZE.0 {
|
||||||
|
if (x + y) % 2 == 0 {
|
||||||
|
set_color(win, Color::Cyan);
|
||||||
|
} else {
|
||||||
|
set_color(win, Color::Red);
|
||||||
|
}
|
||||||
|
|
||||||
win.addch(if filter((x as _, y as _)) {
|
win.addch(if filter((x as _, y as _)) {
|
||||||
self.render_tile(x, y)
|
self.render_tile(x, y)
|
||||||
} else {
|
} else {
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -1,15 +1,14 @@
|
||||||
use std::process::exit;
|
|
||||||
|
|
||||||
use components::{register_all, CharRender, MobAction, Mobile, Player, Position, TurnTaker};
|
use components::{register_all, CharRender, MobAction, Mobile, Player, Position, TurnTaker};
|
||||||
|
use io::init_window;
|
||||||
use level::DungeonLevel;
|
use level::DungeonLevel;
|
||||||
|
|
||||||
use pancurses::{endwin, initscr, noecho, Window};
|
|
||||||
use player::player_turn;
|
use player::player_turn;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use systems::{MobSystem, TimeSystem};
|
use systems::{MobSystem, TimeSystem};
|
||||||
|
|
||||||
mod components;
|
mod components;
|
||||||
|
mod io;
|
||||||
mod level;
|
mod level;
|
||||||
mod player;
|
mod player;
|
||||||
mod rooms;
|
mod rooms;
|
||||||
|
@ -65,27 +64,3 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the terminal to accept user input, and creates a new
|
|
||||||
/// Window.
|
|
||||||
fn init_window() -> Window {
|
|
||||||
// Create a new window over the terminal.
|
|
||||||
let window = initscr();
|
|
||||||
|
|
||||||
// Enable keypad mode (off by default for historical reasons), so
|
|
||||||
// we can read special keycodes other than just characters.
|
|
||||||
window.keypad(true);
|
|
||||||
|
|
||||||
// Disable echoing so the user doesn't see flickering in the
|
|
||||||
// upper-left corner of the screen when they type a character.
|
|
||||||
noecho();
|
|
||||||
|
|
||||||
window
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cleans everything up and exits the game.
|
|
||||||
fn quit() -> ! {
|
|
||||||
endwin();
|
|
||||||
|
|
||||||
exit(0)
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use specs::prelude::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{CharRender, MobAction, Mobile, Player, Position},
|
components::{CharRender, MobAction, Mobile, Player, Position},
|
||||||
level::DungeonLevel,
|
level::DungeonLevel,
|
||||||
quit,
|
io::quit,
|
||||||
visibility::{visible, CellVisibility, Lighting},
|
visibility::{visible, CellVisibility, Lighting},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue