//! 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 ::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::(); /// state.ecs.register::(); /// ``` 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, 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::::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 fn main() -> BError { let context = BTermBuilder::simple(80, 60) .unwrap() .with_title("Roguelike Tutorial") .with_font("vga8x16.png", 8, 16) .with_sparse_console(80, 30, "vga8x16.png") .with_vsync(false) .build()?; main_loop(context, init_state()) }