Add breakable walls and monster collision with them
This commit is contained in:
parent
c2db40dd6b
commit
9ad3d9de0b
7 changed files with 91 additions and 33 deletions
|
@ -6,9 +6,4 @@ use specs_derive::Component;
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
pub last_moved: Instant,
|
pub last_moved: Instant,
|
||||||
pub score: u32,
|
|
||||||
pub gems: u32,
|
|
||||||
pub whips: u32,
|
|
||||||
pub teleports: u32,
|
|
||||||
pub keys: u32,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs_derive::Component;
|
use specs_derive::Component;
|
||||||
|
|
||||||
|
@ -6,3 +7,9 @@ pub struct Position {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq<Point> for Position {
|
||||||
|
fn eq(&self, other: &Point) -> bool {
|
||||||
|
return self.x == other.x && self.y == other.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -17,7 +17,7 @@ use components::{
|
||||||
};
|
};
|
||||||
use constants::*;
|
use constants::*;
|
||||||
use map::{Map, TileType};
|
use map::{Map, TileType};
|
||||||
use resources::{Clock, LevelNumber, ShowDebugInfo};
|
use resources::{Clock, LevelNumber, ShowDebugInfo, Stats};
|
||||||
use sound::SoundSystem;
|
use sound::SoundSystem;
|
||||||
use sound_effects::SoundEffects;
|
use sound_effects::SoundEffects;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
@ -178,6 +178,13 @@ fn main() -> BError {
|
||||||
ticks: 0,
|
ticks: 0,
|
||||||
});
|
});
|
||||||
gs.ecs.insert(sound_effects);
|
gs.ecs.insert(sound_effects);
|
||||||
|
gs.ecs.insert(Stats {
|
||||||
|
score: 1290,
|
||||||
|
gems: 14,
|
||||||
|
whips: 7,
|
||||||
|
teleports: 0,
|
||||||
|
keys: 0,
|
||||||
|
});
|
||||||
|
|
||||||
gs.ecs.register::<Position>();
|
gs.ecs.register::<Position>();
|
||||||
gs.ecs.register::<Renderable>();
|
gs.ecs.register::<Renderable>();
|
||||||
|
@ -225,11 +232,6 @@ fn main() -> BError {
|
||||||
})
|
})
|
||||||
.with(Player {
|
.with(Player {
|
||||||
last_moved: Instant::now(),
|
last_moved: Instant::now(),
|
||||||
score: 1290,
|
|
||||||
gems: 14,
|
|
||||||
whips: 7,
|
|
||||||
teleports: 0,
|
|
||||||
keys: 0,
|
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
29
src/map.rs
29
src/map.rs
|
@ -7,6 +7,7 @@ use bracket_lib::{prelude::*, random::RandomNumberGenerator};
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum TileType {
|
pub enum TileType {
|
||||||
Wall,
|
Wall,
|
||||||
|
BreakableWall,
|
||||||
Floor,
|
Floor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +36,10 @@ impl Map {
|
||||||
let mut tiles = vec![TileType::Floor; MAP_SIZE];
|
let mut tiles = vec![TileType::Floor; MAP_SIZE];
|
||||||
let mut rng = RandomNumberGenerator::new();
|
let mut rng = RandomNumberGenerator::new();
|
||||||
for tile in &mut tiles {
|
for tile in &mut tiles {
|
||||||
if rng.roll_dice(1, 4) < 2 {
|
if rng.roll_dice(1, 16) < 2 {
|
||||||
*tile = TileType::Wall;
|
*tile = TileType::Wall;
|
||||||
|
} else if rng.roll_dice(1, 16) < 2 {
|
||||||
|
*tile = TileType::BreakableWall;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
|
@ -78,7 +81,7 @@ impl Map {
|
||||||
to_cp437(' '),
|
to_cp437(' '),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TileType::Wall => {
|
TileType::BreakableWall => {
|
||||||
ctx.set(
|
ctx.set(
|
||||||
x + MAP_X,
|
x + MAP_X,
|
||||||
y + MAP_Y,
|
y + MAP_Y,
|
||||||
|
@ -87,15 +90,33 @@ impl Map {
|
||||||
to_cp437('▓'),
|
to_cp437('▓'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
TileType::Wall => {
|
||||||
|
ctx.set(
|
||||||
|
x + MAP_X,
|
||||||
|
y + MAP_Y,
|
||||||
|
RGB::named(vga::YELLOW),
|
||||||
|
RGB::named(vga::BLACK),
|
||||||
|
to_cp437('█'),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tile_at(&self, point: Point) -> TileType {
|
pub fn get_tile_at(&self, point: Point) -> TileType {
|
||||||
self.tiles[self.point2d_to_index(point)]
|
self.tiles[self.point2d_to_index(point)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_tile_at(&mut self, point: Point, tile: TileType) {
|
||||||
|
let index = self.point2d_to_index(point);
|
||||||
|
self.tiles[index] = tile;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_solid(&self, point: Point) -> bool {
|
pub fn is_solid(&self, point: Point) -> bool {
|
||||||
self.tile_at(point) == TileType::Wall
|
match self.get_tile_at(point) {
|
||||||
|
TileType::Wall => true,
|
||||||
|
TileType::BreakableWall => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,3 +32,11 @@ impl Clock {
|
||||||
self.ticks += 1;
|
self.ticks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Stats {
|
||||||
|
pub score: u32,
|
||||||
|
pub gems: u32,
|
||||||
|
pub whips: u32,
|
||||||
|
pub teleports: u32,
|
||||||
|
pub keys: u32,
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::constants::{SIDEBAR_POS_X, SIDEBAR_POS_Y};
|
use crate::constants::{SIDEBAR_POS_X, SIDEBAR_POS_Y};
|
||||||
use crate::resources::{Clock, ShowDebugInfo};
|
use crate::resources::{Clock, LevelNumber, ShowDebugInfo, Stats};
|
||||||
use crate::vga_color as vga;
|
use crate::vga_color as vga;
|
||||||
use crate::{LevelNumber, Player};
|
|
||||||
use bracket_lib::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
@ -47,14 +46,12 @@ pub fn draw(ecs: &World, ctx: &mut BTerm) {
|
||||||
ctx.print(SIDEBAR_POS_X + 2, SIDEBAR_POS_Y + 12, "Teleports");
|
ctx.print(SIDEBAR_POS_X + 2, SIDEBAR_POS_Y + 12, "Teleports");
|
||||||
ctx.print(SIDEBAR_POS_X + 4, SIDEBAR_POS_Y + 15, "Keys");
|
ctx.print(SIDEBAR_POS_X + 4, SIDEBAR_POS_Y + 15, "Keys");
|
||||||
|
|
||||||
let players = ecs.read_storage::<Player>();
|
let stats = ecs.read_resource::<Stats>();
|
||||||
for player in players.join() {
|
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 1, stats.score);
|
||||||
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 1, player.score);
|
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 7, stats.gems);
|
||||||
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 7, player.gems);
|
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 10, stats.whips);
|
||||||
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 10, player.whips);
|
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 13, stats.teleports);
|
||||||
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 13, player.teleports);
|
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 16, stats.keys);
|
||||||
ctx.print_centered_at(SIDEBAR_POS_X + 6, SIDEBAR_POS_Y + 16, player.keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hotkey list
|
// Hotkey list
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
|
|
|
@ -3,8 +3,8 @@ use crate::{
|
||||||
monster::{self, ticks_for_kind},
|
monster::{self, ticks_for_kind},
|
||||||
Monster, Position, Renderable,
|
Monster, Position, Renderable,
|
||||||
},
|
},
|
||||||
map::Map,
|
map::{Map, TileType},
|
||||||
resources::Clock,
|
resources::{Clock, Stats},
|
||||||
};
|
};
|
||||||
use bracket_lib::{prelude::*, random::RandomNumberGenerator};
|
use bracket_lib::{prelude::*, random::RandomNumberGenerator};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
@ -14,9 +14,11 @@ pub struct MonsterMotion {}
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
impl<'a> System<'a> for MonsterMotion {
|
impl<'a> System<'a> for MonsterMotion {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
|
Entities<'a>,
|
||||||
ReadExpect<'a, Clock>,
|
ReadExpect<'a, Clock>,
|
||||||
ReadExpect<'a, Point>,
|
ReadExpect<'a, Point>,
|
||||||
ReadExpect<'a, Map>,
|
WriteExpect<'a, Map>,
|
||||||
|
WriteExpect<'a, Stats>,
|
||||||
WriteStorage<'a, Monster>,
|
WriteStorage<'a, Monster>,
|
||||||
WriteStorage<'a, Position>,
|
WriteStorage<'a, Position>,
|
||||||
WriteStorage<'a, Renderable>,
|
WriteStorage<'a, Renderable>,
|
||||||
|
@ -24,9 +26,19 @@ impl<'a> System<'a> for MonsterMotion {
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
(clock, player_pos, map, mut monster, mut position, mut renderable): Self::SystemData,
|
(
|
||||||
|
entities,
|
||||||
|
clock,
|
||||||
|
player_pos,
|
||||||
|
mut map,
|
||||||
|
mut stats,
|
||||||
|
mut monster,
|
||||||
|
mut position,
|
||||||
|
mut renderable,
|
||||||
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
for (monster, position, renderable) in (&mut monster, &mut position, &mut renderable).join()
|
for (entity, monster, position, renderable) in
|
||||||
|
(&entities, &mut monster, &mut position, &mut renderable).join()
|
||||||
{
|
{
|
||||||
if clock.has_ticked {
|
if clock.has_ticked {
|
||||||
monster.ticks_until_move -= 1;
|
monster.ticks_until_move -= 1;
|
||||||
|
@ -57,10 +69,26 @@ impl<'a> System<'a> for MonsterMotion {
|
||||||
x: position.x + delta_x,
|
x: position.x + delta_x,
|
||||||
y: position.y + delta_y,
|
y: position.y + delta_y,
|
||||||
};
|
};
|
||||||
if !map.is_solid(destination) {
|
|
||||||
|
if destination == *player_pos {
|
||||||
|
// TODO: Sound
|
||||||
|
stats.gems -= 1;
|
||||||
|
let _ = entities.delete(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
match map.get_tile_at(destination) {
|
||||||
|
TileType::Wall => {}
|
||||||
|
TileType::BreakableWall => {
|
||||||
|
// TODO: Sound
|
||||||
|
map.set_tile_at(destination, TileType::Floor);
|
||||||
|
let _ = entities.delete(entity);
|
||||||
|
}
|
||||||
|
TileType::Floor => {
|
||||||
position.x = destination.x;
|
position.x = destination.x;
|
||||||
position.y = destination.y;
|
position.y = destination.y;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
monster.ticks_until_move = ticks_for_kind(monster.kind);
|
monster.ticks_until_move = ticks_for_kind(monster.kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue