You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

124 lines
3.5 KiB

use crate::crypto;
use crate::traits::Render;
use crate::State;
use rltk::prelude::*;
use rltk::Point;
use rltk::RandomNumberGenerator;
use std::fmt::Display;
pub type Chunk = Vec<TileType>;
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum TileType {
Wall,
Floor,
}
impl Display for TileType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self {
Self::Floor => f.write_str("Floor"),
Self::Wall => f.write_str("Wall"),
}
}
}
impl Render for Chunk {
fn render(&mut self, gs: &mut State, ctx: &mut rltk::Rltk) {
// We'll use batched drawing
let mut draw_batch = DrawBatch::new();
// Set all tiles to not visible
for v in gs.visible.iter_mut() {
*v = false;
}
// Obtain the player's visible tile set, and apply it
let player_position = gs.index_to_point2d(gs.player_position);
let fov = rltk::field_of_view_set(player_position, 8, gs);
// Note that the steps above would generally not be run every frame!
for idx in fov.iter() {
let point = gs.point2d_to_index(*idx);
gs.visible[point] = true;
}
// Clear the screen
draw_batch.cls();
// Iterate the map array, incrementing coordinates as we go.
let mut y = 0;
let mut x = 0;
for (i, tile) in gs.view.iter().enumerate() {
// Render a tile depending upon the tile type; now we check visibility as well!
let mut fg;
let mut glyph = ".";
match tile {
TileType::Floor => {
fg = RGB::from_f32(0.5, 0.5, 0.0);
}
TileType::Wall => {
fg = RGB::from_f32(0.0, 1.0, 0.0);
glyph = "#";
}
}
if !gs.visible[i] {
fg = fg.to_greyscale();
}
draw_batch.print_color(
Point::new(x, y),
glyph,
ColorPair::new(fg, RGB::from_f32(0., 0., 0.)),
);
// Move the coordinates
x += 1;
if x > 79 {
x = 0;
y += 1;
}
}
// Display selected object below the screen
let selected_object_text = match gs.selected_object {
Some(obj) => format!("{}", obj),
None => "".to_string(),
};
draw_batch.print_color(
Point::new(0, 51),
selected_object_text,
ColorPair::new(RGB::from_f32(1.0, 1.0, 0.0), RGB::from_f32(0., 0., 0.)),
);
// Render the player @ symbol
let ppos = gs.index_to_point2d(gs.player_position);
draw_batch.print_color(
Point::new(ppos.x, ppos.y),
"@",
ColorPair::new(RGB::from_f32(1.0, 1.0, 0.0), RGB::from_f32(0., 0., 0.)),
);
draw_batch.submit(0).expect("Batch error");
render_draw_buffer(ctx).expect("Render error");
}
}
pub fn new_chunk(seed: u64, pos: Point) -> Chunk {
let mut map = vec![TileType::Floor; 80 * 50];
let count = map.len();
let pos_hash = crypto::hash_to_number(pos);
// Feed seed and world position into random generator.
// There might be a better way to do this, but I think this works for now.
let mut rng = RandomNumberGenerator::seeded(seed.max(pos_hash) - seed.min(pos_hash));
// Place obstacles
for _ in 0..20 {
map[rng.range(0, count)] = TileType::Wall;
}
map
}