Browse Source

Added interaction

master
Graham Northup 3 years ago
parent
commit
9ae3fd5eb1
Signed by untrusted user: grissess GPG Key ID: 5D000E6F539376FB
  1. 40
      src/main.rs
  2. 15
      src/world/entity/mod.rs
  3. 55
      src/world/entity/player.rs
  4. 72
      src/world/mod.rs

40
src/main.rs

@ -3,11 +3,41 @@ extern crate rogue_util;
pub mod world;
use rogue_util::{coord::V2i, grid::region::{Region, RegionConfig}};
use rogue_util::{coord::*, grid::{region::{Region, RegionConfig}, path::Traversable}};
use termion::{raw::IntoRawMode, input::TermRead};
use std::io::{self, Write};
fn main() -> Result<(), rogue_util::grid::region::Error>
use world::World;
fn main() -> io::Result<()>
{
let world_grid: Region<world::Tile> = RegionConfig::default().build()?;
unimplemented!();
Ok(())
let stdin = io::stdin();
let mut stdout = io::stdout().into_raw_mode().unwrap();
let mut w = World::new(0, stdin.keys());
let ppos: V2i = {
let mut rg = w.region_mut();
let mut ps: Option<V2i> = None;
for pt in &R2i::origin_dim(V2i(0, 0), rg.grid_size()) {
let tile = rg.get_or_create(pt);
if tile.can_pass() {
ps = Some(pt);
break;
}
}
ps.unwrap()
};
w.player_mut().set_pos(ppos);
let (width, height) = termion::terminal_size()?;
let rs = world::render::RenderState::new(V2i(width as isize, height as isize));
loop {
w.render(&rs, &mut stdout);
stdout.flush();
w.step();
}
}

15
src/world/entity/mod.rs

@ -1,3 +1,5 @@
pub mod player;
use super::*;
use rogue_util::{coord::*, raster, grid::{Grid, region::Region}};
use std::collections::HashMap;
@ -38,6 +40,7 @@ impl LinfDir {
pub enum Action {
Move(LinfDir),
Wait,
Quit,
}
impl Default for Action {
@ -49,6 +52,14 @@ pub struct Observation {
pub sight: SightObs
}
impl Observation {
pub fn new(world: &World, v: V2i, sr: usize) -> Observation {
Observation {
sight: SightObs::new(world, v, sr),
}
}
}
#[derive(Debug, Clone)]
pub struct SightObs {
pub tiles: Grid<Option<V2i>>, // NB: Relative coordinate; 0,0 is this
@ -105,9 +116,11 @@ const DEFAULT_ACT_TIME: usize = 10000;
const ECLS_LIVING: usize = 1;
pub trait Entity: Debug {
pub trait Entity {
fn pos(&self) -> V2i;
fn set_pos(&mut self, v: V2i);
fn next_time(&self) -> usize;
fn set_next_time(&mut self, t: usize);
fn class(&self) -> usize { 0 }
fn hp(&self) -> isize { 100 }

55
src/world/entity/player.rs

@ -0,0 +1,55 @@
use super::*;
use rogue_util::coord::*;
use termion::event::Key;
use std::io;
pub struct Player<R> {
pos: V2i,
hp: usize,
time: usize,
input: R,
}
impl<R> Player<R> {
pub fn new(p: V2i, r: R) -> Player<R> {
Player {
pos: p,
hp: 100,
time: 0,
input: r,
}
}
}
impl<R> Entity for Player<R>
where
R: Iterator<Item=io::Result<Key>>
{
fn pos(&self) -> V2i { self.pos }
fn set_pos(&mut self, p: V2i) { self.pos = p; }
fn next_time(&self) -> usize { self.time }
fn set_next_time(&mut self, t: usize) { self.time = t; }
fn class(&self) -> usize {
ECLS_LIVING
}
fn char(&self) -> char { '@' }
fn act(&mut self, obs: &Observation) -> Action {
use termion::event::Key::*;
loop {
match self.input.next().unwrap().unwrap() {
Char('h') | Char('a') | Left => return Action::Move(LinfDir::L),
Char('j') | Char('s') | Down => return Action::Move(LinfDir::D),
Char('k') | Char('w') | Up => return Action::Move(LinfDir::U),
Char('l') | Char('d') | Right => return Action::Move(LinfDir::R),
Char('y') => return Action::Move(LinfDir::UL),
Char('u') => return Action::Move(LinfDir::UR),
Char('b') => return Action::Move(LinfDir::DL),
Char('n') => return Action::Move(LinfDir::DR),
Char('q') => return Action::Quit,
_ => ()
}
}
}
}

72
src/world/mod.rs

@ -2,10 +2,11 @@ pub mod render;
pub mod gen;
pub mod entity;
use rogue_util::{coord::*, grid::{Grid, region::{Region, RegionConfig}}};
use rogue_util::{coord::*, grid::{Grid, region::{Region, RegionConfig}, path::Traversable}};
use std::cell::RefCell;
use std::io::{self, Write};
use std::ops::{Deref, DerefMut};
use std::fmt::Debug;
use entity::Entity;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -33,7 +34,12 @@ impl Default for Tile {
}
}
#[derive(Debug)]
impl Traversable for Tile {
fn can_pass(&self) -> bool {
self.content == Content::Air
}
}
pub struct World {
seed: u64,
cur_region: usize,
@ -42,7 +48,10 @@ pub struct World {
}
impl World {
pub fn new(seed: u64) -> World {
pub fn new<R>(seed: u64, r: R) -> World
where
R: Iterator<Item=io::Result<termion::event::Key>> + 'static
{
let start_region = RegionConfig::default()
.with_grid_gen(Some(Box::new(move |_, r, o, d| {
let mut g = Grid::from_default(o, d).expect("Failed to generate Grid");
@ -55,7 +64,9 @@ impl World {
seed,
cur_region: 0,
regions: vec![RefCell::new(start_region)],
entities: Vec::new(),
entities: vec![
RefCell::new(Box::new(entity::player::Player::new(V2i(0, 0), r)))
],
}
}
@ -83,7 +94,7 @@ impl World {
self.entities[idx].borrow()
}
pub fn entity_mut<'s>(&'s mut self, idx: usize) -> impl DerefMut<Target=Box<dyn Entity>> + 's {
pub fn entity_mut<'s>(&'s self, idx: usize) -> impl DerefMut<Target=Box<dyn Entity>> + 's {
self.entities[idx].borrow_mut()
}
@ -104,6 +115,55 @@ impl World {
}
Ok(())
}
pub fn step(&mut self) {
let mut ents: Vec<_> = self.entities().enumerate().map(|(i, eref)| {
(i, eref.borrow().next_time())
}).collect();
ents.sort_by_key(|&(_, t)| t);
if let Some((i, t)) = ents.pop() {
let (pos, sr) = {
let mut e = self.entity_mut(i);
let pos = e.pos();
let sr = e.sight();
let dt = e.act_time();
e.set_next_time(t + dt);
(pos, sr)
};
let obs = entity::Observation::new(self as &World, pos, sr);
{
let mut e = self.entity_mut(i);
let act = e.act(&obs);
self.perform_act(e, act);
}
}
}
pub fn perform_act<E: DerefMut<Target=Box<dyn Entity>>>(&self, mut e: E, act: entity::Action) {
use entity::{Action::*, LinfDir};
match act {
Wait => (),
Move(d) => {
let p = e.pos();
let dp = d.to_v2i();
{
let mut rg = self.region_mut();
let tile = rg.get_or_create(p + dp);
if !tile.can_pass() {
return;
}
}
e.set_pos(p + dp);
},
Quit => {
panic!("Thank you for playing Wing Commander");
},
}
}
}
#[cfg(test)]
@ -159,6 +219,8 @@ mod test {
impl Entity for Ent {
fn pos(&self) -> V2i { V2i(0, 0) }
fn set_pos(&mut self, v: V2i) {}
fn next_time(&self) -> usize { 0 }
fn set_next_time(&mut self, t: usize) {}
}
w.add_entity(Box::new(Ent));

Loading…
Cancel
Save