diff --git a/assets/config.json b/assets/config.json index 0eb9d0b..56bc933 100644 --- a/assets/config.json +++ b/assets/config.json @@ -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", diff --git a/src/features/config/components.rs b/src/features/config/components.rs index 5319dbe..6533682 100644 --- a/src/features/config/components.rs +++ b/src/features/config/components.rs @@ -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, } @@ -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(), diff --git a/src/features/inventory/components.rs b/src/features/inventory/components.rs index 0008095..63ca0d9 100644 --- a/src/features/inventory/components.rs +++ b/src/features/inventory/components.rs @@ -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 { diff --git a/src/features/mod.rs b/src/features/mod.rs index 76983e4..5ef139a 100644 --- a/src/features/mod.rs +++ b/src/features/mod.rs @@ -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; diff --git a/src/features/shop/components.rs b/src/features/shop/components.rs new file mode 100644 index 0000000..0b5d762 --- /dev/null +++ b/src/features/shop/components.rs @@ -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 { + 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 + } +} diff --git a/src/features/shop/mod.rs b/src/features/shop/mod.rs new file mode 100644 index 0000000..9f2a0f8 --- /dev/null +++ b/src/features/shop/mod.rs @@ -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) {} +} diff --git a/src/features/shop/ui/mod.rs b/src/features/shop/ui/mod.rs new file mode 100644 index 0000000..1ba9936 --- /dev/null +++ b/src/features/shop/ui/mod.rs @@ -0,0 +1,3 @@ +pub mod shop; + +pub use shop::open_shop; diff --git a/src/features/shop/ui/shop.rs b/src/features/shop/ui/shop.rs new file mode 100644 index 0000000..5dbafea --- /dev/null +++ b/src/features/shop/ui/shop.rs @@ -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(|_| {}); + }); + }); +} diff --git a/src/main.rs b/src/main.rs index 3fb1b5e..d9b2558 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,7 @@ fn main() { features::SavegamePlugin, features::UiPlugin, features::InventoryPlugin, + features::ShopPlugin, )) .insert_resource(config) .run(); diff --git a/tests/config.rs b/tests/config.rs index 3401dbe..90b2dc6 100644 --- a/tests/config.rs +++ b/tests/config.rs @@ -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": [] }"#, );