Preparing for combat
This commit is contained in:
parent
99795856af
commit
d81ace4555
82
Cargo.lock
generated
82
Cargo.lock
generated
@ -14,22 +14,82 @@ version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand 0.4.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||
dependencies = [
|
||||
"fuchsia-cprng",
|
||||
"libc",
|
||||
"rand_core 0.3.1",
|
||||
"rdrand",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roguelike"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rand 0.3.23",
|
||||
"tcod",
|
||||
]
|
||||
|
||||
@ -53,3 +113,25 @@ dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
@ -7,3 +7,4 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
tcod = "*"
|
||||
rand = "0.3.9"
|
||||
|
||||
407
src/main.rs
407
src/main.rs
@ -3,9 +3,11 @@
|
||||
#![allow(unused_mut)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use rand::Rng;
|
||||
use std::cmp;
|
||||
use tcod::colors::*;
|
||||
use tcod::console::*;
|
||||
use tcod::map::{FovAlgorithm, Map as FovMap};
|
||||
|
||||
const SCREEN_WIDTH: i32 = 80;
|
||||
const SCREEN_HEIGHT: i32 = 50;
|
||||
@ -13,232 +15,325 @@ const FPS: i32 = 20;
|
||||
const MAP_WIDTH: i32 = 80;
|
||||
const MAP_HEIGHT: i32 = 45;
|
||||
const COLOR_DARK_WALL: Color = Color { r: 0, g: 0, b: 100 };
|
||||
const COLOR_DARK_GROUND: Color = Color {
|
||||
r: 50,
|
||||
g: 50,
|
||||
b: 150,
|
||||
const COLOR_LIGHT_WALL: Color = Color {
|
||||
r: 130,
|
||||
g: 110,
|
||||
b: 50,
|
||||
};
|
||||
const COLOR_DARK_GROUND: Color = Color {
|
||||
r: 50,
|
||||
g: 50,
|
||||
b: 150,
|
||||
};
|
||||
const COLOR_LIGHT_GROUND: Color = Color {
|
||||
r: 200,
|
||||
g: 180,
|
||||
b: 50,
|
||||
};
|
||||
const ROOM_MAX_SIZE: i32 = 10;
|
||||
const ROOM_MIN_SIZE: i32 = 6;
|
||||
const MAX_ROOMS: i32 = 30;
|
||||
const FOV_ALGO: FovAlgorithm = FovAlgorithm::Basic;
|
||||
const FOV_LIGHT_WALLS: bool = true;
|
||||
const TORCH_RADIUS: i32 = 10;
|
||||
|
||||
struct Tcod {
|
||||
root: Root,
|
||||
con: Offscreen,
|
||||
root: Root,
|
||||
con: Offscreen,
|
||||
fov: FovMap,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Object {
|
||||
x: i32,
|
||||
y: i32,
|
||||
char: char,
|
||||
color: Color,
|
||||
x: i32,
|
||||
y: i32,
|
||||
char: char,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl Object {
|
||||
pub fn new(x: i32, y: i32, char: char, color: Color) -> Self {
|
||||
Object { x, y, char, color }
|
||||
}
|
||||
pub fn new(x: i32, y: i32, char: char, color: Color) -> Self {
|
||||
Object { x, y, char, color }
|
||||
}
|
||||
|
||||
// Move by given amount, if the destination is not blocked
|
||||
pub fn move_by(&mut self, dx: i32, dy: i32, game: &Game) {
|
||||
if !game.map[(self.x + dx) as usize][(self.y + dy) as usize].blocked {
|
||||
self.x += dx;
|
||||
self.y += dy;
|
||||
}
|
||||
// Move by given amount, if the destination is not blocked
|
||||
pub fn move_by(&mut self, dx: i32, dy: i32, game: &Game) {
|
||||
if !game.map[(self.x + dx) as usize][(self.y + dy) as usize].blocked {
|
||||
self.x += dx;
|
||||
self.y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the color and then draw the character that represents this object at its position
|
||||
pub fn draw(&self, con: &mut dyn Console) {
|
||||
con.set_default_foreground(self.color);
|
||||
con.put_char(self.x, self.y, self.char, BackgroundFlag::None);
|
||||
}
|
||||
// Set the color and then draw the character that represents this object at its position
|
||||
pub fn draw(&self, con: &mut dyn Console) {
|
||||
con.set_default_foreground(self.color);
|
||||
con.put_char(self.x, self.y, self.char, BackgroundFlag::None);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Tile {
|
||||
blocked: bool,
|
||||
block_sight: bool,
|
||||
blocked: bool,
|
||||
explored: bool,
|
||||
block_sight: bool,
|
||||
}
|
||||
|
||||
impl Tile {
|
||||
pub fn empty() -> Self {
|
||||
Tile {
|
||||
blocked: false,
|
||||
block_sight: false,
|
||||
}
|
||||
pub fn empty() -> Self {
|
||||
Tile {
|
||||
blocked: false,
|
||||
explored: false,
|
||||
block_sight: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wall() -> Self {
|
||||
Tile {
|
||||
blocked: true,
|
||||
block_sight: true,
|
||||
}
|
||||
pub fn wall() -> Self {
|
||||
Tile {
|
||||
blocked: true,
|
||||
explored: false,
|
||||
block_sight: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Map = Vec<Vec<Tile>>;
|
||||
|
||||
struct Game {
|
||||
map: Map,
|
||||
map: Map,
|
||||
}
|
||||
|
||||
// A rectangle on the map, used to characterise a room.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Rect {
|
||||
x1: i32,
|
||||
y1: i32,
|
||||
x2: i32,
|
||||
y2: i32,
|
||||
x1: i32,
|
||||
y1: i32,
|
||||
x2: i32,
|
||||
y2: i32,
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
pub fn new(x: i32, y: i32, w: i32, h: i32) -> Self {
|
||||
Rect {
|
||||
x1: x,
|
||||
y1: y,
|
||||
x2: x + w,
|
||||
y2: y + h,
|
||||
}
|
||||
pub fn new(x: i32, y: i32, w: i32, h: i32) -> Self {
|
||||
Rect {
|
||||
x1: x,
|
||||
y1: y,
|
||||
x2: x + w,
|
||||
y2: y + h,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn center(&self) -> (i32, i32) {
|
||||
let center_x = (self.x1 + self.x2) / 2;
|
||||
let center_y = (self.y1 + self.y2) / 2;
|
||||
(center_x, center_y)
|
||||
}
|
||||
|
||||
pub fn intersects_with(&self, other: &Rect) -> bool {
|
||||
(self.x1 <= other.x2) && (self.x2 >= other.x1) && (self.y1 <= other.y2) && (self.y2 >= other.y1)
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_keys(tcod: &mut Tcod, game: &Game, player: &mut Object) -> bool {
|
||||
use tcod::input::Key;
|
||||
use tcod::input::KeyCode::*;
|
||||
use tcod::input::Key;
|
||||
use tcod::input::KeyCode::*;
|
||||
|
||||
let key = tcod.root.wait_for_keypress(true);
|
||||
match key {
|
||||
Key {
|
||||
code: Enter,
|
||||
alt: true,
|
||||
..
|
||||
} => {
|
||||
// Alt+Enter: toggle fullscreen
|
||||
let fullscreen = tcod.root.is_fullscreen();
|
||||
tcod.root.set_fullscreen(!fullscreen);
|
||||
}
|
||||
Key { code: Escape, .. } => return true, // exit game
|
||||
|
||||
Key { code: Up, .. } => player.move_by(0, -1, game),
|
||||
Key { code: Down, .. } => player.move_by(0, 1, game),
|
||||
Key { code: Left, .. } => player.move_by(-1, 0, game),
|
||||
Key { code: Right, .. } => player.move_by(1, 0, game),
|
||||
|
||||
_ => {}
|
||||
let key = tcod.root.wait_for_keypress(true);
|
||||
match key {
|
||||
Key {
|
||||
code: Enter,
|
||||
alt: true,
|
||||
..
|
||||
} => {
|
||||
// Alt+Enter: toggle fullscreen
|
||||
let fullscreen = tcod.root.is_fullscreen();
|
||||
tcod.root.set_fullscreen(!fullscreen);
|
||||
}
|
||||
false
|
||||
Key { code: Escape, .. } => return true, // exit game
|
||||
|
||||
Key { code: Up, .. } => player.move_by(0, -1, game),
|
||||
Key { code: Down, .. } => player.move_by(0, 1, game),
|
||||
Key { code: Left, .. } => player.move_by(-1, 0, game),
|
||||
Key { code: Right, .. } => player.move_by(1, 0, game),
|
||||
|
||||
_ => {}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn make_map() -> Map {
|
||||
// Fill the map with unblocked tiles
|
||||
let mut map = vec![vec![Tile::wall(); MAP_HEIGHT as usize]; MAP_WIDTH as usize];
|
||||
fn make_map(player: &mut Object) -> Map {
|
||||
// Fill the map with unblocked tiles
|
||||
let mut map = vec![vec![Tile::wall(); MAP_HEIGHT as usize]; MAP_WIDTH as usize];
|
||||
|
||||
// Create two rooms
|
||||
let room1 = Rect::new(20, 15, 10, 15);
|
||||
let room2 = Rect::new(50, 15, 10, 15);
|
||||
create_room(room1, &mut map);
|
||||
create_room(room2, &mut map);
|
||||
create_h_tunnel(25, 55, 23, &mut map);
|
||||
let mut rooms = vec![];
|
||||
|
||||
map
|
||||
for _ in 0..MAX_ROOMS {
|
||||
let w = rand::thread_rng().gen_range(ROOM_MIN_SIZE, ROOM_MAX_SIZE + 1);
|
||||
let h = rand::thread_rng().gen_range(ROOM_MIN_SIZE, ROOM_MAX_SIZE + 1);
|
||||
let x = rand::thread_rng().gen_range(0, MAP_WIDTH - w);
|
||||
let y = rand::thread_rng().gen_range(0, MAP_HEIGHT - h);
|
||||
|
||||
let new_room = Rect::new(x, y, w, h);
|
||||
let failed = rooms
|
||||
.iter()
|
||||
.any(|other_room| new_room.intersects_with(other_room));
|
||||
|
||||
if !failed {
|
||||
create_room(new_room, &mut map);
|
||||
let (new_x, new_y) = new_room.center();
|
||||
|
||||
if rooms.is_empty() {
|
||||
player.x = new_x;
|
||||
player.y = new_y;
|
||||
} else {
|
||||
let (prev_x, prev_y) = rooms[rooms.len() - 1].center();
|
||||
|
||||
if rand::random() {
|
||||
create_h_tunnel(prev_x, new_x, prev_y, &mut map);
|
||||
create_v_tunnel(prev_y, new_y, new_x, &mut map);
|
||||
} else {
|
||||
create_v_tunnel(prev_y, new_y, prev_x, &mut map);
|
||||
create_h_tunnel(prev_x, new_x, new_y, &mut map);
|
||||
}
|
||||
}
|
||||
rooms.push(new_room);
|
||||
}
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
fn create_room(room: Rect, map: &mut Map) {
|
||||
// Go through the tiles in the rectangle and make them passable
|
||||
for x in (room.x1 + 1)..room.x2 {
|
||||
for y in (room.y1 + 1)..room.y2 {
|
||||
map[x as usize][y as usize] = Tile::empty();
|
||||
}
|
||||
// Go through the tiles in the rectangle and make them passable
|
||||
for x in (room.x1 + 1)..room.x2 {
|
||||
for y in (room.y1 + 1)..room.y2 {
|
||||
map[x as usize][y as usize] = Tile::empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_h_tunnel(x1: i32, x2: i32, y: i32, map: &mut Map) {
|
||||
// Horizontal tunnel. `min()` and `max()` are used in case
|
||||
// `x1 > x2`
|
||||
for x in cmp::min(x1, x2)..(cmp::max(x1, x2) + 1) {
|
||||
map[x as usize][y as usize] = Tile::empty();
|
||||
}
|
||||
// Horizontal tunnel. `min()` and `max()` are used in case
|
||||
// `x1 > x2`
|
||||
for x in cmp::min(x1, x2)..(cmp::max(x1, x2) + 1) {
|
||||
map[x as usize][y as usize] = Tile::empty();
|
||||
}
|
||||
}
|
||||
|
||||
fn create_v_tunnel(y1: i32, y2: i32, x: i32, map: &mut Map) {
|
||||
// Vertical tunnel
|
||||
for y in cmp::min(y1, y2)..(cmp::max(y1, y2) + 1) {
|
||||
map[x as usize][y as usize] = Tile::empty();
|
||||
}
|
||||
// Vertical tunnel
|
||||
for y in cmp::min(y1, y2)..(cmp::max(y1, y2) + 1) {
|
||||
map[x as usize][y as usize] = Tile::empty();
|
||||
}
|
||||
}
|
||||
|
||||
fn render_all(tcod: &mut Tcod, game: &Game, objects: &[Object]) {
|
||||
// Draw all objects in the list
|
||||
for object in objects {
|
||||
object.draw(&mut tcod.con);
|
||||
}
|
||||
fn render_all(tcod: &mut Tcod, game: &mut Game, objects: &[Object], fov_recompute: bool) {
|
||||
if fov_recompute {
|
||||
let player = &objects[0];
|
||||
tcod
|
||||
.fov
|
||||
.compute_fov(player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO);
|
||||
}
|
||||
|
||||
// Go through all tiles and set their background color
|
||||
for y in 0..MAP_HEIGHT {
|
||||
for x in 0..MAP_WIDTH {
|
||||
let wall = game.map[x as usize][y as usize].block_sight;
|
||||
if wall {
|
||||
tcod.con
|
||||
.set_char_background(x, y, COLOR_DARK_WALL, BackgroundFlag::Set);
|
||||
} else {
|
||||
tcod.con
|
||||
.set_char_background(x, y, COLOR_DARK_GROUND, BackgroundFlag::Set)
|
||||
}
|
||||
}
|
||||
// Draw all objects in the list
|
||||
for object in objects {
|
||||
if tcod.fov.is_in_fov(object.x, object.y) {
|
||||
object.draw(&mut tcod.con);
|
||||
}
|
||||
}
|
||||
|
||||
// Blit contents of "con" to the root console
|
||||
blit(
|
||||
&tcod.con,
|
||||
(0, 0),
|
||||
(MAP_WIDTH, MAP_HEIGHT),
|
||||
&mut tcod.root,
|
||||
(0, 0),
|
||||
1.0,
|
||||
1.0,
|
||||
);
|
||||
// Go through all tiles and set their background color
|
||||
for y in 0..MAP_HEIGHT {
|
||||
for x in 0..MAP_WIDTH {
|
||||
let visible = tcod.fov.is_in_fov(x, y);
|
||||
let wall = game.map[x as usize][y as usize].block_sight;
|
||||
let color = match (visible, wall) {
|
||||
// Outside fov:
|
||||
(false, true) => COLOR_DARK_WALL,
|
||||
(false, false) => COLOR_DARK_GROUND,
|
||||
// INside fov:
|
||||
(true, true) => COLOR_LIGHT_WALL,
|
||||
(true, false) => COLOR_LIGHT_GROUND,
|
||||
};
|
||||
let explored = &mut game.map[x as usize][y as usize].explored;
|
||||
if visible {
|
||||
*explored = true;
|
||||
}
|
||||
if *explored {
|
||||
tcod
|
||||
.con
|
||||
.set_char_background(x, y, color, BackgroundFlag::Set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blit contents of "con" to the root console
|
||||
blit(
|
||||
&tcod.con,
|
||||
(0, 0),
|
||||
(MAP_WIDTH, MAP_HEIGHT),
|
||||
&mut tcod.root,
|
||||
(0, 0),
|
||||
1.0,
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tcod::system::set_fps(FPS);
|
||||
tcod::system::set_fps(FPS);
|
||||
|
||||
let root = Root::initializer()
|
||||
.font("arial10x10.png", FontLayout::Tcod)
|
||||
.font_type(FontType::Greyscale)
|
||||
.size(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
.title("Rust/libtcod tutorial")
|
||||
.init();
|
||||
let root = Root::initializer()
|
||||
.font("arial10x10.png", FontLayout::Tcod)
|
||||
.font_type(FontType::Greyscale)
|
||||
.size(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
.title("Rust/libtcod tutorial")
|
||||
.init();
|
||||
|
||||
let con = Offscreen::new(MAP_WIDTH, MAP_HEIGHT);
|
||||
let mut tcod = Tcod {
|
||||
root,
|
||||
con: Offscreen::new(MAP_WIDTH, MAP_HEIGHT),
|
||||
fov: FovMap::new(MAP_WIDTH, MAP_HEIGHT),
|
||||
};
|
||||
|
||||
let mut tcod = Tcod { root, con };
|
||||
// Create player object
|
||||
let player = Object::new(0, 0, '@', WHITE);
|
||||
|
||||
// Create player object
|
||||
let player = Object::new(25, 23, '@', WHITE);
|
||||
// // Create an NPC
|
||||
let npc = Object::new(SCREEN_WIDTH / 2 - 5, SCREEN_HEIGHT / 2, '@', YELLOW);
|
||||
|
||||
// // Create an NPC
|
||||
let npc = Object::new(SCREEN_WIDTH / 2 - 5, SCREEN_HEIGHT / 2, '@', YELLOW);
|
||||
// List of objects in the world
|
||||
let mut objects = [player, npc];
|
||||
|
||||
// List of objects in the world
|
||||
let mut objects = [player, npc];
|
||||
let mut game = Game {
|
||||
// Generate map
|
||||
map: make_map(&mut objects[0]),
|
||||
};
|
||||
|
||||
let game = Game {
|
||||
// Generate map
|
||||
map: make_map(),
|
||||
};
|
||||
|
||||
while !tcod.root.window_closed() {
|
||||
tcod.con.clear();
|
||||
|
||||
for object in &objects {
|
||||
object.draw(&mut tcod.con)
|
||||
}
|
||||
|
||||
render_all(&mut tcod, &game, &objects);
|
||||
tcod.root.flush();
|
||||
|
||||
let player = &mut objects[0];
|
||||
let exit = handle_keys(&mut tcod, &game, player);
|
||||
if exit {
|
||||
break;
|
||||
}
|
||||
// Populate FOV map, according to generated map
|
||||
for y in 0..MAP_HEIGHT {
|
||||
for x in 0..MAP_WIDTH {
|
||||
tcod.fov.set(
|
||||
x,
|
||||
y,
|
||||
!game.map[x as usize][y as usize].block_sight,
|
||||
!game.map[x as usize][y as usize].blocked,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let mut previous_player_position = (-1, -1);
|
||||
|
||||
// Main game loop
|
||||
while !tcod.root.window_closed() {
|
||||
tcod.con.clear();
|
||||
|
||||
let fov_recompute = previous_player_position != (objects[0].x, objects[0].y);
|
||||
render_all(&mut tcod, &mut game, &objects, fov_recompute);
|
||||
tcod.root.flush();
|
||||
|
||||
let player = &mut objects[0];
|
||||
previous_player_position = (player.x, player.y);
|
||||
let exit = handle_keys(&mut tcod, &game, player);
|
||||
if exit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user