feat: Add shop logic and popup UI (#34). Update config tests and
defaults
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
"grid_width": 12,
|
||||
"grid_height": 4,
|
||||
"pom_speed": 1.5,
|
||||
"shovel_base_price": 10,
|
||||
"shovel_rate": 0.5,
|
||||
"berry_seeds": [
|
||||
{
|
||||
"name": "Normale Samen",
|
||||
|
||||
@@ -7,6 +7,8 @@ pub struct GameConfig {
|
||||
pub grid_width: u32,
|
||||
pub grid_height: u32,
|
||||
pub pom_speed: f32,
|
||||
pub shovel_base_price: u32,
|
||||
pub shovel_rate: f32,
|
||||
pub berry_seeds: Vec<BerrySeedConfig>,
|
||||
}
|
||||
|
||||
@@ -25,6 +27,8 @@ impl Default for GameConfig {
|
||||
grid_width: 12,
|
||||
grid_height: 4,
|
||||
pom_speed: 1.5,
|
||||
shovel_base_price: 10,
|
||||
shovel_rate: 0.2,
|
||||
berry_seeds: vec![
|
||||
BerrySeedConfig {
|
||||
name: "Normale Samen".to_string(),
|
||||
|
||||
@@ -4,12 +4,14 @@ use crate::{features::config::components::BerrySeedConfig, prelude::*};
|
||||
pub enum ItemType {
|
||||
Berry,
|
||||
BerrySeed { name: String },
|
||||
Shovel,
|
||||
}
|
||||
|
||||
impl ItemType {
|
||||
pub fn singular(&self, game_config: &GameConfig) -> String {
|
||||
match self {
|
||||
ItemType::Berry => "Beere".into(),
|
||||
ItemType::Shovel => "Schaufel".into(),
|
||||
ItemType::BerrySeed { name } => {
|
||||
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
|
||||
seed_config
|
||||
@@ -22,6 +24,7 @@ impl ItemType {
|
||||
pub fn plural(&self, game_config: &GameConfig) -> String {
|
||||
match self {
|
||||
ItemType::Berry => "Beeren".into(),
|
||||
ItemType::Shovel => "Schaufeln".into(),
|
||||
ItemType::BerrySeed { name } => {
|
||||
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
|
||||
seed_config
|
||||
@@ -36,6 +39,7 @@ impl ItemType {
|
||||
ItemType::Berry => {
|
||||
"Von Pflanzen erntbar. Kann im Shop zum Einkaufen benutzt werden.".into()
|
||||
}
|
||||
ItemType::Shovel => "Schaltet ein neues Feld im Garten frei.".into(),
|
||||
ItemType::BerrySeed { name } => {
|
||||
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
|
||||
if let Some(s) = seed_config {
|
||||
@@ -57,7 +61,7 @@ impl ItemType {
|
||||
|
||||
pub fn get_seed_config<'a>(&self, game_config: &'a GameConfig) -> Option<&'a BerrySeedConfig> {
|
||||
match self {
|
||||
ItemType::Berry => None,
|
||||
ItemType::Berry | ItemType::Shovel => None,
|
||||
ItemType::BerrySeed { name } => {
|
||||
game_config.berry_seeds.iter().find(|s| s.name == *name)
|
||||
}
|
||||
@@ -70,6 +74,10 @@ impl ItemType {
|
||||
name: "Berry".into(),
|
||||
aseprite: asset_server.load("berry.aseprite"),
|
||||
},
|
||||
ItemType::Shovel => AseSlice {
|
||||
name: "Berry".into(),
|
||||
aseprite: asset_server.load("berry.aseprite"),
|
||||
},
|
||||
ItemType::BerrySeed { name } => {
|
||||
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
|
||||
if let Some(s) = seed_config {
|
||||
|
||||
@@ -8,6 +8,7 @@ pub mod inventory;
|
||||
pub mod phase;
|
||||
pub mod pom;
|
||||
pub mod savegame;
|
||||
pub mod shop;
|
||||
pub mod start_screen;
|
||||
pub mod ui;
|
||||
|
||||
@@ -20,5 +21,6 @@ pub use inventory::InventoryPlugin;
|
||||
pub use phase::PhasePlugin;
|
||||
pub use pom::PomPlugin;
|
||||
pub use savegame::SavegamePlugin;
|
||||
pub use shop::ShopPlugin;
|
||||
pub use start_screen::StartScreenPlugin;
|
||||
pub use ui::UiPlugin;
|
||||
|
||||
51
src/features/shop/components.rs
Normal file
51
src/features/shop/components.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum RootMarker {
|
||||
Shop,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum ButtonType {
|
||||
ShopClose,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ShopOffer {
|
||||
pub item: ItemStack,
|
||||
pub cost: u32,
|
||||
}
|
||||
|
||||
impl ShopOffer {
|
||||
pub fn list_all(game_config: &GameConfig, tile_count: u32) -> Vec<ShopOffer> {
|
||||
let mut offers = Vec::new();
|
||||
|
||||
for seed in &game_config.berry_seeds {
|
||||
offers.push(ShopOffer {
|
||||
item: ItemStack {
|
||||
item_type: ItemType::BerrySeed {
|
||||
name: seed.name.clone(),
|
||||
},
|
||||
amount: 1,
|
||||
},
|
||||
cost: seed.cost,
|
||||
});
|
||||
}
|
||||
|
||||
let mut shovel_cost = game_config.shovel_base_price as f32;
|
||||
for _ in 0..=tile_count {
|
||||
shovel_cost = shovel_cost + (game_config.shovel_rate * shovel_cost);
|
||||
shovel_cost = shovel_cost.ceil();
|
||||
}
|
||||
|
||||
offers.push(ShopOffer {
|
||||
item: ItemStack {
|
||||
item_type: ItemType::Shovel,
|
||||
amount: 1,
|
||||
},
|
||||
cost: shovel_cost as u32,
|
||||
});
|
||||
|
||||
offers
|
||||
}
|
||||
}
|
||||
10
src/features/shop/mod.rs
Normal file
10
src/features/shop/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub mod components;
|
||||
pub mod ui;
|
||||
|
||||
pub struct ShopPlugin;
|
||||
|
||||
impl Plugin for ShopPlugin {
|
||||
fn build(&self, app: &mut App) {}
|
||||
}
|
||||
3
src/features/shop/ui/mod.rs
Normal file
3
src/features/shop/ui/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod shop;
|
||||
|
||||
pub use shop::open_shop;
|
||||
54
src/features/shop/ui/shop.rs
Normal file
54
src/features/shop/ui/shop.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use super::super::components::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn open_shop(commands: &mut Commands) {
|
||||
commands
|
||||
.spawn((
|
||||
RootMarker::Shop,
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
width: percent(100),
|
||||
height: percent(100),
|
||||
..Node::center()
|
||||
},
|
||||
ZIndex(1),
|
||||
BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)),
|
||||
GlobalTransform::default(),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn((
|
||||
Node {
|
||||
width: px(700),
|
||||
padding: UiRect::all(px(20.0)),
|
||||
..Node::vstack(px(20))
|
||||
},
|
||||
BackgroundColor(Color::srgb(0.2, 0.2, 0.2)),
|
||||
BorderRadius::all(px(10.0)),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Node {
|
||||
justify_content: JustifyContent::SpaceBetween,
|
||||
..Node::hstack(px(20))
|
||||
},
|
||||
children![
|
||||
text("Shop", 40.0, Color::WHITE),
|
||||
pill_button(
|
||||
ButtonType::ShopClose,
|
||||
ButtonVariant::Destructive,
|
||||
Node {
|
||||
width: px(40),
|
||||
height: px(40),
|
||||
..default()
|
||||
},
|
||||
"X",
|
||||
24.0
|
||||
),
|
||||
],
|
||||
));
|
||||
|
||||
parent.spawn(Node::vstack(px(10))).with_children(|_| {});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -33,6 +33,7 @@ fn main() {
|
||||
features::SavegamePlugin,
|
||||
features::UiPlugin,
|
||||
features::InventoryPlugin,
|
||||
features::ShopPlugin,
|
||||
))
|
||||
.insert_resource(config)
|
||||
.run();
|
||||
|
||||
@@ -22,7 +22,10 @@ fn test_load_valid_config() {
|
||||
r#"{
|
||||
"grid_width": 10,
|
||||
"grid_height": 5,
|
||||
"pom_speed": 2.0
|
||||
"pom_speed": 2.0,
|
||||
"shovel_base_price": 10,
|
||||
"shovel_rate": 0.2,
|
||||
"berry_seeds": []
|
||||
}"#,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user