world_digger_ascii

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit 1e371a49fd68e7d70304979737729bfc71998ec7
parent e4ade1aa28412366c2b9dc1ff0571d0e1ce3dfcd
Author: Joël Lupien (Jojolepro) <jojolepro@jojolepro.com>
Date:   Fri, 17 Jul 2020 12:20:10 -0400

switch to minigene

Diffstat:
MCargo.lock | 30++++++++++++++++++++++--------
MCargo.toml | 18+++++++++---------
Msrc/main.rs | 298+++++--------------------------------------------------------------------------
3 files changed, 50 insertions(+), 296 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -756,6 +756,21 @@ dependencies = [ ] [[package]] +name = "minigene" +version = "0.1.0" +dependencies = [ + "bracket-lib", + "derive-new", + "game_features", + "hibitset", + "pushdown-automaton-macro", + "shrev", + "specs", + "specs-derive", + "specs_declaration", +] + +[[package]] name = "miniz_oxide" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1055,6 +1070,12 @@ dependencies = [ ] [[package]] +name = "pushdown-automaton-macro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c3ae625bc8d58d2ae19980066885482b53e6d18c03c419abca4c4cda102f1" + +[[package]] name = "quote" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1783,14 +1804,7 @@ dependencies = [ name = "world_digger_ascii" version = "0.1.0" dependencies = [ - "bracket-lib", - "derive-new", - "game_features", - "hibitset", - "shrev", - "specs", - "specs-derive", - "specs_declaration", + "minigene", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml @@ -8,12 +8,12 @@ edition = "2018" [dependencies] #bracket-lib = { version = "0.8.1", default-features = false, features = ["specs", "threaded", "crossterm"] } -bracket-lib = { path = "../bracket-lib", default-features = false, features = ["specs", "threaded", "crossterm"] } -specs_declaration = { path = "../specs_declaration" } -game_features = { path = "../game_features" } -specs = "0.16.1" -specs-derive = "0.4.1" -shrev = "1.1.1" -hibitset = "0.6.3" -derive-new = "0.5" - +#bracket-lib = { path = "../bracket-lib", default-features = false, features = ["specs", "threaded", "crossterm"] } +#specs_declaration = { path = "../specs_declaration" } +#game_features = { path = "../game_features" } +#specs = "0.16.1" +#specs-derive = "0.4.1" +#shrev = "1.1.1" +#hibitset = "0.6.3" +#derive-new = "0.5" +minigene = { path = "../minigene" } diff --git a/src/main.rs b/src/main.rs @@ -1,48 +1,14 @@ -#[macro_use] -extern crate specs_declaration; -#[macro_use] -extern crate specs_derive; -#[macro_use] -extern crate derive_new; -#[macro_use] -extern crate bracket_lib; - -use bracket_lib::prelude::*; -use specs::prelude::*; -use hibitset::BitSet; -use game_features::*; -use shrev::*; - -add_wasm_support!(); +use minigene::*; pub const SCREEN_WIDTH: u32 = 200; pub const SCREEN_HEIGHT: u32 = 65; pub const WIDTH: u32 = 200; pub const HEIGHT: u32 = 60; -/// Component wrapper for types not implementing Component -#[derive(new)] -pub struct Comp<T>(T); -impl<T: Send+Sync+'static> Component for Comp<T> { - type Storage = DenseVecStorage<Self>; -} - -#[derive(Component)] -pub struct Tower; -#[derive(Component)] -pub struct Creep; -#[derive(Component)] -pub struct CreepSpawner(u32); #[derive(Component)] pub struct Base; #[derive(Component, Default, new, Clone, Copy)] pub struct MiningMapTag; -#[derive(Component)] -pub struct Sprite { - pub glyph: u16, - pub fg: RGBA, - pub bg: RGBA, -} #[derive(Clone, Debug, new)] pub struct Mine { @@ -92,24 +58,7 @@ pub struct Progress { pub mined: u64, pub money: u64, } -#[derive(Component, new)] -pub struct MultiSprite { - pub tile: MultiTileSprite, -} -#[derive(Component, new)] -pub struct AiPath { - pub path: NavigationPath, -} - -#[derive(Component, new)] -pub struct AiDestination { - pub target: Point, -} - -pub struct Spawner<F: Fn(&mut World)> { - f: F, -} #[derive(Component)] pub struct Player; @@ -121,216 +70,21 @@ pub enum Stats { Mana, } -pub struct GameSpeed(f32); - -impl Default for GameSpeed { - fn default() -> Self { - GameSpeed(1.0) - } -} - -// Collision stuff -// Coords starts at the upper right corner -/// Collision of a single tile entity -#[derive(Component)] -pub struct Collision; -/// Collision of a multi tile entity. Not necessarily colliding everywhere. -/// Can be both used as a global resource and as a component for individual entities. -#[derive(Component)] -pub struct CollisionMap { - bitset: BitSet, - width: u32, - height: u32, -} - -impl CollisionMap { - pub fn new(width: u32, height: u32) -> Self { - Self { - bitset: BitSet::with_capacity(width * height), - width, - height, - } - } - - pub fn set(&mut self, x: u32, y: u32) { - self.bitset.add(self.index_of(x, y)); - } - - pub fn unset(&mut self, x: u32, y: u32) { - self.bitset.remove(self.index_of(x, y)); - } - - pub fn is_set(&self, x: u32, y: u32) -> bool { - self.bitset.contains(self.index_of(x, y)) - } - - pub fn size(&self) -> (u32, u32) { - (self.width, self.height) - } - - pub fn clear(&mut self) { - self.bitset.clear(); - } - - pub fn index_of(&self, x: u32, y: u32) -> u32 { - y * self.width + x - } - - pub fn position_of(&self, idx: u32) -> (u32, u32) { - (idx % self.width, idx / self.width) - } -} - -#[cfg(test)] -mod tests { - use crate::CollisionMap; - #[test] - fn collmap() { - let mut m = CollisionMap::new(3, 3); - m.set(2, 2); - assert!(m.is_set(2, 2)); - assert_eq!(m.index_of(2,2), 8); - assert_eq!(m.position_of(8), (2, 2)); - } -} - -#[derive(new)] -pub struct CollisionResource { - pub map: CollisionMap, - pub position: Point, -} - -impl CollisionResource { - pub fn is_inside(&self, p: &Point) -> bool { - position_inside_rect(p.x - self.position.x, p.y - self.position.y, 0, 0, self.map.size().0, self.map.size().1) - } - /// Check is_inside before calling this. - pub fn relative_point(&self, p: &Point) -> (u32, u32) { - ((p.x - self.position.x) as u32, (p.y - self.position.y) as u32) - } -} - -impl Default for CollisionResource { - fn default() -> Self { - Self { - map: CollisionMap::new(WIDTH, HEIGHT), - position: Point::new(0, 0), - } - } -} - -#[derive(new)] -pub struct Camera { - pub position: Point, - pub size: Point, -} - -pub fn position_inside_rect(pos_x: i32, pos_y: i32, rect_x: i32, rect_y: i32, size_x: u32, size_y: u32) -> bool { - pos_x >= rect_x && - pos_y >= rect_y && - pos_x < rect_x + size_x as i32 && - pos_y < rect_y + size_y as i32 -} - -system!(CombineCollisionSystem, |positions: ReadStorage<'a, Point>, collisions: ReadStorage<'a, Collision>, maps: ReadStorage<'a, CollisionMap>, global_map: Write<'a, CollisionResource>| { - global_map.map.clear(); - - for (pos, _) in (&positions, &collisions).join() { - let (x, y) = (pos.x, pos.y); - if position_inside_rect(x, y, global_map.position.x, global_map.position.y, global_map.map.size().0, global_map.map.size().1) { - let (t_x, t_y) = (global_map.position.x, global_map.position.y); - global_map.map.set((x - t_x) as u32, (y - t_y) as u32); - } - } - - for (pos, coll) in (&positions, &maps).join() { - for i in 0..coll.size().0 as i32{ - for j in 0..coll.size().1 as i32 { - let (x, y) = (pos.x + i, pos.y + j); - if coll.is_set(i as u32, j as u32) && position_inside_rect(x, y, global_map.position.x, global_map.position.y, global_map.map.size().0, global_map.map.size().1) { - let (t_x, t_y) = (global_map.position.x, global_map.position.y); - global_map.map.set((x - t_x) as u32, (y - t_y) as u32); - } - } - } - } -}); - -// non portable -//system!(UpdateCollisionResourceSystem, |global_map: Write<'a, CollisionResource>, positions: ReadStorage<'a, Point>, players: ReadStorage<'a, Player>| { -// for j in 0..50usize { -// MAP[j].char_indices().for_each(|(i, c)| { -// if c == '#' { -// global_map.map.set(i as u32, j as u32); -// } else { -// global_map.map.unset(i as u32, j as u32); -// } -// }); -// } -// for (pos, _) in (&positions, &players).join() { -// global_map.position.x = pos.x - 40; -// global_map.position.y = pos.y - 25; -// } -//}); - -system!(CreepSpawnerSystem, |entities: Entities<'a>, positions: WriteStorage<'a, Point>, spawners: WriteStorage<'a, CreepSpawner>, creeps: WriteStorage<'a, Creep>, - ai_destinations: WriteStorage<'a, AiDestination>, ai_paths: WriteStorage<'a, AiPath>, sprites: WriteStorage<'a, Sprite>| { - let mut v = vec![]; - for (pos, mut spawner) in (&positions, &mut spawners).join() { - if spawner.0 == 0 { - spawner.0 = 20; - // spawn - v.push(pos.clone()); - } - spawner.0 -= 1; - } - v.into_iter().for_each(|pos| { - let creep = entities.create(); - positions.insert(creep, pos.clone()).unwrap(); - creeps.insert(creep, Creep).unwrap(); - ai_paths.insert(creep, AiPath::new(NavigationPath::new())).unwrap(); - ai_destinations.insert(creep, AiDestination::new(Point::new(39, 25))).unwrap(); - sprites.insert(creep, Sprite { - glyph: to_cp437('c'), - fg: RGBA::named(YELLOW), - bg: RGBA::named(BLACK), - }).unwrap(); - }); -}); - -//system!(AiPathingSystem, |dests: ReadStorage<'a, AiDestination>, global_map: Read<'a, CollisionResource>, positions: ReadStorage<'a, Point>, paths: WriteStorage<'a, AiPath>| { -// for (pos, dest, path) in (&positions, &dests, &mut paths).join() { -// if pos.x == dest.target.x && pos.y == dest.target.y { -// continue; -// } -// // TODO Safety check for < 0 or out of map bounds -// let d = global_map.map.index_of((pos.x - global_map.position.x) as u32, (pos.y - global_map.position.y) as u32); -// let t = global_map.map.index_of((dest.target.x - global_map.position.x) as u32, (dest.target.y - global_map.position.y) as u32); -// let p = a_star_search(d, t, &global_map.map); -// path.path = p; -// } -//}); - #[derive(new)] pub struct PlayerMovementRes { pub reader: ReaderId<VirtualKeyCode>, } -#[derive(Debug, Clone, Copy)] -pub enum Direction { - Left, Down, Right, Up, -} - -system!(PlayerMovementSystem, |positions: WriteStorage<'a, Point>, players: ReadStorage<'a, Player>, global_map: Read<'a, CollisionResource>, channel: Read<'a, EventChannel<VirtualKeyCode>>, +system!(PlayerMovementSystem, |positions: WriteStorage<'a, Point>, players: ReadStorage<'a, Player>, global_map: ReadExpect<'a, CollisionResource>, channel: Read<'a, EventChannel<VirtualKeyCode>>, res: WriteExpect<'a, PlayerMovementRes>| { // doesn't handle two entities that want to go to the same tile. for key in channel.read(&mut res.reader) { for (mut pos, _) in (&mut positions, &players).join() { match key { - VirtualKeyCode::H => try_move(&mut pos, &global_map, Direction::Left), - VirtualKeyCode::J => try_move(&mut pos, &global_map, Direction::Down), - VirtualKeyCode::L => try_move(&mut pos, &global_map, Direction::Right), - VirtualKeyCode::K => try_move(&mut pos, &global_map, Direction::Up), + VirtualKeyCode::H => try_move(&mut pos, &global_map, Direction::West), + VirtualKeyCode::J => try_move(&mut pos, &global_map, Direction::South), + VirtualKeyCode::L => try_move(&mut pos, &global_map, Direction::East), + VirtualKeyCode::K => try_move(&mut pos, &global_map, Direction::North), _ => {}, } } @@ -342,10 +96,11 @@ pub fn try_move(p: &mut Point, map: &CollisionResource, dir: Direction) { let (rel_x, rel_y) = (p.x - map.position.x, p.y - map.position.y); let mut n = p.clone(); match dir { - Direction::Left => if rel_x > 0 {n.x -= 1}, - Direction::Down => if rel_y < map.map.size().1 as i32 - 1 {n.y += 1}, - Direction::Right => if rel_x < map.map.size().0 as i32 - 1 {n.x += 1}, - Direction::Up => if rel_y > 0 {n.y -= 1}, + Direction::West => if rel_x > 0 {n.x -= 1}, + Direction::South => if rel_y < map.map.size().1 as i32 - 1 {n.y += 1}, + Direction::East => if rel_x < map.map.size().0 as i32 - 1 {n.x += 1}, + Direction::North => if rel_y > 0 {n.y -= 1}, + _ => unreachable!() } if !map.map.is_set((n.x - map.position.x) as u32, (n.y - map.position.y) as u32) { p.x = n.x; @@ -433,12 +188,7 @@ fn render<'a>(ctx: &mut BTerm, camera: &Camera, positions: ReadStorage<'a, Point } } - for (pos, sprite) in (&positions, &multi_sprites).join() { - sprite.tile.render(ctx, Point::new(pos.x - camera.position.x, pos.y - camera.position.y)); - } - for (pos, sprite) in (&positions, &sprites).join() { - ctx.set(pos.x - camera.position.x, pos.y - camera.position.y, sprite.fg, sprite.bg, sprite.glyph); - } + render_sprites(ctx, camera, positions, multi_sprites, sprites); if progress.block_progress == 0 { ctx.draw_bar_horizontal(0, SCREEN_HEIGHT - 5, SCREEN_WIDTH, 1, 1, WHITE, BLACK); @@ -482,30 +232,20 @@ fn init_collision_map(coll: &mut CollisionMap) { } fn main() -> BError { - let context = BTermBuilder::new() - .with_simple_console(SCREEN_WIDTH, SCREEN_HEIGHT, "terminal8x8.png") - .with_font("terminal8x8.png", 8, 8) - .with_title("World Digger") - .with_vsync(false) - .with_advanced_input(true) - .build()?; - let mut world = World::new(); - let mut dispatcher = DispatcherBuilder::new() + let mut builder = DispatcherBuilder::new() .with(CombineCollisionSystem, "combine_collision", &[]) //.with(UpdateCollisionResourceSystem, "update_collision_res", &["combine_collision"]) - .with(CreepSpawnerSystem, "creep_spawner", &[]) .with(PlayerMovementSystem, "player_movement", &[]) .with(ResetSystem, "reset", &[]) - .with(MineSystem, "mine", &[]) - //.with(AiPathingSystem, "ai_pathing", &["update_collision_res"]) - //.with(AiMovementSystem, "ai_movement", &["ai_pathing"]) - .build(); - dispatcher.setup(&mut world); - + .with(MineSystem, "mine", &[]); + let (mut world, mut dispatcher, mut context) = + mini_init(SCREEN_WIDTH, SCREEN_HEIGHT, "World Digger", builder); world.register::<MultiSprite>(); world.register::<Sprite>(); world.register::<Comp<StatSet<Stats>>>(); + + // overwrite the default channel let mut channel = EventChannel::<VirtualKeyCode>::new(); let reader = channel.register_reader(); let reader2 = channel.register_reader(); @@ -515,7 +255,7 @@ fn main() -> BError { world.insert(MineRes::new(reader2)); world.insert(ResetRes::new(reader3)); - world.insert(CollisionResource::default()); + world.insert(CollisionResource::new(CollisionMap::new(WIDTH, HEIGHT), Point::new(0, 0))); world.insert(Camera::new(Point::new(0,0), Point::new(160, 60))); let stat_defs = StatDefinitions::from(vec![ StatDefinition::new(Stats::Health, String::from("health"), String::from("HP"), 100.0),