Separate binary from game engine
This commit is contained in:
parent
73525db8dd
commit
4a8b791acb
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "roguelike_tutorial"
|
name = "tim_rogue"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
rust-version = "1.56"
|
rust-version = "1.56"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
2
Makefile
2
Makefile
@ -46,6 +46,6 @@ fix: $(call print-help, fix, Fixes some warnings, then runs the formatter)
|
|||||||
make fmt
|
make fmt
|
||||||
|
|
||||||
docs: $(call print-help, docs, Generates code docs)
|
docs: $(call print-help, docs, Generates code docs)
|
||||||
cargo doc --features $(FEATURES)
|
cargo doc --features $(FEATURES) --document-private-items
|
||||||
|
|
||||||
.phony: run-pi clean check run fmt fix lint docs build build-wasm check-wasm build-wasm-dev
|
.phony: run-pi clean check run fmt fix lint docs build build-wasm check-wasm build-wasm-dev
|
@ -73,4 +73,6 @@ If you want to see what else you can run with Makefile, run `make help`. This wi
|
|||||||
* Added a macro to register components for `specs`, like was in the tutorial for saving/loading.
|
* Added a macro to register components for `specs`, like was in the tutorial for saving/loading.
|
||||||
* Game state machine is moved to `src/state.rs`
|
* Game state machine is moved to `src/state.rs`
|
||||||
* Colors (Bracket-lib `RGB` struct) have been converted to static values in `src/colors.rs`, to cut down on boilerplate and numbers of ways of generating color values.
|
* Colors (Bracket-lib `RGB` struct) have been converted to static values in `src/colors.rs`, to cut down on boilerplate and numbers of ways of generating color values.
|
||||||
* All references to `rltk` have been converted to `bracket_lib`, as `rltk` was a facade in `bracket_lib`
|
* All references to `rltk` have been converted to `bracket_lib`, as `rltk` was a facade in `bracket_lib`
|
||||||
|
* Made the crate a library and binary, with the binary just starting and running the game engine
|
||||||
|
* Submodules use named files as the module base, rather than `mod.rs`
|
@ -10,6 +10,7 @@ use std::collections::{HashSet, VecDeque};
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use ::bracket_lib::prelude::*;
|
use ::bracket_lib::prelude::*;
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
pub use targeting::*;
|
pub use targeting::*;
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref EVENTS: Mutex<HashMap<String, i32>> = Mutex::new(HashMap::new());
|
static ref EVENTS: Mutex<HashMap<String, i32>> = Mutex::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use ::bracket_lib::prelude::*;
|
use ::bracket_lib::prelude::*;
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
|
|
||||||
use super::LogFragment;
|
use super::LogFragment;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
|
185
src/lib.rs
Normal file
185
src/lib.rs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
//! Roguelike
|
||||||
|
//!
|
||||||
|
//! An implementation of a rogue-like dungeon-crawler game.
|
||||||
|
|
||||||
|
mod colors;
|
||||||
|
mod components;
|
||||||
|
mod damage_system;
|
||||||
|
mod effects;
|
||||||
|
mod gamelog;
|
||||||
|
mod gamesystem;
|
||||||
|
mod gui;
|
||||||
|
mod map;
|
||||||
|
mod map_builders;
|
||||||
|
mod player;
|
||||||
|
mod random_table;
|
||||||
|
pub mod raws;
|
||||||
|
mod rect;
|
||||||
|
mod rex_assets;
|
||||||
|
mod rng;
|
||||||
|
mod saveload_system;
|
||||||
|
mod spatial;
|
||||||
|
mod spawner;
|
||||||
|
mod state;
|
||||||
|
mod systems;
|
||||||
|
|
||||||
|
use ::bracket_lib::prelude::*;
|
||||||
|
use ::specs::prelude::*;
|
||||||
|
use ::specs::saveload::{SimpleMarker, SimpleMarkerAllocator};
|
||||||
|
use components::*;
|
||||||
|
use map::*;
|
||||||
|
use rect::Rect;
|
||||||
|
use state::*;
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
|
// $state is needed to get the scope at the usage point
|
||||||
|
// $Type is the Component type that is being registered
|
||||||
|
($state: ident <- $( $Type: ty ),*,) => {
|
||||||
|
$(
|
||||||
|
$state.ecs.register::<$Type>();
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register the Component Structs with Specs
|
||||||
|
fn register_components() -> State {
|
||||||
|
let mut state = State::new();
|
||||||
|
|
||||||
|
register!(
|
||||||
|
state <-
|
||||||
|
AlwaysTargetsSelf,
|
||||||
|
ApplyMove,
|
||||||
|
ApplyTeleport,
|
||||||
|
AreaOfEffect,
|
||||||
|
AttributeBonus,
|
||||||
|
Attributes,
|
||||||
|
BlocksTile,
|
||||||
|
BlocksVisibility,
|
||||||
|
Chasing,
|
||||||
|
Confusion,
|
||||||
|
Consumable,
|
||||||
|
CursedItem,
|
||||||
|
DamageOverTime,
|
||||||
|
DMSerializationHelper,
|
||||||
|
Door,
|
||||||
|
Duration,
|
||||||
|
EntityMoved,
|
||||||
|
EntryTrigger,
|
||||||
|
EquipmentChanged,
|
||||||
|
Equippable,
|
||||||
|
Equipped,
|
||||||
|
Faction,
|
||||||
|
Hidden,
|
||||||
|
HungerClock,
|
||||||
|
IdentifiedItem,
|
||||||
|
InBackpack,
|
||||||
|
InflictsDamage,
|
||||||
|
Initiative,
|
||||||
|
Item,
|
||||||
|
KnownSpells,
|
||||||
|
LightSource,
|
||||||
|
LootTable,
|
||||||
|
MagicItem,
|
||||||
|
MagicMapper,
|
||||||
|
MoveMode,
|
||||||
|
MyTurn,
|
||||||
|
Name,
|
||||||
|
NaturalAttackDefense,
|
||||||
|
ObfuscatedName,
|
||||||
|
OnDeath,
|
||||||
|
OtherLevelPosition,
|
||||||
|
ParticleLifetime,
|
||||||
|
Player,
|
||||||
|
Pools,
|
||||||
|
Position,
|
||||||
|
ProvidesFood,
|
||||||
|
ProvidesHealing,
|
||||||
|
ProvidesIdentification,
|
||||||
|
ProvidesMana,
|
||||||
|
ProvidesRemoveCurse,
|
||||||
|
Quips,
|
||||||
|
Ranged,
|
||||||
|
Renderable,
|
||||||
|
SerializationHelper,
|
||||||
|
SimpleMarker<SerializeMe>,
|
||||||
|
SingleActivation,
|
||||||
|
Skills,
|
||||||
|
Slow,
|
||||||
|
SpawnParticleBurst,
|
||||||
|
SpawnParticleLine,
|
||||||
|
SpecialAbilities,
|
||||||
|
SpellTemplate,
|
||||||
|
StatusEffect,
|
||||||
|
Target,
|
||||||
|
TeachesSpell,
|
||||||
|
TeleportTo,
|
||||||
|
TileSize,
|
||||||
|
TownPortal,
|
||||||
|
Vendor,
|
||||||
|
Viewshed,
|
||||||
|
WantsToApproach,
|
||||||
|
WantsToCastSpell,
|
||||||
|
WantsToDropItem,
|
||||||
|
WantsToFlee,
|
||||||
|
WantsToMelee,
|
||||||
|
WantsToPickupItem,
|
||||||
|
WantsToRemoveItem,
|
||||||
|
WantsToShoot,
|
||||||
|
WantsToUseItem,
|
||||||
|
Weapon,
|
||||||
|
Wearable,
|
||||||
|
);
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
pub fn init_state() -> State {
|
||||||
|
use systems::particle_system::ParticleBuilder;
|
||||||
|
|
||||||
|
let mut state = register_components();
|
||||||
|
|
||||||
|
state
|
||||||
|
.ecs
|
||||||
|
.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
||||||
|
|
||||||
|
raws::load_raws();
|
||||||
|
|
||||||
|
state.ecs.insert(MasterDungeonMap::new());
|
||||||
|
state.ecs.insert(Map::new(1, 64, 64, "New Map"));
|
||||||
|
state.ecs.insert(Point::zero());
|
||||||
|
|
||||||
|
let player_entity = spawner::player(&mut state.ecs, 0, 0);
|
||||||
|
state.ecs.insert(player_entity);
|
||||||
|
|
||||||
|
state.ecs.insert(RunState::MapGeneration {});
|
||||||
|
state.ecs.insert(ParticleBuilder::new());
|
||||||
|
state.ecs.insert(rex_assets::RexAssets::new());
|
||||||
|
|
||||||
|
state.generate_world_map(1, 0);
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
186
src/main.rs
186
src/main.rs
@ -1,188 +1,4 @@
|
|||||||
//! Roguelike
|
|
||||||
//!
|
|
||||||
//! An implementation of a rogue-like dungeon-crawler game.
|
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
|
|
||||||
mod colors;
|
|
||||||
mod components;
|
|
||||||
mod damage_system;
|
|
||||||
mod effects;
|
|
||||||
mod gamelog;
|
|
||||||
mod gamesystem;
|
|
||||||
mod gui;
|
|
||||||
mod map;
|
|
||||||
pub mod map_builders;
|
|
||||||
mod player;
|
|
||||||
mod random_table;
|
|
||||||
mod raws;
|
|
||||||
mod rect;
|
|
||||||
mod rex_assets;
|
|
||||||
mod rng;
|
|
||||||
mod saveload_system;
|
|
||||||
mod spatial;
|
|
||||||
mod spawner;
|
|
||||||
mod state;
|
|
||||||
mod systems;
|
|
||||||
|
|
||||||
use ::bracket_lib::prelude::*;
|
use ::bracket_lib::prelude::*;
|
||||||
use ::specs::prelude::*;
|
|
||||||
use ::specs::saveload::{SimpleMarker, SimpleMarkerAllocator};
|
|
||||||
use components::*;
|
|
||||||
pub use map::*;
|
|
||||||
pub use rect::Rect;
|
|
||||||
pub use state::*;
|
|
||||||
|
|
||||||
/// 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 {
|
|
||||||
// $state is needed to get the scope at the usage point
|
|
||||||
// $Type is the Component type that is being registered
|
|
||||||
($state: ident <- $( $Type: ty ),*,) => {
|
|
||||||
$(
|
|
||||||
$state.ecs.register::<$Type>();
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register the Component Structs with Specs
|
|
||||||
fn register_components(state: &mut State) {
|
|
||||||
register!(
|
|
||||||
state <-
|
|
||||||
AlwaysTargetsSelf,
|
|
||||||
ApplyMove,
|
|
||||||
ApplyTeleport,
|
|
||||||
AreaOfEffect,
|
|
||||||
AttributeBonus,
|
|
||||||
Attributes,
|
|
||||||
BlocksTile,
|
|
||||||
BlocksVisibility,
|
|
||||||
Chasing,
|
|
||||||
Confusion,
|
|
||||||
Consumable,
|
|
||||||
CursedItem,
|
|
||||||
DamageOverTime,
|
|
||||||
DMSerializationHelper,
|
|
||||||
Door,
|
|
||||||
Duration,
|
|
||||||
EntityMoved,
|
|
||||||
EntryTrigger,
|
|
||||||
EquipmentChanged,
|
|
||||||
Equippable,
|
|
||||||
Equipped,
|
|
||||||
Faction,
|
|
||||||
Hidden,
|
|
||||||
HungerClock,
|
|
||||||
IdentifiedItem,
|
|
||||||
InBackpack,
|
|
||||||
InflictsDamage,
|
|
||||||
Initiative,
|
|
||||||
Item,
|
|
||||||
KnownSpells,
|
|
||||||
LightSource,
|
|
||||||
LootTable,
|
|
||||||
MagicItem,
|
|
||||||
MagicMapper,
|
|
||||||
MoveMode,
|
|
||||||
MyTurn,
|
|
||||||
Name,
|
|
||||||
NaturalAttackDefense,
|
|
||||||
ObfuscatedName,
|
|
||||||
OnDeath,
|
|
||||||
OtherLevelPosition,
|
|
||||||
ParticleLifetime,
|
|
||||||
Player,
|
|
||||||
Pools,
|
|
||||||
Position,
|
|
||||||
ProvidesFood,
|
|
||||||
ProvidesHealing,
|
|
||||||
ProvidesIdentification,
|
|
||||||
ProvidesMana,
|
|
||||||
ProvidesRemoveCurse,
|
|
||||||
Quips,
|
|
||||||
Ranged,
|
|
||||||
Renderable,
|
|
||||||
SerializationHelper,
|
|
||||||
SimpleMarker<SerializeMe>,
|
|
||||||
SingleActivation,
|
|
||||||
Skills,
|
|
||||||
Slow,
|
|
||||||
SpawnParticleBurst,
|
|
||||||
SpawnParticleLine,
|
|
||||||
SpecialAbilities,
|
|
||||||
SpellTemplate,
|
|
||||||
StatusEffect,
|
|
||||||
Target,
|
|
||||||
TeachesSpell,
|
|
||||||
TeleportTo,
|
|
||||||
TileSize,
|
|
||||||
TownPortal,
|
|
||||||
Vendor,
|
|
||||||
Viewshed,
|
|
||||||
WantsToApproach,
|
|
||||||
WantsToCastSpell,
|
|
||||||
WantsToDropItem,
|
|
||||||
WantsToFlee,
|
|
||||||
WantsToMelee,
|
|
||||||
WantsToPickupItem,
|
|
||||||
WantsToRemoveItem,
|
|
||||||
WantsToShoot,
|
|
||||||
WantsToUseItem,
|
|
||||||
Weapon,
|
|
||||||
Wearable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 {
|
|
||||||
use systems::particle_system::ParticleBuilder;
|
|
||||||
|
|
||||||
let mut state = State::new();
|
|
||||||
|
|
||||||
register_components(&mut state);
|
|
||||||
|
|
||||||
state
|
|
||||||
.ecs
|
|
||||||
.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
|
||||||
|
|
||||||
raws::load_raws();
|
|
||||||
|
|
||||||
state.ecs.insert(MasterDungeonMap::new());
|
|
||||||
state.ecs.insert(Map::new(1, 64, 64, "New Map"));
|
|
||||||
state.ecs.insert(Point::zero());
|
|
||||||
|
|
||||||
let player_entity = spawner::player(&mut state.ecs, 0, 0);
|
|
||||||
state.ecs.insert(player_entity);
|
|
||||||
|
|
||||||
state.ecs.insert(RunState::MapGeneration {});
|
|
||||||
state.ecs.insert(ParticleBuilder::new());
|
|
||||||
state.ecs.insert(rex_assets::RexAssets::new());
|
|
||||||
|
|
||||||
state.generate_world_map(1, 0);
|
|
||||||
|
|
||||||
state
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The entry point
|
/// The entry point
|
||||||
fn main() -> BError {
|
fn main() -> BError {
|
||||||
@ -194,5 +10,5 @@ fn main() -> BError {
|
|||||||
.with_vsync(false)
|
.with_vsync(false)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
main_loop(context, init_state())
|
main_loop(context, ::tim_rogue::init_state())
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ mod weapon_traits;
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use ::bracket_lib::prelude::*;
|
use ::bracket_lib::prelude::*;
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
use ::serde::Deserialize;
|
use ::serde::Deserialize;
|
||||||
pub use faction_structs::*;
|
pub use faction_structs::*;
|
||||||
use item_structs::*;
|
use item_structs::*;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use ::bracket_lib::prelude::*;
|
use ::bracket_lib::prelude::*;
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
use ::regex::Regex;
|
use ::regex::Regex;
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
use ::specs::saveload::{MarkedBuilder, SimpleMarker};
|
use ::specs::saveload::{MarkedBuilder, SimpleMarker};
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
//! The random number generator, using a mutex to share the instance
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use ::bracket_lib::prelude::*;
|
use ::bracket_lib::prelude::*;
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref RNG: Mutex<RandomNumberGenerator> = Mutex::new(RandomNumberGenerator::new());
|
static ref RNG: Mutex<RandomNumberGenerator> = Mutex::new(RandomNumberGenerator::new());
|
||||||
@ -11,10 +13,12 @@ pub fn reseed(seed: u64) {
|
|||||||
*RNG.lock().unwrap() = RandomNumberGenerator::seeded(seed);
|
*RNG.lock().unwrap() = RandomNumberGenerator::seeded(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rolls `n` dice, with `die_type` sides
|
||||||
pub fn roll_dice(n: i32, die_type: i32) -> i32 {
|
pub fn roll_dice(n: i32, die_type: i32) -> i32 {
|
||||||
RNG.lock().unwrap().roll_dice(n, die_type)
|
RNG.lock().unwrap().roll_dice(n, die_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a number in the range given
|
||||||
pub fn range(min: i32, max: i32) -> i32 {
|
pub fn range(min: i32, max: i32) -> i32 {
|
||||||
RNG.lock().unwrap().range(min, max)
|
RNG.lock().unwrap().range(min, max)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use ::lazy_static::lazy_static;
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
use crate::{tile_walkable, Map, RunState};
|
use crate::{tile_walkable, Map, RunState};
|
||||||
|
Loading…
Reference in New Issue
Block a user