diff options
author | Griffin Smith <root@gws.fyi> | 2019-07-09T00·58-0400 |
---|---|---|
committer | Griffin Smith <root@gws.fyi> | 2019-07-09T00·58-0400 |
commit | 5af2429ecb5742383cf0798ce23682d316bdb24d (patch) | |
tree | 0fba959d9a5bce5c749c8529b3f2ea7b557c5767 /src/game.rs | |
parent | 20f1ccb4600b88ac01768e912e6d5837534ca852 (diff) |
Implement a global map of entities
Implement a global map of entities, which allows referencing by either position or ID and updating the positions of existent entities, and put the character in there.
Diffstat (limited to 'src/game.rs')
-rw-r--r-- | src/game.rs | 78 |
1 files changed, 62 insertions, 16 deletions
diff --git a/src/game.rs b/src/game.rs index daa5fa575f68..90d94dc5f220 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,10 +1,14 @@ use crate::display::{self, Viewport}; use crate::entities::Character; +use crate::entities::Entity; use crate::messages::message; use crate::settings::Settings; use crate::types::command::Command; -use crate::types::Positioned; -use crate::types::{BoundingBox, Dimensions, Position}; +use crate::types::entity_map::EntityID; +use crate::types::entity_map::EntityMap; +use crate::types::{ + BoundingBox, Collision, Dimensions, Position, Positioned, PositionedMut, +}; use rand::rngs::SmallRng; use rand::SeedableRng; use std::io::{self, StdinLock, StdoutLock, Write}; @@ -16,6 +20,20 @@ type Stdout<'a> = RawTerminal<StdoutLock<'a>>; type Rng = SmallRng; +type AnEntity<'a> = Box<dyn Entity>; + +impl<'a> Positioned for AnEntity<'a> { + fn position(&self) -> Position { + (**self).position() + } +} + +impl<'a> PositionedMut for AnEntity<'a> { + fn set_position(&mut self, pos: Position) { + (**self).set_position(pos) + } +} + /// The full state of a running Game pub struct Game<'a> { settings: Settings, @@ -25,8 +43,11 @@ pub struct Game<'a> { /// An iterator on keypresses from the user keys: Keys<StdinLock<'a>>, - /// The player character - character: Character, + /// The map of all the entities in the game + entities: EntityMap<AnEntity<'a>>, + + /// The entity ID of the player character + character_entity_id: EntityID, /// The messages that have been said to the user, in forward time order messages: Vec<String>, @@ -51,6 +72,7 @@ impl<'a> Game<'a> { Some(seed) => SmallRng::seed_from_u64(seed), None => SmallRng::from_entropy(), }; + let mut entities: EntityMap<AnEntity<'a>> = EntityMap::new(); Game { settings, rng, @@ -61,19 +83,34 @@ impl<'a> Game<'a> { stdout, ), keys: stdin.keys(), - character: Character::new(), + character_entity_id: entities.insert(Box::new(Character::new())), messages: Vec::new(), + entities, } } - /// Returns true if there's a collision in the game at the given Position - fn collision_at(&self, pos: Position) -> bool { - !pos.within(self.viewport.inner) + /// Returns a collision, if any, at the given Position in the game + fn collision_at(&self, pos: Position) -> Option<Collision> { + if !pos.within(self.viewport.inner) { + Some(Collision::Stop) + } else { + None + } + } + + fn character(&self) -> &Character { + debug!("ents: {:?} cid: {:?}", self.entities.ids().map(|id| *id).collect::<Vec<u32>>(), self.character_entity_id); + (*self.entities.get(self.character_entity_id).unwrap()) + .downcast_ref() + .unwrap() } /// Draw all the game entities to the screen fn draw_entities(&mut self) -> io::Result<()> { - self.viewport.draw(&self.character) + for entity in self.entities.entities() { + self.viewport.draw(entity)?; + } + Ok(()) } /// Get a message from the global map based on the rng in this game @@ -104,7 +141,6 @@ impl<'a> Game<'a> { self.viewport.init()?; self.draw_entities()?; self.say("global.welcome")?; - self.say("somethign else")?; self.flush()?; loop { let mut old_position = None; @@ -116,10 +152,18 @@ impl<'a> Game<'a> { } Some(Move(direction)) => { - let new_pos = self.character.position + direction; - if !self.collision_at(new_pos) { - old_position = Some(self.character.position); - self.character.position = new_pos; + use Collision::*; + let new_pos = self.character().position + direction; + match self.collision_at(new_pos) { + None => { + old_position = Some(self.character().position); + self.entities.update_position( + self.character_entity_id, + new_pos, + ); + } + Some(Combat) => unimplemented!(), + Some(Stop) => (), } } @@ -131,12 +175,14 @@ impl<'a> Game<'a> { match old_position { Some(old_pos) => { self.viewport.clear(old_pos)?; - self.viewport.draw(&self.character)?; + self.viewport.draw( + // TODO this clone feels unnecessary. + &self.character().clone())?; } None => (), } self.flush()?; - debug!("{:?}", self.character); + debug!("{:?}", self.character()); } Ok(()) } |