SaveLoad
This commit is contained in:
parent
70c46ab9d2
commit
5254209c35
33
Cargo.lock
generated
33
Cargo.lock
generated
@ -92,6 +92,7 @@ source = "git+https://github.com/amethyst/bracket-lib#851f6f08675444fb6fa088b9e6
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot 0.12.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -108,6 +109,7 @@ name = "bracket-geometry"
|
||||
version = "0.8.7"
|
||||
source = "git+https://github.com/amethyst/bracket-lib#851f6f08675444fb6fa088b9e67bee9fd75554c6"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"ultraviolet",
|
||||
]
|
||||
|
||||
@ -155,6 +157,7 @@ dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"regex",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@ -800,6 +803,8 @@ name = "hellorust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rltk",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"specs",
|
||||
"specs-derive",
|
||||
]
|
||||
@ -856,6 +861,12 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.0"
|
||||
@ -1353,6 +1364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1431,6 +1443,12 @@ dependencies = [
|
||||
"bracket-lib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.5.2"
|
||||
@ -1484,6 +1502,9 @@ name = "serde"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
@ -1496,6 +1517,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo-fontconfig"
|
||||
version = "0.5.1"
|
||||
@ -1620,6 +1652,7 @@ dependencies = [
|
||||
"hibitset",
|
||||
"log",
|
||||
"rayon",
|
||||
"serde",
|
||||
"shred",
|
||||
"shrev",
|
||||
"tuple_utils",
|
||||
|
||||
@ -6,7 +6,9 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rltk = { git = "https://github.com/amethyst/bracket-lib" }
|
||||
rltk = { git = "https://github.com/amethyst/bracket-lib", features= ["serde"] }
|
||||
# rltk = { version = "0.8.7" }
|
||||
specs = "0.18.0"
|
||||
specs = { version = "0.18.0", features= ["serde"]}
|
||||
specs-derive = "0.4.1"
|
||||
serde= { version = "1.0.93", features = ["derive"]}
|
||||
serde_json = "1.0.39"
|
||||
@ -2,6 +2,7 @@ use rltk::RGB;
|
||||
use specs::prelude::*;
|
||||
use specs_derive::*;
|
||||
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Position {
|
||||
pub x: i32,
|
||||
@ -34,17 +35,7 @@ pub struct Name {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum RunState {
|
||||
AwaitingInput,
|
||||
PreRun,
|
||||
PlayerTurn,
|
||||
MonsterTurn,
|
||||
ShowInventory,
|
||||
ShowDropItem,
|
||||
ShowSpawnMenu,
|
||||
ShowTargeting { range : i32, item : Entity},
|
||||
}
|
||||
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct BlocksTile {}
|
||||
@ -131,3 +122,5 @@ pub struct AreaOfEffect {
|
||||
pub struct Confusion {
|
||||
pub turns : i32
|
||||
}
|
||||
|
||||
pub struct SerializeMe;
|
||||
|
||||
70
src/gui.rs
70
src/gui.rs
@ -1,7 +1,13 @@
|
||||
use rltk::{RGB, Rltk, Point, VirtualKeyCode};
|
||||
use specs::prelude::*;
|
||||
|
||||
use super::{CombatStats, Player, GameLog, Map, Name, Position, State, InBackpack, Viewshed, spawner};
|
||||
use super::{CombatStats, Player, GameLog, Map, Name, Position, State, InBackpack, Viewshed, spawner, RunState};
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum MainMenuSelection { NewGame, LoadGame, Quit }
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum MainMenuResult { NoSelection{ selected: MainMenuSelection}, Selected{ selected: MainMenuSelection } }
|
||||
|
||||
fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
||||
let map = ecs.fetch::<Map>();
|
||||
@ -160,7 +166,7 @@ pub fn spawn_item(gs: &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Option<En
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => {
|
||||
match (key) {
|
||||
match key {
|
||||
VirtualKeyCode::Escape => { (ItemMenuResult::Cancel, None)},
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
@ -208,7 +214,7 @@ pub fn drop_item_menu(gs: &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Optio
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => {
|
||||
match (key) {
|
||||
match key {
|
||||
VirtualKeyCode::Escape => { (ItemMenuResult::Cancel, None)},
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
@ -264,3 +270,61 @@ pub fn ranged_target(gs: &mut State, ctx : &mut Rltk, range: i32) -> (ItemMenuRe
|
||||
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
|
||||
|
||||
pub fn main_menu(gs: &mut State, ctx : &mut Rltk) -> MainMenuResult {
|
||||
let runstate = gs.ecs.fetch::<RunState>();
|
||||
|
||||
ctx.print_color_centered(15, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Rust Roguelike Tutorial");
|
||||
|
||||
if let RunState::MainMenu{ menu_selection : selection } = *runstate {
|
||||
if selection == MainMenuSelection::NewGame {
|
||||
ctx.print_color_centered(24, RGB::named(rltk::MAGENTA), RGB::named(rltk::BLACK), "Start a new game");
|
||||
} else {
|
||||
ctx.print_color_centered(24, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Start a new game");
|
||||
}
|
||||
|
||||
if selection == MainMenuSelection::LoadGame {
|
||||
ctx.print_color_centered(25, RGB::named(rltk::MAGENTA), RGB::named(rltk::BLACK), "Load a save");
|
||||
} else {
|
||||
ctx.print_color_centered(25, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Load a save");
|
||||
}
|
||||
|
||||
if selection == MainMenuSelection::Quit {
|
||||
ctx.print_color_centered(26, RGB::named(rltk::MAGENTA), RGB::named(rltk::BLACK), "Quit the game");
|
||||
} else {
|
||||
ctx.print_color_centered(26, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Quit the game");
|
||||
}
|
||||
|
||||
match ctx.key {
|
||||
None => return MainMenuResult::NoSelection { selected: selection },
|
||||
Some(key) => {
|
||||
match key {
|
||||
VirtualKeyCode::Escape => {return MainMenuResult::NoSelection { selected: MainMenuSelection::Quit }},
|
||||
VirtualKeyCode::Up => {
|
||||
let newselection;
|
||||
match selection {
|
||||
MainMenuSelection::NewGame => newselection = MainMenuSelection::Quit,
|
||||
MainMenuSelection::LoadGame => newselection = MainMenuSelection::NewGame,
|
||||
MainMenuSelection::Quit => newselection = MainMenuSelection::LoadGame
|
||||
}
|
||||
return MainMenuResult::NoSelection { selected: newselection }
|
||||
}
|
||||
VirtualKeyCode::Down => {
|
||||
let newselection;
|
||||
match selection {
|
||||
MainMenuSelection::NewGame => newselection = MainMenuSelection::LoadGame,
|
||||
MainMenuSelection::LoadGame => newselection = MainMenuSelection::Quit,
|
||||
MainMenuSelection::Quit => newselection = MainMenuSelection::NewGame
|
||||
}
|
||||
return MainMenuResult::NoSelection { selected: newselection }
|
||||
}
|
||||
VirtualKeyCode::Return => {return MainMenuResult::Selected { selected: selection }}
|
||||
_ => return MainMenuResult::NoSelection { selected: selection }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame }
|
||||
|
||||
}
|
||||
@ -1,7 +1,5 @@
|
||||
use specs::prelude::*;
|
||||
|
||||
use crate::player;
|
||||
|
||||
use super::{
|
||||
gamelog::GameLog, CombatStats, Consumable, InBackpack, Name, Position, ProvidesHealing,
|
||||
WantsToDropItem, WantsToPickupItem, WantsToUseItem, InflictsDamage, Map, SufferDamage, AreaOfEffect, Confusion
|
||||
|
||||
105
src/main.rs
105
src/main.rs
@ -1,5 +1,8 @@
|
||||
use rltk::{GameState, Point, Rltk, RGB};
|
||||
use rltk::{GameState, Point, Rltk};
|
||||
use specs::prelude::*;
|
||||
use specs::saveload::{SimpleMarker, SimpleMarkerAllocator};
|
||||
|
||||
extern crate serde;
|
||||
|
||||
mod components;
|
||||
pub use components::*;
|
||||
@ -35,11 +38,25 @@ mod gamelog;
|
||||
pub use gamelog::*;
|
||||
|
||||
mod spawner;
|
||||
use spawner::*;
|
||||
|
||||
|
||||
mod inventory_system;
|
||||
use inventory_system::*;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum RunState {
|
||||
AwaitingInput,
|
||||
PreRun,
|
||||
PlayerTurn,
|
||||
MonsterTurn,
|
||||
ShowInventory,
|
||||
ShowDropItem,
|
||||
ShowSpawnMenu,
|
||||
ShowTargeting { range : i32, item : Entity},
|
||||
MainMenu { menu_selection : gui::MainMenuSelection },
|
||||
SaveGame,
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
pub ecs: World,
|
||||
}
|
||||
@ -68,7 +85,16 @@ impl State {
|
||||
|
||||
impl GameState for State {
|
||||
fn tick(&mut self, ctx: &mut Rltk) {
|
||||
let mut newrunstate;
|
||||
{
|
||||
let runstate = self.ecs.fetch::<RunState>();
|
||||
newrunstate = *runstate;
|
||||
}
|
||||
|
||||
ctx.cls();
|
||||
match newrunstate {
|
||||
RunState::MainMenu { .. } => {}
|
||||
_ => {
|
||||
draw_map(&self.ecs, ctx);
|
||||
|
||||
{
|
||||
@ -85,20 +111,9 @@ impl GameState for State {
|
||||
ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
|
||||
}
|
||||
}
|
||||
// for (pos, render) in (&positions, &renderables).join() {
|
||||
// let idx = map.xy_idx(pos.x, pos.y);
|
||||
// if map.visible_tiles[idx] {
|
||||
// ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
|
||||
// }
|
||||
// }
|
||||
|
||||
gui::draw_ui(&self.ecs, ctx);
|
||||
}
|
||||
|
||||
let mut newrunstate;
|
||||
{
|
||||
let runstate = self.ecs.fetch::<RunState>();
|
||||
newrunstate = *runstate;
|
||||
}
|
||||
}
|
||||
|
||||
match newrunstate {
|
||||
@ -130,7 +145,10 @@ impl GameState for State {
|
||||
let is_ranged = self.ecs.read_storage::<Ranged>();
|
||||
let is_item_ranged = is_ranged.get(item_entity);
|
||||
if let Some(is_item_ranged) = is_item_ranged {
|
||||
newrunstate = RunState::ShowTargeting { range: is_item_ranged.range, item: item_entity };
|
||||
newrunstate = RunState::ShowTargeting {
|
||||
range: is_item_ranged.range,
|
||||
item: item_entity,
|
||||
};
|
||||
} else {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
intent
|
||||
@ -144,25 +162,6 @@ impl GameState for State {
|
||||
.expect("Failed to insert intent");
|
||||
newrunstate = RunState::PlayerTurn;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::ShowDropItem => {
|
||||
let result = gui::drop_item_menu(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
let mut intent = self.ecs.write_storage::<WantsToDropItem>();
|
||||
intent
|
||||
.insert(
|
||||
*self.ecs.fetch::<Entity>(),
|
||||
WantsToDropItem { item: item_entity },
|
||||
)
|
||||
.expect("Unable to insert intent");
|
||||
newrunstate = RunState::PlayerTurn;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,20 +190,46 @@ impl GameState for State {
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
intent.insert(*self.ecs.fetch::<Entity>(), WantsToUseItem { item, target: result.1 }).expect("Unable to insert intent");
|
||||
intent
|
||||
.insert(
|
||||
*self.ecs.fetch::<Entity>(),
|
||||
WantsToUseItem {
|
||||
item,
|
||||
target: result.1,
|
||||
},
|
||||
)
|
||||
.expect("Unable to insert intent");
|
||||
newrunstate = RunState::PlayerTurn;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
RunState::ShowSpawnMenu => {
|
||||
let result = gui::spawn_item(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {newrunstate = RunState::AwaitingInput;}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
newrunstate = RunState::AwaitingInput;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
RunState::MainMenu { .. } => {
|
||||
let result = gui::main_menu(self, ctx);
|
||||
match result {
|
||||
gui::MainMenuResult::NoSelection { selected } => newrunstate = RunState::MainMenu{menu_selection: selected},
|
||||
gui::MainMenuResult::Selected { selected } => {
|
||||
match selected {
|
||||
gui::MainMenuSelection::NewGame => newrunstate = RunState::PreRun,
|
||||
gui::MainMenuSelection::LoadGame => newrunstate = RunState::PreRun,
|
||||
gui::MainMenuSelection::Quit => { ::std::process::exit(0)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::SaveGame => {
|
||||
let data = serde_json::to_string(&*self.ecs.fetch::<Map>()).unwrap();
|
||||
println!("{}", data);
|
||||
newrunstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::LoadGame };
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,6 +270,7 @@ fn main() -> rltk::BError {
|
||||
gs.ecs.register::<InflictsDamage>();
|
||||
gs.ecs.register::<AreaOfEffect>();
|
||||
gs.ecs.register::<Confusion>();
|
||||
gs.ecs.register::<SimpleMarker<SerializeMe>>();
|
||||
|
||||
let map = Map::new_map_rooms_and_corridors();
|
||||
let (player_x, player_y) = map.rooms[0].center();
|
||||
@ -260,10 +286,11 @@ fn main() -> rltk::BError {
|
||||
|
||||
gs.ecs.insert(map);
|
||||
gs.ecs.insert(player_entity);
|
||||
gs.ecs.insert(RunState::PreRun);
|
||||
gs.ecs.insert(RunState::MainMenu { menu_selection: MainMenuSelection::NewGame });
|
||||
gs.ecs.insert(gamelog::GameLog {
|
||||
entries: vec!["Welcome to my rougelike".to_string()],
|
||||
});
|
||||
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
||||
|
||||
// Main loop runner
|
||||
rltk::main_loop(context, gs)
|
||||
|
||||
@ -2,18 +2,19 @@ use super::Rect;
|
||||
use rltk::{Algorithm2D, BaseMap, Point, RandomNumberGenerator, Rltk, RGB};
|
||||
use specs::prelude::*;
|
||||
use std::cmp::{max, min};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
pub const MAPWIDTH : usize = 80;
|
||||
pub const MAPHIEGHT : usize = 43;
|
||||
pub const MAPCOUNT : usize = MAPHIEGHT * MAPWIDTH;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||
pub enum TileType {
|
||||
Wall,
|
||||
Floor,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
pub struct Map {
|
||||
pub tiles: Vec<TileType>,
|
||||
pub rooms: Vec<Rect>,
|
||||
@ -22,6 +23,9 @@ pub struct Map {
|
||||
pub revealed_tiles: Vec<bool>,
|
||||
pub visible_tiles: Vec<bool>,
|
||||
pub blocked : Vec<bool>,
|
||||
|
||||
#[serde(skip_serializing)]
|
||||
#[serde(skip_deserializing)]
|
||||
pub tile_content : Vec<Vec<Entity>>
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use specs::prelude::*;
|
||||
use super::{CombatStats, WantsToMelee, Name, SufferDamage, GameLog};
|
||||
use rltk::console;
|
||||
|
||||
|
||||
pub struct MeleeCombatSystem {}
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use crate::spawn_item;
|
||||
|
||||
use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats, WantsToMelee, Item, GameLog, WantsToPickupItem, spawner};
|
||||
use rltk::{Point, Rltk, VirtualKeyCode};
|
||||
use specs::prelude::*;
|
||||
@ -7,7 +5,7 @@ use std::cmp::{max, min};
|
||||
|
||||
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
||||
let mut positions = ecs.write_storage::<Position>();
|
||||
let mut players = ecs.write_storage::<Player>();
|
||||
let players = ecs.write_storage::<Player>();
|
||||
let mut viewsheds = ecs.write_storage::<Viewshed>();
|
||||
let mut ppos = ecs.write_resource::<Point>();
|
||||
let combat_stats = ecs.read_storage::<CombatStats>();
|
||||
@ -95,6 +93,7 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
||||
spawner::health_potion(&mut gs.ecs, mouse_pos.0, mouse_pos.1);
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
VirtualKeyCode::Escape => return RunState::SaveGame,
|
||||
_ => return RunState::AwaitingInput,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||
pub struct Rect {
|
||||
pub x1: i32,
|
||||
pub x2: i32,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user