Compare commits
2 Commits
f8a9cc5d75
...
eee0c23f5f
| Author | SHA1 | Date | |
|---|---|---|---|
| eee0c23f5f | |||
| f10a3ecc61 |
76
Cargo.lock
generated
76
Cargo.lock
generated
@@ -17,6 +17,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-cprng"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@@ -35,10 +41,58 @@ version = "0.3.28"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
|
checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "roguelike"
|
name = "roguelike"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"rand 0.3.23",
|
||||||
"tcod",
|
"tcod",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -62,3 +116,25 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"pkg-config",
|
"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"
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tcod = "0.15"
|
tcod = "0.15"
|
||||||
|
rand = "0.3.9"
|
||||||
|
|||||||
209
src/main.rs
209
src/main.rs
@@ -1,3 +1,5 @@
|
|||||||
|
use rand::Rng;
|
||||||
|
use std::cmp;
|
||||||
use tcod::colors::*;
|
use tcod::colors::*;
|
||||||
use tcod::console::*;
|
use tcod::console::*;
|
||||||
|
|
||||||
@@ -15,6 +17,11 @@ const COLOR_DARK_GROUND: Color = Color {
|
|||||||
b: 150,
|
b: 150,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// parameters for dungeon generator
|
||||||
|
const ROOM_MAX_SIZE: i32 = 10;
|
||||||
|
const ROOM_MIN_SIZE: i32 = 6;
|
||||||
|
const MAX_ROOMS: i32 = 30;
|
||||||
|
|
||||||
// 20 FPS max
|
// 20 FPS max
|
||||||
const LIMIT_FPS: i32 = 20;
|
const LIMIT_FPS: i32 = 20;
|
||||||
|
|
||||||
@@ -22,48 +29,6 @@ struct Tcod {
|
|||||||
root: Root,
|
root: Root,
|
||||||
con: Offscreen,
|
con: Offscreen,
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
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 };
|
|
||||||
tcod::system::set_fps(LIMIT_FPS);
|
|
||||||
|
|
||||||
let mut player_x = SCREEN_WIDTH / 2;
|
|
||||||
let mut player_y = SCREEN_HEIGHT / 2;
|
|
||||||
|
|
||||||
// create object representing the player
|
|
||||||
let player = Object::new(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, '@', WHITE);
|
|
||||||
// create an NPC
|
|
||||||
let npc = Object::new(SCREEN_WIDTH / 2 - 5, SCREEN_HEIGHT / 2, '@', YELLOW);
|
|
||||||
// the list of objects with the two above
|
|
||||||
let mut objects = [player, npc];
|
|
||||||
|
|
||||||
// Generate map
|
|
||||||
let game = Game { map: make_map() };
|
|
||||||
|
|
||||||
// Main game loop
|
|
||||||
while !tcod.root.window_closed() {
|
|
||||||
tcod.con.clear();
|
|
||||||
render_all(&mut tcod, &game, &objects);
|
|
||||||
|
|
||||||
tcod.root.flush();
|
|
||||||
tcod.root.wait_for_keypress(true);
|
|
||||||
|
|
||||||
// handle kepresses
|
|
||||||
let player = &mut objects[0];
|
|
||||||
let exit = handle_keys(&mut tcod, &game, player);
|
|
||||||
if exit {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle_keys() handles inputs; returns a boolean - "should we exit the game?"
|
// handle_keys() handles inputs; returns a boolean - "should we exit the game?"
|
||||||
fn handle_keys(tcod: &mut Tcod, game: &Game, player: &mut Object) -> bool {
|
fn handle_keys(tcod: &mut Tcod, game: &Game, player: &mut Object) -> bool {
|
||||||
@@ -183,13 +148,161 @@ struct Game {
|
|||||||
map: Map,
|
map: Map,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_map() -> Map {
|
fn make_map(player: &mut Object) -> Map {
|
||||||
// fill map with "unblocked" tiles
|
// fill map with "blocked" tiles
|
||||||
let mut map = vec![vec![Tile::empty(); MAP_HEIGHT as usize]; MAP_WIDTH as usize];
|
let mut map = vec![vec![Tile::wall(); MAP_HEIGHT as usize]; MAP_WIDTH as usize];
|
||||||
|
|
||||||
// place two pillars to test the map
|
let mut rooms = vec![];
|
||||||
map[30][22] = Tile::wall();
|
|
||||||
map[50][22] = Tile::wall();
|
|
||||||
|
|
||||||
|
for _ in 0..MAX_ROOMS {
|
||||||
|
// random width and height
|
||||||
|
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);
|
||||||
|
// random position without going out of the boundaries of the map
|
||||||
|
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);
|
||||||
|
|
||||||
|
// run through the other rooms and see if they intersect with this one
|
||||||
|
let failed = rooms
|
||||||
|
.iter()
|
||||||
|
.any(|other_room| new_room.intersects_with(other_room));
|
||||||
|
|
||||||
|
if !failed {
|
||||||
|
// room is valid, no intersections
|
||||||
|
create_room(new_room, &mut map);
|
||||||
|
|
||||||
|
// center coordinates of the new room (useful later)
|
||||||
|
let (new_x, new_y) = new_room.center();
|
||||||
|
|
||||||
|
if rooms.is_empty() {
|
||||||
|
// this is the first room, have the user start here
|
||||||
|
player.x = new_x;
|
||||||
|
player.y = new_y;
|
||||||
|
} else {
|
||||||
|
// all other rooms after the first - connect them to the prev with a tunnel
|
||||||
|
|
||||||
|
// center coordinates of the previous room
|
||||||
|
let (prev_x, prev_y) = rooms[rooms.len() - 1].center();
|
||||||
|
|
||||||
|
// get a random bool value
|
||||||
|
if rand::random() {
|
||||||
|
// first move horizontally then vertically
|
||||||
|
create_h_tunnel(prev_x, new_x, prev_y, &mut map);
|
||||||
|
create_v_tunnel(prev_y, new_y, new_x, &mut map);
|
||||||
|
} else {
|
||||||
|
// vertically then horizontally
|
||||||
|
create_v_tunnel(prev_y, new_y, prev_x, &mut map);
|
||||||
|
create_h_tunnel(prev_x, new_x, new_y, &mut map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append room to the list
|
||||||
|
rooms.push(new_room);
|
||||||
|
}
|
||||||
|
}
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A rectangle on the map, used to characterize a room
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
struct Rect {
|
||||||
|
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 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 {
|
||||||
|
// returns true if this rectangle intersects with another one
|
||||||
|
(self.x1 <= other.x2)
|
||||||
|
&& (self.y1 <= other.y2)
|
||||||
|
&& (self.y2 >= other.y1)
|
||||||
|
&& (self.y2 >= other.y1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_room(room: Rect, map: &mut Map) {
|
||||||
|
// go through the tles 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
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 };
|
||||||
|
tcod::system::set_fps(LIMIT_FPS);
|
||||||
|
|
||||||
|
let mut player_x = SCREEN_WIDTH / 2;
|
||||||
|
let mut player_y = SCREEN_HEIGHT / 2;
|
||||||
|
|
||||||
|
// create object representing the player
|
||||||
|
let player = Object::new(0, 0, '@', WHITE);
|
||||||
|
// create an NPC
|
||||||
|
let npc = Object::new(SCREEN_WIDTH / 2 - 5, SCREEN_HEIGHT / 2, '@', YELLOW);
|
||||||
|
// the list of objects with the two above
|
||||||
|
let mut objects = [player, npc];
|
||||||
|
|
||||||
|
// Generate map
|
||||||
|
let game = Game {
|
||||||
|
map: make_map(&mut objects[0]),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while !tcod.root.window_closed() {
|
||||||
|
tcod.con.clear();
|
||||||
|
render_all(&mut tcod, &game, &objects);
|
||||||
|
|
||||||
|
tcod.root.flush();
|
||||||
|
tcod.root.wait_for_keypress(true);
|
||||||
|
|
||||||
|
// handle kepresses
|
||||||
|
let player = &mut objects[0];
|
||||||
|
let exit = handle_keys(&mut tcod, &game, player);
|
||||||
|
if exit {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user