|
|
|
@ -1,12 +1,15 @@
|
|
|
|
|
rltk::add_wasm_support!(); |
|
|
|
|
mod crypto; |
|
|
|
|
mod map; |
|
|
|
|
mod traits; |
|
|
|
|
use crate::map::Chunk; |
|
|
|
|
use crate::traits::Render; |
|
|
|
|
use map::TileType; |
|
|
|
|
use rltk::prelude::*; |
|
|
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
|
|
struct State { |
|
|
|
|
#[derive(Clone)] |
|
|
|
|
pub struct State { |
|
|
|
|
view: Chunk, |
|
|
|
|
loaded_chunks: Box<HashMap<(i32, i32), Chunk>>, |
|
|
|
|
world_pos: (i32, i32), |
|
|
|
@ -119,8 +122,6 @@ impl State {
|
|
|
|
|
impl GameState for State { |
|
|
|
|
#[allow(non_snake_case)] |
|
|
|
|
fn tick(&mut self, ctx: &mut Rltk) { |
|
|
|
|
// We'll use batched drawing
|
|
|
|
|
let mut draw_batch = DrawBatch::new(); |
|
|
|
|
match ctx.key { |
|
|
|
|
None => {} // Nothing happened
|
|
|
|
|
Some(key) => { |
|
|
|
@ -155,84 +156,8 @@ impl GameState for State {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set all tiles to not visible
|
|
|
|
|
for v in self.visible.iter_mut() { |
|
|
|
|
*v = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Obtain the player's visible tile set, and apply it
|
|
|
|
|
let player_position = self.index_to_point2d(self.player_position); |
|
|
|
|
let fov = rltk::field_of_view_set(player_position, 8, self); |
|
|
|
|
|
|
|
|
|
// Note that the steps above would generally not be run every frame!
|
|
|
|
|
for idx in fov.iter() { |
|
|
|
|
let point = self.point2d_to_index(*idx); |
|
|
|
|
self.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 self.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 !self.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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if ctx.left_click { |
|
|
|
|
let mouse_pos = ctx.mouse_pos(); |
|
|
|
|
self.select_object(Point::from(mouse_pos)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Display selected object below the screen
|
|
|
|
|
let selected_object_text = match self.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 = self.index_to_point2d(self.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"); |
|
|
|
|
// @cleanup: We shouldn't be cloning the state on each frame
|
|
|
|
|
self.view.render(&mut self.clone(), ctx); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|