Compare commits
4 commits
d818c8f7a6
...
82c4358ac7
Author | SHA1 | Date | |
---|---|---|---|
82c4358ac7 | |||
b62f2759de | |||
b2672904c8 | |||
73aa491d24 |
8 changed files with 105 additions and 40 deletions
|
@ -1,4 +1,7 @@
|
||||||
use crate::vga_color as vga;
|
use crate::{
|
||||||
|
resources::{sound_output::SoundSamples, SoundEffects},
|
||||||
|
vga_color as vga,
|
||||||
|
};
|
||||||
use bracket_lib::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs_derive::Component;
|
use specs_derive::Component;
|
||||||
|
@ -47,3 +50,11 @@ pub fn damage_for_kind(kind: MonsterKind) -> u32 {
|
||||||
MonsterKind::Fast => 3,
|
MonsterKind::Fast => 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sound_effect_for_kind(kind: MonsterKind, sound_effects: &SoundEffects) -> SoundSamples {
|
||||||
|
match kind {
|
||||||
|
MonsterKind::Slow => sound_effects.slow_hit.clone(),
|
||||||
|
MonsterKind::Medium => sound_effects.medium_hit.clone(),
|
||||||
|
MonsterKind::Fast => sound_effects.fast_hit.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ fn main() -> BError {
|
||||||
ecs.register::<Player>();
|
ecs.register::<Player>();
|
||||||
ecs.register::<WantsToWhip>();
|
ecs.register::<WantsToWhip>();
|
||||||
|
|
||||||
let map = Map::from_level(levels::get_level(starting_level));
|
let mut map = Map::from_level(levels::get_level(starting_level));
|
||||||
map.spawn_entities(&mut ecs);
|
map.spawn_entities(&mut ecs);
|
||||||
ecs.insert(map);
|
ecs.insert(map);
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,14 @@ impl Map {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_entities(&self, ecs: &mut World) {
|
pub fn spawn_entities(&mut self, ecs: &mut World) {
|
||||||
for (index, tile) in self.tiles.iter().enumerate() {
|
for (index, tile) in self
|
||||||
let point = self.index_to_point2d(index);
|
.tiles
|
||||||
|
.iter_mut()
|
||||||
|
.enumerate()
|
||||||
|
.collect::<Vec<(usize, &mut TileType)>>()
|
||||||
|
{
|
||||||
|
let point = Point::new(index % MAP_WIDTH, index / MAP_WIDTH);
|
||||||
match tile {
|
match tile {
|
||||||
TileType::Player => {
|
TileType::Player => {
|
||||||
let player_entity = ecs
|
let player_entity = ecs
|
||||||
|
@ -102,6 +107,7 @@ impl Map {
|
||||||
.build();
|
.build();
|
||||||
ecs.insert(point);
|
ecs.insert(point);
|
||||||
ecs.insert(player_entity);
|
ecs.insert(player_entity);
|
||||||
|
self.tile_content[index] = Some(player_entity);
|
||||||
}
|
}
|
||||||
TileType::Slow => {
|
TileType::Slow => {
|
||||||
let mut rng = RandomNumberGenerator::new();
|
let mut rng = RandomNumberGenerator::new();
|
||||||
|
@ -174,15 +180,18 @@ impl Map {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tile_content(&self, index: usize) -> Option<Entity> {
|
pub fn get_tile_content_at(&self, point: Point) -> Option<Entity> {
|
||||||
|
let index = self.point2d_to_index(point);
|
||||||
self.tile_content[index]
|
self.tile_content[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_tile_content(&mut self, index: usize, entity: Entity) {
|
pub fn set_tile_content_at(&mut self, point: Point, entity: Entity) {
|
||||||
|
let index = self.point2d_to_index(point);
|
||||||
self.tile_content[index] = Some(entity);
|
self.tile_content[index] = Some(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_tile_content(&mut self, index: usize) {
|
pub fn clear_tile_content_at(&mut self, point: Point) {
|
||||||
|
let index = self.point2d_to_index(point);
|
||||||
self.tile_content[index] = None;
|
self.tile_content[index] = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +236,11 @@ impl Map {
|
||||||
self.tiles[self.point2d_to_index(point)]
|
self.tiles[self.point2d_to_index(point)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_tile_at_mut(&mut self, point: Point) -> &mut TileType {
|
||||||
|
let index = self.point2d_to_index(point);
|
||||||
|
&mut self.tiles[index]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_tile_at(&mut self, point: Point, tile: TileType) {
|
pub fn set_tile_at(&mut self, point: Point, tile: TileType) {
|
||||||
let index = self.point2d_to_index(point);
|
let index = self.point2d_to_index(point);
|
||||||
self.tiles[index] = tile;
|
self.tiles[index] = tile;
|
||||||
|
|
|
@ -70,4 +70,8 @@ impl Stats {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_score(&mut self, score: u32) {
|
||||||
|
self.score += score;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,19 +35,22 @@ pub struct SoundEffects {
|
||||||
pub whipping: SoundSamples,
|
pub whipping: SoundSamples,
|
||||||
pub whipping_hit: SoundSamples,
|
pub whipping_hit: SoundSamples,
|
||||||
pub whipping_hit_end: SoundSamples,
|
pub whipping_hit_end: SoundSamples,
|
||||||
|
pub slow_hit: SoundSamples,
|
||||||
|
pub medium_hit: SoundSamples,
|
||||||
|
pub fast_hit: SoundSamples,
|
||||||
rng: RandomNumberGenerator,
|
rng: RandomNumberGenerator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SoundEffects {
|
impl SoundEffects {
|
||||||
pub fn new(ss: &SoundOutput) -> Self {
|
pub fn new(sound_output: &SoundOutput) -> Self {
|
||||||
Self {
|
Self {
|
||||||
startup: ss.render_sound_effect(&SoundEffect {
|
startup: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: vec![Sound {
|
sounds: vec![Sound {
|
||||||
sound_type: SoundType::Sweep(1, 350),
|
sound_type: SoundType::Sweep(1, 350),
|
||||||
duration: Duration::from_secs(1),
|
duration: Duration::from_secs(1),
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
step: ss.render_sound_effect(&SoundEffect {
|
step: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: vec![
|
sounds: vec![
|
||||||
Sound {
|
Sound {
|
||||||
sound_type: SoundType::Noise(350, 900),
|
sound_type: SoundType::Noise(350, 900),
|
||||||
|
@ -63,7 +66,7 @@ impl SoundEffects {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
pickup: ss.render_sound_effect(&SoundEffect {
|
pickup: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: vec![
|
sounds: vec![
|
||||||
Sound {
|
Sound {
|
||||||
sound_type: SoundType::Noise(350, 900),
|
sound_type: SoundType::Noise(350, 900),
|
||||||
|
@ -79,7 +82,7 @@ impl SoundEffects {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
bad_key: ss.render_sound_effect(&SoundEffect {
|
bad_key: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: iter::once(Sound {
|
sounds: iter::once(Sound {
|
||||||
sound_type: SoundType::Tone(540),
|
sound_type: SoundType::Tone(540),
|
||||||
duration: Duration::from_millis(40),
|
duration: Duration::from_millis(40),
|
||||||
|
@ -98,7 +101,7 @@ impl SoundEffects {
|
||||||
}))
|
}))
|
||||||
.collect(),
|
.collect(),
|
||||||
}),
|
}),
|
||||||
blocked: ss.render_sound_effect(&SoundEffect {
|
blocked: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: (30..=60)
|
sounds: (30..=60)
|
||||||
.rev()
|
.rev()
|
||||||
.step_by(6)
|
.step_by(6)
|
||||||
|
@ -108,13 +111,13 @@ impl SoundEffects {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}),
|
}),
|
||||||
whipping: ss.render_sound_effect(&SoundEffect {
|
whipping: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: vec![Sound {
|
sounds: vec![Sound {
|
||||||
sound_type: SoundType::Tone(70),
|
sound_type: SoundType::Tone(70),
|
||||||
duration: Duration::from_secs(3),
|
duration: Duration::from_secs(3),
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
whipping_hit: ss.render_sound_effect(&SoundEffect {
|
whipping_hit: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: vec![
|
sounds: vec![
|
||||||
Sound {
|
Sound {
|
||||||
sound_type: SoundType::Tone(400),
|
sound_type: SoundType::Tone(400),
|
||||||
|
@ -126,12 +129,30 @@ impl SoundEffects {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
whipping_hit_end: ss.render_sound_effect(&SoundEffect {
|
whipping_hit_end: sound_output.render_sound_effect(&SoundEffect {
|
||||||
sounds: vec![Sound {
|
sounds: vec![Sound {
|
||||||
sound_type: SoundType::Tone(400),
|
sound_type: SoundType::Tone(400),
|
||||||
duration: Duration::from_millis(20),
|
duration: Duration::from_millis(20),
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
|
slow_hit: sound_output.render_sound_effect(&SoundEffect {
|
||||||
|
sounds: vec![Sound {
|
||||||
|
sound_type: SoundType::Tone(400),
|
||||||
|
duration: Duration::from_millis(25),
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
medium_hit: sound_output.render_sound_effect(&SoundEffect {
|
||||||
|
sounds: vec![Sound {
|
||||||
|
sound_type: SoundType::Tone(600),
|
||||||
|
duration: Duration::from_millis(25),
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
fast_hit: sound_output.render_sound_effect(&SoundEffect {
|
||||||
|
sounds: vec![Sound {
|
||||||
|
sound_type: SoundType::Tone(800),
|
||||||
|
duration: Duration::from_millis(25),
|
||||||
|
}],
|
||||||
|
}),
|
||||||
rng: RandomNumberGenerator::new(),
|
rng: RandomNumberGenerator::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
src/state.rs
24
src/state.rs
|
@ -1,6 +1,7 @@
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::components::monster::damage_for_kind;
|
use crate::components::monster::damage_for_kind;
|
||||||
|
use crate::components::monster::sound_effect_for_kind;
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::resources::*;
|
use crate::resources::*;
|
||||||
use crate::systems::*;
|
use crate::systems::*;
|
||||||
|
@ -119,7 +120,7 @@ impl State {
|
||||||
let monsters = self.ecs.write_storage::<Monster>();
|
let monsters = self.ecs.write_storage::<Monster>();
|
||||||
let mut map = self.ecs.write_resource::<Map>();
|
let mut map = self.ecs.write_resource::<Map>();
|
||||||
let mut stats = self.ecs.write_resource::<Stats>();
|
let mut stats = self.ecs.write_resource::<Stats>();
|
||||||
let mut sound_system = self.ecs.write_resource::<SoundOutput>();
|
let mut sound_output = self.ecs.write_resource::<SoundOutput>();
|
||||||
let wants_to_whips = self.ecs.read_storage::<WantsToWhip>();
|
let wants_to_whips = self.ecs.read_storage::<WantsToWhip>();
|
||||||
|
|
||||||
for (player_entity, player, pos) in (&entities, &mut players, &mut positions).join() {
|
for (player_entity, player, pos) in (&entities, &mut players, &mut positions).join() {
|
||||||
|
@ -139,17 +140,21 @@ impl State {
|
||||||
|
|
||||||
if map.in_bounds(destination) {
|
if map.in_bounds(destination) {
|
||||||
if map.is_solid(destination) {
|
if map.is_solid(destination) {
|
||||||
sound_system.play_sound(sound_effects.blocked.clone());
|
sound_output.play_sound(sound_effects.blocked.clone());
|
||||||
} else {
|
} else {
|
||||||
if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) {
|
if let Some(e) = map.get_tile_content_at(destination) {
|
||||||
if let Some(monster) = monsters.get(e) {
|
if let Some(monster) = monsters.get(e) {
|
||||||
|
stats.add_score(damage_for_kind(monster.kind));
|
||||||
stats.take_gems(damage_for_kind(monster.kind));
|
stats.take_gems(damage_for_kind(monster.kind));
|
||||||
|
sound_output.play_sound(sound_effect_for_kind(
|
||||||
|
monster.kind,
|
||||||
|
&sound_effects,
|
||||||
|
));
|
||||||
let _ = entities.delete(e);
|
let _ = entities.delete(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = map.point2d_to_index(Point::from(*pos));
|
map.clear_tile_content_at(Point::from(*pos));
|
||||||
map.clear_tile_content(index);
|
|
||||||
|
|
||||||
pos.x = destination.x;
|
pos.x = destination.x;
|
||||||
pos.y = destination.y;
|
pos.y = destination.y;
|
||||||
|
@ -158,16 +163,15 @@ impl State {
|
||||||
player_pos.x = pos.x;
|
player_pos.x = pos.x;
|
||||||
player_pos.y = pos.y;
|
player_pos.y = pos.y;
|
||||||
|
|
||||||
let index = map.point2d_to_index(destination);
|
map.set_tile_content_at(destination, player_entity);
|
||||||
map.set_tile_content(index, player_entity);
|
|
||||||
|
|
||||||
self.ecs.write_resource::<Clock>().force_tick();
|
self.ecs.write_resource::<Clock>().force_tick();
|
||||||
|
|
||||||
sound_system.play_sound(sound_effects.step.clone());
|
sound_output.play_sound(sound_effects.step.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let static_sound = sound_effects.get_new_static_effect(&sound_system);
|
let static_sound = sound_effects.get_new_static_effect(&sound_output);
|
||||||
sound_system.play_sound(static_sound);
|
sound_output.play_sound(static_sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
player.last_moved = now;
|
player.last_moved = now;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{
|
components::{
|
||||||
monster::{self, damage_for_kind, ticks_for_kind},
|
monster::{self, damage_for_kind, sound_effect_for_kind, ticks_for_kind},
|
||||||
Monster, Player, Position, Renderable,
|
Monster, Player, Position, Renderable,
|
||||||
},
|
},
|
||||||
resources::{Clock, Map, Stats},
|
resources::{Clock, Map, SoundEffects, SoundOutput, Stats},
|
||||||
tile_data::TileType,
|
tile_data::TileType,
|
||||||
};
|
};
|
||||||
use bracket_lib::{prelude::*, random::RandomNumberGenerator};
|
use bracket_lib::{prelude::*, random::RandomNumberGenerator};
|
||||||
|
@ -19,6 +19,8 @@ impl<'a> System<'a> for MonsterAiSystem {
|
||||||
ReadExpect<'a, Point>,
|
ReadExpect<'a, Point>,
|
||||||
WriteExpect<'a, Map>,
|
WriteExpect<'a, Map>,
|
||||||
WriteExpect<'a, Stats>,
|
WriteExpect<'a, Stats>,
|
||||||
|
ReadExpect<'a, SoundEffects>,
|
||||||
|
WriteExpect<'a, SoundOutput>,
|
||||||
WriteStorage<'a, Monster>,
|
WriteStorage<'a, Monster>,
|
||||||
WriteStorage<'a, Position>,
|
WriteStorage<'a, Position>,
|
||||||
WriteStorage<'a, Renderable>,
|
WriteStorage<'a, Renderable>,
|
||||||
|
@ -33,6 +35,8 @@ impl<'a> System<'a> for MonsterAiSystem {
|
||||||
player_pos,
|
player_pos,
|
||||||
mut map,
|
mut map,
|
||||||
mut stats,
|
mut stats,
|
||||||
|
sound_effects,
|
||||||
|
mut sound_output,
|
||||||
mut monsters,
|
mut monsters,
|
||||||
mut positions,
|
mut positions,
|
||||||
mut renderables,
|
mut renderables,
|
||||||
|
@ -74,26 +78,29 @@ impl<'a> System<'a> for MonsterAiSystem {
|
||||||
y: position.y + delta_y,
|
y: position.y + delta_y,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) {
|
if let Some(e) = map.get_tile_content_at(destination) {
|
||||||
if let Some(_player) = players.get(e) {
|
if let Some(_player) = players.get(e) {
|
||||||
// TODO: Sound
|
// TODO: Sound
|
||||||
|
map.clear_tile_content_at(Point::from(**position));
|
||||||
stats.take_gems(damage_for_kind(monster.kind));
|
stats.take_gems(damage_for_kind(monster.kind));
|
||||||
|
sound_output
|
||||||
|
.play_sound(sound_effect_for_kind(monster.kind, &sound_effects));
|
||||||
let _ = entities.delete(*entity);
|
let _ = entities.delete(*entity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match map.get_tile_at(destination) {
|
let tile = map.get_tile_at_mut(destination);
|
||||||
|
match tile {
|
||||||
TileType::Wall => {}
|
TileType::Wall => {}
|
||||||
TileType::Block => {
|
TileType::Block => {
|
||||||
// TODO: Sound
|
// TODO: Sound
|
||||||
|
*tile = TileType::Floor;
|
||||||
let _ = entities.delete(*entity);
|
let _ = entities.delete(*entity);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let index = map.point2d_to_index(Point::from(**position));
|
map.clear_tile_content_at(Point::from(**position));
|
||||||
map.clear_tile_content(index);
|
|
||||||
position.x = destination.x;
|
position.x = destination.x;
|
||||||
position.y = destination.y;
|
position.y = destination.y;
|
||||||
let index = map.point2d_to_index(destination);
|
map.set_tile_content_at(destination, *entity);
|
||||||
map.set_tile_content(index, *entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ use bracket_lib::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{Monster, Position, WantsToWhip},
|
components::{monster::damage_for_kind, Monster, Position, WantsToWhip},
|
||||||
resources::{Map, SoundEffects, SoundOutput, StopClock},
|
resources::{Map, SoundEffects, SoundOutput, Stats, StopClock},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct WhipSystem {}
|
pub struct WhipSystem {}
|
||||||
|
@ -17,6 +17,7 @@ impl<'a> System<'a> for WhipSystem {
|
||||||
WriteExpect<'a, StopClock>,
|
WriteExpect<'a, StopClock>,
|
||||||
WriteExpect<'a, SoundOutput>,
|
WriteExpect<'a, SoundOutput>,
|
||||||
ReadExpect<'a, SoundEffects>,
|
ReadExpect<'a, SoundEffects>,
|
||||||
|
WriteExpect<'a, Stats>,
|
||||||
ReadStorage<'a, Position>,
|
ReadStorage<'a, Position>,
|
||||||
WriteStorage<'a, WantsToWhip>,
|
WriteStorage<'a, WantsToWhip>,
|
||||||
WriteStorage<'a, Monster>,
|
WriteStorage<'a, Monster>,
|
||||||
|
@ -25,10 +26,11 @@ impl<'a> System<'a> for WhipSystem {
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (
|
let (
|
||||||
map,
|
mut map,
|
||||||
mut stop_clock,
|
mut stop_clock,
|
||||||
mut sound_output,
|
mut sound_output,
|
||||||
sound_effects,
|
sound_effects,
|
||||||
|
mut stats,
|
||||||
positions,
|
positions,
|
||||||
mut wants_to_whips,
|
mut wants_to_whips,
|
||||||
monsters,
|
monsters,
|
||||||
|
@ -92,9 +94,11 @@ impl<'a> System<'a> for WhipSystem {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(dest) = destination {
|
if let Some(dest) = destination {
|
||||||
if let Some(e) = map.get_tile_content(map.point2d_to_index(dest)) {
|
if let Some(e) = map.get_tile_content_at(dest) {
|
||||||
if let Some(_monster) = monsters.get(e) {
|
if let Some(monster) = monsters.get(e) {
|
||||||
|
stats.add_score(damage_for_kind(monster.kind));
|
||||||
let _ = entities.delete(e);
|
let _ = entities.delete(e);
|
||||||
|
map.clear_tile_content_at(dest);
|
||||||
if let Some(sound) = &mut wants_to_whip.sound {
|
if let Some(sound) = &mut wants_to_whip.sound {
|
||||||
sound.control::<oddio::Stop<_>, _>().stop();
|
sound.control::<oddio::Stop<_>, _>().stop();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue