//! Roguelike //! //! An implementation of a rogue-like dungeon-crawler game. #[macro_use] extern crate lazy_static; mod ai; pub mod camera; mod colors; mod components; mod damage_system; mod effects; mod game_log; mod gamesystem; mod gui; mod hunger_system; mod inventory_system; mod lighting_system; mod map; pub mod map_builders; mod map_indexing_system; mod melee_combat_system; mod movement_system; mod particle_system; mod player; mod random_table; mod raws; mod rect; mod rex_assets; mod saveload_system; mod spatial; mod spawner; mod state; mod trigger_system; mod visibility_system; use ::specs::prelude::*; use ::specs::saveload::{SimpleMarker, SimpleMarkerAllocator}; use components::*; pub use game_log::GameLog; 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>(); )* } } /// 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 { let mut state = State::new(); register!( state <- AlwaysTargetsSelf, ApplyMove, ApplyTeleport, AreaOfEffect, AttributeBonus, Attributes, BlocksTile, BlocksVisibility, Chasing, Confusion, Consumable, CursedItem, DamageOverTime, Door, DMSerializationHelper, Duration, EntityMoved, EntryTrigger, Equippable, Equipped, EquipmentChanged, Faction, Hidden, HungerClock, IdentifiedItem, InBackpack, InflictsDamage, Initiative, Item, KnownSpells, LightSource, LootTable, MagicItem, MagicMapper, MeleeWeapon, 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, TeachesSpell, TeleportTo, TileSize, TownPortal, Vendor, Viewshed, WantsToApproach, WantsToCastSpell, WantsToDropItem, WantsToFlee, WantsToMelee, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem, Wearable, ); 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(::rltk::Point::zero()); state.ecs.insert(::rltk::RandomNumberGenerator::new()); let player_entity = spawner::player(&mut state.ecs, 0, 0); state.ecs.insert(player_entity); state.ecs.insert(RunState::MapGeneration {}); state.ecs.insert(GameLog::new("Welcome to Rusty Roguelike")); state.ecs.insert(particle_system::ParticleBuilder::new()); state.ecs.insert(rex_assets::RexAssets::new()); state.generate_world_map(1, 0); state } /// The entry point fn main() -> ::rltk::BError { let context = ::rltk::RltkBuilder::simple(80, 60) .unwrap() .with_title("Roguelike Tutorial") .build()?; ::rltk::main_loop(context, init_state()) }