feat: Add savegame loading (#37)
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
use crate::{features::savegame::messages::SavegameLoadMessage, prelude::*};
|
||||
use components::*;
|
||||
use consts::*;
|
||||
|
||||
pub mod components;
|
||||
pub mod consts;
|
||||
|
||||
pub struct StartScreenPlugin;
|
||||
|
||||
@@ -10,107 +15,198 @@ impl Plugin for StartScreenPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct MenuData {
|
||||
button_entity: Entity,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
enum ButtonType {
|
||||
LoadGame,
|
||||
NewGame,
|
||||
Settings,
|
||||
}
|
||||
|
||||
const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
|
||||
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
|
||||
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
|
||||
|
||||
fn setup(mut commands: Commands) {
|
||||
let button_entity = commands
|
||||
commands.spawn((
|
||||
RootMarker::MainMenu,
|
||||
Node {
|
||||
width: percent(100),
|
||||
height: percent(100),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
flex_direction: FlexDirection::Column,
|
||||
..default()
|
||||
},
|
||||
children![
|
||||
(
|
||||
Text::new("Pomonon Garten"),
|
||||
TextFont::from_font_size(64.0),
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::LoadGame,
|
||||
Node {
|
||||
width: px(300),
|
||||
height: px(65),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Text::new("Spiel laden"),
|
||||
TextFont::from_font_size(33.0),
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)]
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::NewGame,
|
||||
Node {
|
||||
width: px(300),
|
||||
height: px(65),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Text::new("Neues Spiel"),
|
||||
TextFont::from_font_size(33.0),
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)]
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::Settings,
|
||||
Node {
|
||||
width: px(300),
|
||||
height: px(65),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Text::new("Einstellungen"),
|
||||
TextFont::from_font_size(33.0),
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)]
|
||||
)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
fn spawn_load_popup(commands: &mut Commands) {
|
||||
commands
|
||||
.spawn((
|
||||
RootMarker::PopupSavegameLoad,
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
width: percent(100),
|
||||
height: percent(100),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
flex_direction: FlexDirection::Column,
|
||||
..default()
|
||||
},
|
||||
children![
|
||||
(
|
||||
Text::new("Pomonon Garten"),
|
||||
TextFont {
|
||||
font_size: 64.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::LoadGame,
|
||||
Node {
|
||||
width: px(300),
|
||||
height: px(65),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Text::new("Spiel laden"),
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)]
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::NewGame,
|
||||
Node {
|
||||
width: px(300),
|
||||
height: px(65),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Text::new("Neues Spiel"),
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)]
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::Settings,
|
||||
Node {
|
||||
width: px(300),
|
||||
height: px(65),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Text::new("Einstellungen"),
|
||||
TextFont {
|
||||
font_size: 33.0,
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)]
|
||||
)
|
||||
],
|
||||
ZIndex(1),
|
||||
BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)),
|
||||
))
|
||||
.id();
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn((
|
||||
Node {
|
||||
width: px(600.0),
|
||||
height: px(500.0),
|
||||
flex_direction: FlexDirection::Column,
|
||||
align_items: AlignItems::Center,
|
||||
padding: UiRect::all(px(20.0)),
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(Color::srgb(0.2, 0.2, 0.2)),
|
||||
BorderRadius::all(Val::Px(10.0)),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Node {
|
||||
width: percent(100.0),
|
||||
justify_content: JustifyContent::SpaceBetween,
|
||||
align_items: AlignItems::Center,
|
||||
margin: UiRect::bottom(px(20.0)),
|
||||
..default()
|
||||
},
|
||||
children![
|
||||
(
|
||||
Text::new("Spielstand Auswahl"),
|
||||
TextFont::from_font_size(40.0),
|
||||
TextColor(Color::WHITE),
|
||||
),
|
||||
(
|
||||
Button,
|
||||
ButtonType::PopupClose,
|
||||
Node {
|
||||
width: px(40.0),
|
||||
height: px(40.0),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(Color::srgb(0.8, 0.2, 0.2)),
|
||||
children![(
|
||||
Text::new("X"),
|
||||
TextFont::from_font_size(24.0),
|
||||
TextColor(Color::WHITE),
|
||||
)]
|
||||
)
|
||||
],
|
||||
));
|
||||
|
||||
commands.insert_resource(MenuData { button_entity });
|
||||
parent
|
||||
.spawn(Node {
|
||||
width: percent(100),
|
||||
flex_direction: FlexDirection::Column,
|
||||
overflow: Overflow::scroll_y(),
|
||||
margin: UiRect::all(px(20.0)),
|
||||
row_gap: px(10.0),
|
||||
..default()
|
||||
})
|
||||
.with_children(|parent| {
|
||||
for savegame in SavegamePath::list() {
|
||||
parent.spawn((
|
||||
Button,
|
||||
ButtonType::PopupSavegameLoad {
|
||||
savegame_path: savegame.path.clone(),
|
||||
},
|
||||
Node {
|
||||
width: percent(100),
|
||||
height: px(80),
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(NORMAL_BUTTON),
|
||||
children![(
|
||||
Node {
|
||||
width: percent(100),
|
||||
height: percent(100),
|
||||
flex_direction: FlexDirection::Column,
|
||||
..default()
|
||||
},
|
||||
children![
|
||||
(
|
||||
Text::new(format!(
|
||||
"Spielstand {}",
|
||||
savegame.index + 1
|
||||
)),
|
||||
TextFont::from_font_size(24.0),
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
),
|
||||
(
|
||||
Text::new(format!(
|
||||
"Beeren: {}, Fokusphasen abgeschlossen: {}",
|
||||
savegame.total_berries,
|
||||
savegame.completed_focus
|
||||
)),
|
||||
TextFont::from_font_size(18.0),
|
||||
TextColor(Color::srgb(0.9, 0.9, 0.9))
|
||||
)
|
||||
]
|
||||
)],
|
||||
));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn menu(
|
||||
@@ -120,7 +216,8 @@ fn menu(
|
||||
(&Interaction, &ButtonType, &mut BackgroundColor),
|
||||
(Changed<Interaction>, With<Button>),
|
||||
>,
|
||||
mut load_messages: MessageWriter<SavegameLoadMessage>,
|
||||
root_query: Query<(Entity, &RootMarker)>,
|
||||
mut savegame_messages: MessageWriter<SavegameLoadMessage>,
|
||||
) {
|
||||
for (interaction, button_type, mut color) in &mut interaction_query {
|
||||
match *interaction {
|
||||
@@ -129,14 +226,25 @@ fn menu(
|
||||
|
||||
match button_type {
|
||||
ButtonType::LoadGame => {
|
||||
commands.insert_resource(SavegamePath::new("savegame.json"));
|
||||
next_state.set(AppState::GameScreen);
|
||||
load_messages.write(SavegameLoadMessage);
|
||||
spawn_load_popup(&mut commands);
|
||||
}
|
||||
ButtonType::NewGame => {
|
||||
commands.insert_resource(SavegamePath::new("savegame.json"));
|
||||
commands.insert_resource(SavegamePath::next());
|
||||
next_state.set(AppState::GameScreen);
|
||||
}
|
||||
ButtonType::PopupClose => {
|
||||
for (entity, root) in root_query.iter() {
|
||||
match *root {
|
||||
RootMarker::PopupSavegameLoad => commands.entity(entity).despawn(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
ButtonType::PopupSavegameLoad { savegame_path } => {
|
||||
commands.insert_resource(savegame_path.clone());
|
||||
next_state.set(AppState::GameScreen);
|
||||
savegame_messages.write(SavegameLoadMessage);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
@@ -150,6 +258,8 @@ fn menu(
|
||||
}
|
||||
}
|
||||
|
||||
fn cleanup(mut commands: Commands, menu_data: Res<MenuData>) {
|
||||
commands.entity(menu_data.button_entity).despawn();
|
||||
fn cleanup(mut commands: Commands, query: Query<Entity, With<RootMarker>>) {
|
||||
for entity in query.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user