Add docs
This commit is contained in:
parent
fe31fdaa13
commit
5b8d127af0
8
Makefile
8
Makefile
@ -20,4 +20,10 @@ fmt:
|
|||||||
fix: fmt
|
fix: fmt
|
||||||
cargo fix --allow-dirty --allow-staged
|
cargo fix --allow-dirty --allow-staged
|
||||||
|
|
||||||
.phony: run-pi clean check run fmt fix lint
|
docs:
|
||||||
|
cargo doc
|
||||||
|
|
||||||
|
open-docs:
|
||||||
|
cargo doc --open
|
||||||
|
|
||||||
|
.phony: run-pi clean check run fmt fix lint docs open-docs
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Systems for making NPCs come to life
|
||||||
|
|
||||||
mod adjacent_ai_system;
|
mod adjacent_ai_system;
|
||||||
mod approach_ai_system;
|
mod approach_ai_system;
|
||||||
mod chase_ai_system;
|
mod chase_ai_system;
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
|
//! Handle rendering of the viewport
|
||||||
use ::rltk::{Point, Rltk};
|
use ::rltk::{Point, Rltk};
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
use crate::map::tile_glyph;
|
use crate::map::tile_glyph;
|
||||||
use crate::{colors, Hidden, Map, Position, Renderable};
|
use crate::{colors, Hidden, Map, Position, Renderable};
|
||||||
|
|
||||||
|
/// Whether to render an outline of the current map's boundaries
|
||||||
const SHOW_BOUNDARIES: bool = false;
|
const SHOW_BOUNDARIES: bool = false;
|
||||||
|
|
||||||
|
/// Get the rectangle representing the current viewport
|
||||||
pub fn get_screen_bounds(ecs: &World, _ctx: &mut Rltk) -> (i32, i32, i32, i32) {
|
pub fn get_screen_bounds(ecs: &World, _ctx: &mut Rltk) -> (i32, i32, i32, i32) {
|
||||||
let player_pos = ecs.fetch::<Point>();
|
let player_pos = ecs.fetch::<Point>();
|
||||||
// let (x_chars, y_chars) = ctx.get_char_size();
|
// let (x_chars, y_chars) = ctx.get_char_size();
|
||||||
@ -22,6 +25,7 @@ pub fn get_screen_bounds(ecs: &World, _ctx: &mut Rltk) -> (i32, i32, i32, i32) {
|
|||||||
(min_x, max_x, min_y, max_y)
|
(min_x, max_x, min_y, max_y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Render the current viewport
|
||||||
pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let (min_x, max_x, min_y, max_y) = get_screen_bounds(ecs, ctx);
|
let (min_x, max_x, min_y, max_y) = get_screen_bounds(ecs, ctx);
|
||||||
|
@ -15,9 +15,11 @@ pub use targeting::*;
|
|||||||
use crate::spatial;
|
use crate::spatial;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
/// The shared queue of effects
|
||||||
pub static ref EFFECT_QUEUE: Mutex<VecDeque<EffectSpawner>> = Mutex::new(VecDeque::new());
|
pub static ref EFFECT_QUEUE: Mutex<VecDeque<EffectSpawner>> = Mutex::new(VecDeque::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The kind of effect to cause
|
||||||
pub enum EffectType {
|
pub enum EffectType {
|
||||||
Damage {
|
Damage {
|
||||||
amount: i32,
|
amount: i32,
|
||||||
@ -51,8 +53,8 @@ pub enum EffectType {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Who, or what the effect should affect.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum Targets {
|
pub enum Targets {
|
||||||
Single { target: Entity },
|
Single { target: Entity },
|
||||||
TargetList { targets: Vec<Entity> },
|
TargetList { targets: Vec<Entity> },
|
||||||
@ -60,12 +62,14 @@ pub enum Targets {
|
|||||||
Tiles { tiles: Vec<i32> },
|
Tiles { tiles: Vec<i32> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An effect for the queue
|
||||||
pub struct EffectSpawner {
|
pub struct EffectSpawner {
|
||||||
pub creator: Option<Entity>,
|
pub creator: Option<Entity>,
|
||||||
pub effect_type: EffectType,
|
pub effect_type: EffectType,
|
||||||
pub targets: Targets,
|
pub targets: Targets,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an effect to the queue
|
||||||
pub fn add_effect(creator: Option<Entity>, effect_type: EffectType, targets: Targets) {
|
pub fn add_effect(creator: Option<Entity>, effect_type: EffectType, targets: Targets) {
|
||||||
EFFECT_QUEUE.lock().unwrap().push_back(EffectSpawner {
|
EFFECT_QUEUE.lock().unwrap().push_back(EffectSpawner {
|
||||||
creator,
|
creator,
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
/// A struct to hold the player's game log.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GameLog {
|
pub struct GameLog {
|
||||||
pub entries: Vec<String>,
|
pub entries: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameLog {
|
impl GameLog {
|
||||||
|
/// Convenience constructor that adds the first
|
||||||
|
/// entry to the game log.
|
||||||
pub fn new<S: ToString>(first_entry: S) -> Self {
|
pub fn new<S: ToString>(first_entry: S) -> Self {
|
||||||
let mut log = GameLog::default();
|
let mut log = GameLog::default();
|
||||||
log.append(first_entry);
|
log.append(first_entry);
|
||||||
@ -11,6 +14,10 @@ impl GameLog {
|
|||||||
log
|
log
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convenience method for adding an entry to the game log.
|
||||||
|
/// Generic on the [`ToString`] trait so that [`&str`], [`String`],
|
||||||
|
/// and `&String` types, all work without more type juggling
|
||||||
|
/// at the call site.
|
||||||
pub fn append<S: ToString>(&mut self, s: S) {
|
pub fn append<S: ToString>(&mut self, s: S) {
|
||||||
self.entries.push(s.to_string());
|
self.entries.push(s.to_string());
|
||||||
}
|
}
|
||||||
|
27
src/main.rs
27
src/main.rs
@ -1,3 +1,6 @@
|
|||||||
|
//! Roguelike
|
||||||
|
//!
|
||||||
|
//! An implementation of a rogue-like dungeon-crawler game.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
@ -40,6 +43,21 @@ pub use rect::Rect;
|
|||||||
pub use state::*;
|
pub use state::*;
|
||||||
|
|
||||||
/// Cut down on the amount of syntax to register components
|
/// Cut down on the amount of syntax to register components
|
||||||
|
///
|
||||||
|
/// Compare:
|
||||||
|
/// ```ignore
|
||||||
|
/// let mut game_state = State::new();
|
||||||
|
///
|
||||||
|
/// register!(state <- ComponentA, ComponentB, ...);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Without macro:
|
||||||
|
/// ```ignore
|
||||||
|
/// let mut game_state = State::new();
|
||||||
|
///
|
||||||
|
/// state.ecs.register::<ComponentA>();
|
||||||
|
/// state.ecs.register::<ComponentB>();
|
||||||
|
/// ```
|
||||||
macro_rules! register {
|
macro_rules! register {
|
||||||
// $state is needed to get the scope at the usage point
|
// $state is needed to get the scope at the usage point
|
||||||
// $Type is the Component type that is being registered
|
// $Type is the Component type that is being registered
|
||||||
@ -50,6 +68,14 @@ macro_rules! register {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets up the game.
|
||||||
|
///
|
||||||
|
/// * Creates the [`State`] object
|
||||||
|
/// * Registers [`components`](register!)
|
||||||
|
/// * Loads the dynamic game entities using the [`raws`](crate::raws::load_raws) module
|
||||||
|
/// * Generates the map builder environment
|
||||||
|
/// * Creates the [`Player`](crate::spawner::player)
|
||||||
|
/// * Generates the first [`map`](crate::state::State::generate_world_map)
|
||||||
fn init_state() -> State {
|
fn init_state() -> State {
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
|
|
||||||
@ -146,6 +172,7 @@ fn init_state() -> State {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The entry point
|
||||||
fn main() -> ::rltk::BError {
|
fn main() -> ::rltk::BError {
|
||||||
let context = ::rltk::RltkBuilder::simple(80, 60)
|
let context = ::rltk::RltkBuilder::simple(80, 60)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
10
src/map.rs
10
src/map.rs
@ -1,13 +1,13 @@
|
|||||||
|
//! An object to hold the state of the current level's map
|
||||||
mod dungeon;
|
mod dungeon;
|
||||||
mod themes;
|
mod themes;
|
||||||
mod tiletype;
|
mod tiletype;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use ::rltk::{Algorithm2D, BaseMap, Point, SmallVec};
|
use ::rltk::{Algorithm2D, BaseMap, Point, SmallVec, RGB};
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
pub use dungeon::*;
|
pub use dungeon::*;
|
||||||
use rltk::RGB;
|
|
||||||
pub use themes::*;
|
pub use themes::*;
|
||||||
pub use tiletype::{tile_opaque, tile_walkable, TileType};
|
pub use tiletype::{tile_opaque, tile_walkable, TileType};
|
||||||
|
|
||||||
@ -30,6 +30,8 @@ pub struct Map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Map {
|
impl Map {
|
||||||
|
/// Converts an `(x, y)` coordinate to the flat index within the
|
||||||
|
/// `Map`'s internal array.
|
||||||
pub fn xy_idx(&self, x: i32, y: i32) -> usize {
|
pub fn xy_idx(&self, x: i32, y: i32) -> usize {
|
||||||
(y as usize * self.width as usize) + x as usize
|
(y as usize * self.width as usize) + x as usize
|
||||||
}
|
}
|
||||||
@ -83,7 +85,7 @@ impl BaseMap for Map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_available_exits(&self, idx: usize) -> SmallVec<[(usize, f32); 10]> {
|
fn get_available_exits(&self, idx: usize) -> SmallVec<[(usize, f32); 10]> {
|
||||||
let mut exits = rltk::SmallVec::new();
|
let mut exits = SmallVec::new();
|
||||||
let x = idx as i32 % self.width;
|
let x = idx as i32 % self.width;
|
||||||
let y = idx as i32 / self.width;
|
let y = idx as i32 / self.width;
|
||||||
let w = self.width as usize;
|
let w = self.width as usize;
|
||||||
@ -125,7 +127,7 @@ impl BaseMap for Map {
|
|||||||
let p1 = Point::new(idx1 % w, idx1 / w);
|
let p1 = Point::new(idx1 % w, idx1 / w);
|
||||||
let p2 = Point::new(idx2 % w, idx2 / w);
|
let p2 = Point::new(idx2 % w, idx2 / w);
|
||||||
|
|
||||||
rltk::DistanceAlg::Pythagoras.distance2d(p1, p2)
|
::rltk::DistanceAlg::Pythagoras.distance2d(p1, p2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//! Functionality that is common to all the currently generated maps.
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use ::rltk::{Point, RandomNumberGenerator};
|
use ::rltk::{Point, RandomNumberGenerator};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//! Different looks for the same set of [`TileType`]s
|
||||||
use ::rltk::{to_cp437, FontCharType, RGB};
|
use ::rltk::{to_cp437, FontCharType, RGB};
|
||||||
|
|
||||||
use super::{Map, TileType};
|
use super::{Map, TileType};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// The type of location for a specific square of a [`Map`](crate::map::Map)
|
||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum TileType {
|
pub enum TileType {
|
||||||
Wall,
|
Wall,
|
||||||
@ -17,6 +18,7 @@ pub enum TileType {
|
|||||||
Stalagmite,
|
Stalagmite,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Can you go through this type of map tile?
|
||||||
pub fn tile_walkable(tt: TileType) -> bool {
|
pub fn tile_walkable(tt: TileType) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
tt,
|
tt,
|
||||||
@ -32,6 +34,7 @@ pub fn tile_walkable(tt: TileType) -> bool {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is it impossible to see through this type of map tile?
|
||||||
pub fn tile_opaque(tt: TileType) -> bool {
|
pub fn tile_opaque(tt: TileType) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
tt,
|
tt,
|
||||||
@ -39,6 +42,7 @@ pub fn tile_opaque(tt: TileType) -> bool {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// How difficult is it to cross this type of map tile?
|
||||||
pub fn tile_cost(tt: TileType) -> f32 {
|
pub fn tile_cost(tt: TileType) -> f32 {
|
||||||
match tt {
|
match tt {
|
||||||
TileType::Road => 0.8,
|
TileType::Road => 0.8,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//! Four points, one plane, 90° angles
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//!
|
||||||
use ::rltk::{GameState, Point, Rltk};
|
use ::rltk::{GameState, Point, Rltk};
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
@ -21,8 +22,10 @@ use crate::trigger_system::TriggerSystem;
|
|||||||
use crate::visibility_system::VisibilitySystem;
|
use crate::visibility_system::VisibilitySystem;
|
||||||
use crate::{ai, camera, damage_system, effects, saveload_system, spawner};
|
use crate::{ai, camera, damage_system, effects, saveload_system, spawner};
|
||||||
|
|
||||||
|
/// Whether to show a visual representation of map generation
|
||||||
pub const SHOW_MAPGEN_VISUALIZER: bool = false;
|
pub const SHOW_MAPGEN_VISUALIZER: bool = false;
|
||||||
|
|
||||||
|
/// The main actions possible with a vendor
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum VendorMode {
|
pub enum VendorMode {
|
||||||
Buy,
|
Buy,
|
||||||
@ -30,6 +33,7 @@ pub enum VendorMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
|
/// The states for the game engine's state machine
|
||||||
pub enum RunState {
|
pub enum RunState {
|
||||||
AwaitingInput,
|
AwaitingInput,
|
||||||
PreRun,
|
PreRun,
|
||||||
@ -203,6 +207,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GameState for State {
|
impl GameState for State {
|
||||||
|
/// The big, nasty, state machine handler
|
||||||
fn tick(&mut self, ctx: &mut Rltk) {
|
fn tick(&mut self, ctx: &mut Rltk) {
|
||||||
let mut newrunstate;
|
let mut newrunstate;
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user