WIP: 2.10

This commit is contained in:
Kasper Juul Hermansen 2022-01-27 19:42:51 +01:00
parent ecbecc1a58
commit f2f4c40c28
Signed by: kjuulh
GPG Key ID: 0F95C140730F2F23
7 changed files with 96 additions and 82 deletions

View File

@ -1,9 +1,11 @@
use rltk::{Point, RGB};
use serde::{Deserialize, Serialize};
use specs::error::NoError;
use specs::prelude::*;
use specs::saveload::*;
use specs::saveload::{ConvertSaveload, Marker};
use specs_derive::*;
#[derive(Component, Clone, ConvertSaveload)]
#[derive(Component, ConvertSaveload, Clone)]
pub struct Position {
pub x: i32,
pub y: i32,
@ -17,10 +19,10 @@ pub struct Renderable {
pub render_order: i32,
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct Player {}
#[derive(Component, Clone, ConvertSaveload)]
#[derive(Component, ConvertSaveload, Clone)]
pub struct Viewshed {
pub visible_tiles: Vec<rltk::Point>,
pub range: i32,
@ -30,15 +32,15 @@ pub struct Viewshed {
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct Monster {}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct Name {
pub name: String,
}
#[derive(Component, Debug, Serialize, Deserialize)]
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct BlocksTile {}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct CombatStats {
pub max_hp: i32,
pub hp: i32,
@ -46,12 +48,12 @@ pub struct CombatStats {
pub power: i32,
}
#[derive(Component, Debug, Clone, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct WantsToMelee {
pub target: Entity,
}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct SufferDamage {
pub amount: Vec<i32>,
}
@ -69,15 +71,15 @@ impl SufferDamage {
}
}
#[derive(Component, Debug, Serialize, Deserialize)]
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Item {}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct Potion {
pub heal_amount: i32,
}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct InBackpack {
pub owner: Entity,
}
@ -88,7 +90,7 @@ pub struct WantsToPickupItem {
pub item: Entity,
}
#[derive(Component, Debug, Clone, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct WantsToUseItem {
pub item: Entity,
pub target: Option<Point>,
@ -99,10 +101,10 @@ pub struct WantsToDropItem {
pub item: Entity,
}
#[derive(Component, Debug, Serialize, Deserialize)]
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Consumable {}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct ProvidesHealing {
pub heal_amount: i32,
}
@ -117,19 +119,19 @@ pub struct InflictsDamage {
pub damage: i32,
}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct AreaOfEffect {
pub radius: i32,
}
#[derive(Component, Debug, ConvertSaveload)]
#[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct Confusion {
pub turns: i32,
}
pub struct SerializeMe;
#[derive(Component, Clone, Serialize, Deserialize)]
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct SerializationHelper {
pub map: super::map::Map,
}

View File

@ -1,14 +1,14 @@
use rltk::Rltk;
use rltk::RGB;
use rltk::{Point, VirtualKeyCode};
use rltk::RGB;
use rltk::Rltk;
use specs::prelude::*;
use crate::{CombatStats, InBackpack, RunState, State, Viewshed};
use crate::gamelog::GameLog;
use crate::Map;
use crate::Name;
use crate::Player;
use crate::Position;
use crate::{CombatStats, InBackpack, RunState, State, Viewshed};
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
ctx.draw_box(
@ -403,6 +403,7 @@ pub enum MainMenuResult {
}
pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
let save_exists = super::save_load_system::does_save_exist();
let runstate = gs.ecs.fetch::<RunState>();
ctx.print_color_centered(
@ -412,6 +413,7 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
"Rust Roguelike Tutorial",
);
if let RunState::MainMenu {
menu_selection: selection,
} = *runstate
@ -432,22 +434,25 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
);
}
if selection == MainMenuSelection::LoadGame {
ctx.print_color_centered(
25,
RGB::named(rltk::MAGENTA),
RGB::named(rltk::BLACK),
"Load Game",
);
} else {
ctx.print_color_centered(
25,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
"Load Game",
);
if save_exists {
if selection == MainMenuSelection::LoadGame {
ctx.print_color_centered(
25,
RGB::named(rltk::MAGENTA),
RGB::named(rltk::BLACK),
"Load Game",
);
} else {
ctx.print_color_centered(
25,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
"Load Game",
);
}
}
if selection == MainMenuSelection::Quit {
ctx.print_color_centered(
26,

View File

@ -206,7 +206,11 @@ impl GameState for State {
}
gui::MainMenuResult::Selected { selected } => match selected {
gui::MainMenuSelection::NewGame => new_run_state = RunState::PreRun,
gui::MainMenuSelection::LoadGame => new_run_state = RunState::PreRun,
gui::MainMenuSelection::LoadGame => {
save_load_system::load_game(&mut self.ecs);
new_run_state = RunState::AwaitingInput;
save_load_system::delete_save();
}
gui::MainMenuSelection::Quit => ::std::process::exit(0),
},
}
@ -214,7 +218,7 @@ impl GameState for State {
RunState::SaveGame => {
save_load_system::save_game(&mut self.ecs);
new_run_state = RunState::MainMenu {
menu_selection: gui::MainMenuSelection::LoadGame,
menu_selection: gui::MainMenuSelection::Quit,
};
}
}
@ -238,9 +242,6 @@ fn main() -> rltk::BError {
let mut gs = State { ecs: World::new() };
gs.ecs.insert(rltk::RandomNumberGenerator::new());
gs.ecs.insert(gamelog::GameLog {
entries: vec!["Welcome to Rusty Roguelike".to_string()],
});
gs.ecs.register::<Position>();
gs.ecs.register::<Renderable>();
@ -265,22 +266,27 @@ fn main() -> rltk::BError {
gs.ecs.register::<Confusion>();
gs.ecs.register::<SimpleMarker<SerializeMe>>();
gs.ecs.register::<SerializationHelper>();
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
let map = Map::new_map_rooms_and_corridors();
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
let map = Map::new_map_rooms_and_corridors();
let (player_x, player_y) = map.rooms[0].center();
gs.ecs.insert(Point::new(player_x, player_y));
let player_entity = spawner::player(&mut gs.ecs, player_x, player_y);
gs.ecs.insert(player_entity);
for room in map.rooms.iter().skip(1) {
spawner::spawn_room(&mut gs.ecs, room);
}
gs.ecs.insert(map);
gs.ecs.insert(Point::new(player_x, player_y));
gs.ecs.insert(player_entity);
gs.ecs.insert(RunState::MainMenu {
menu_selection: gui::MainMenuSelection::NewGame,
});
gs.ecs.insert(gamelog::GameLog {
entries: vec!["Welcome to Rusty Roguelike".to_string()],
});
rltk::main_loop(context, gs)
}

View File

@ -65,6 +65,27 @@ impl Map {
}
}
fn is_exit_valid(&self, x: i32, y: i32) -> bool {
if x < 1 || x > self.width - 1 || y < 1 || y > self.height - 1 {
return false;
}
let idx = self.xy_idx(x, y);
!self.blocked[idx]
}
pub fn populate_blocked(&mut self) {
for (i, tile) in self.tiles.iter_mut().enumerate() {
self.blocked[i] = *tile == TileType::Wall;
}
}
pub fn clear_content_index(&mut self) {
for content in self.tile_content.iter_mut() {
content.clear();
}
}
pub fn new_map_rooms_and_corridors() -> Map {
let mut map = Map {
tiles: vec![TileType::Wall; MAP_COUNT],
@ -116,37 +137,11 @@ impl Map {
map
}
fn is_exit_valid(&self, x: i32, y: i32) -> bool {
if x < 1 || x > self.width - 1 || y < 1 || y > self.height - 1 {
return false;
}
let idx = self.xy_idx(x, y);
!self.blocked[idx]
}
pub fn populate_blocked(&mut self) {
for (i, tile) in self.tiles.iter_mut().enumerate() {
self.blocked[i] = *tile == TileType::Wall;
}
}
pub fn clear_content_index(&mut self) {
for content in self.tile_content.iter_mut() {
content.clear();
}
}
}
impl Algorithm2D for Map {
fn dimensions(&self) -> rltk::Point {
Point::new(self.width, self.height)
}
}
impl BaseMap for Map {
fn is_opaque(&self, idx: usize) -> bool {
self.tiles[idx as usize] == TileType::Wall
self.tiles[idx] == TileType::Wall
}
fn get_pathing_distance(&self, idx1: usize, idx2: usize) -> f32 {
@ -192,6 +187,12 @@ impl BaseMap for Map {
}
}
impl Algorithm2D for Map {
fn dimensions(&self) -> rltk::Point {
Point::new(self.width, self.height)
}
}
pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
let map = ecs.fetch::<Map>();
@ -203,12 +204,12 @@ pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
let mut fg;
match tile {
TileType::Floor => {
fg = RGB::from_f32(0.5, 0.5, 0.5);
fg = RGB::from_f32(0.0, 0.5, 0.5);
glyph = rltk::to_cp437('.');
}
TileType::Wall => {
fg = RGB::from_f32(0.0, 1.0, 0.0);
fg = RGB::from_f32(0., 1.0, 0.);
glyph = rltk::to_cp437('#');
}
}
@ -219,7 +220,7 @@ pub fn draw_map(ecs: &World, ctx: &mut Rltk) {
}
x += 1;
if x > 79 {
if x > MAP_WIDTH as i32 - 1 {
x = 0;
y += 1;
}

View File

@ -3,12 +3,12 @@ use std::cmp::{max, min};
use rltk::{Point, Rltk, VirtualKeyCode};
use specs::prelude::*;
use crate::gamelog::GameLog;
use crate::{
components::{CombatStats, Player, Position, Viewshed, WantsToMelee},
map::Map,
Item, RunState, State, WantsToPickupItem,
Item,
map::Map, RunState, State, WantsToPickupItem,
};
use crate::gamelog::GameLog;
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
let mut positions = ecs.write_storage::<Position>();
@ -20,8 +20,9 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
let map = ecs.fetch::<Map>();
for (entity, _player, pos, viewshed) in
(&entities, &mut players, &mut positions, &mut viewsheds).join()
(&entities, &mut players, &mut positions, &mut viewsheds).join()
{
if pos.x + delta_x < 1 || pos.x + delta_x > map.width - 1 || pos.y + delta_y < 1 || pos.y + delta_y > map.height - 1 { return; }
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
for potential_target in map.tile_content[destination_idx].iter() {

View File

@ -168,7 +168,7 @@ pub fn magic_missile_scroll(ecs: &mut World, x: i32, y: i32) {
.with(Item {})
.with(Consumable {})
.with(Ranged { range: 6 })
.with(InflictsDamage { damage: 8 })
.with(InflictsDamage { damage: 20 })
.marked::<SimpleMarker<SerializeMe>>()
.build();
}
@ -178,7 +178,7 @@ pub fn fireball_scroll(ecs: &mut World, x: i32, y: i32) {
.with(Position { x, y })
.with(Renderable {
glyph: rltk::to_cp437(')'),
fg: RGB::named(rltk::CYAN),
fg: RGB::named(rltk::ORANGE),
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
@ -199,7 +199,7 @@ pub fn confusion_scroll(ecs: &mut World, x: i32, y: i32) {
.with(Position { x, y })
.with(Renderable {
glyph: rltk::to_cp437(')'),
fg: RGB::named(rltk::CYAN),
fg: RGB::named(rltk::PINK),
bg: RGB::named(rltk::BLACK),
render_order: 2,
})

View File

@ -25,7 +25,6 @@ impl<'a> System<'a> for VisibilitySystem {
}
viewshed.dirty = false;
viewshed.visible_tiles.clear();
viewshed.visible_tiles = field_of_view(Point::new(pos.x, pos.y), viewshed.range, &*map);
viewshed
.visible_tiles