feat: Display shop offers (#34)
This commit is contained in:
@@ -39,7 +39,7 @@ impl ItemType {
|
|||||||
ItemType::Berry => {
|
ItemType::Berry => {
|
||||||
"Von Pflanzen erntbar. Kann im Shop zum Einkaufen benutzt werden.".into()
|
"Von Pflanzen erntbar. Kann im Shop zum Einkaufen benutzt werden.".into()
|
||||||
}
|
}
|
||||||
ItemType::Shovel => "Schaltet ein neues Feld im Garten frei.".into(),
|
ItemType::Shovel => "Im Shop kaufbar. Schaltet ein neues Feld im Garten frei. Preis steigt bei jedem Kauf!".into(),
|
||||||
ItemType::BerrySeed { name } => {
|
ItemType::BerrySeed { name } => {
|
||||||
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
|
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
|
||||||
if let Some(s) = seed_config {
|
if let Some(s) = seed_config {
|
||||||
@@ -68,7 +68,11 @@ impl ItemType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sprite(&self, asset_server: Res<AssetServer>, game_config: &GameConfig) -> AseSlice {
|
pub fn get_sprite(
|
||||||
|
&self,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
game_config: &GameConfig,
|
||||||
|
) -> AseSlice {
|
||||||
match self {
|
match self {
|
||||||
ItemType::Berry => AseSlice {
|
ItemType::Berry => AseSlice {
|
||||||
name: "Berry".into(),
|
name: "Berry".into(),
|
||||||
|
|||||||
@@ -20,12 +20,13 @@ fn buttons(
|
|||||||
itemstack_query: Query<&ItemStack>,
|
itemstack_query: Query<&ItemStack>,
|
||||||
root_query: Query<(Entity, &RootMarker)>,
|
root_query: Query<(Entity, &RootMarker)>,
|
||||||
game_config: Res<GameConfig>,
|
game_config: Res<GameConfig>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
for (interaction, button_type) in &mut interaction_query {
|
for (interaction, button_type) in &mut interaction_query {
|
||||||
match *interaction {
|
match *interaction {
|
||||||
Interaction::Pressed => match button_type {
|
Interaction::Pressed => match button_type {
|
||||||
ButtonType::InventoryOpen => {
|
ButtonType::InventoryOpen => {
|
||||||
open_inventory(&mut commands, itemstack_query, &game_config);
|
open_inventory(&mut commands, itemstack_query, &game_config, &asset_server);
|
||||||
}
|
}
|
||||||
ButtonType::InventoryClose => {
|
ButtonType::InventoryClose => {
|
||||||
for (entity, root) in root_query.iter() {
|
for (entity, root) in root_query.iter() {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub fn open_inventory(
|
|||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
items: Query<&ItemStack>,
|
items: Query<&ItemStack>,
|
||||||
game_config: &Res<GameConfig>,
|
game_config: &Res<GameConfig>,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
@@ -61,7 +62,7 @@ pub fn open_inventory(
|
|||||||
})
|
})
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
for itemstack in items.iter() {
|
for itemstack in items.iter() {
|
||||||
parent.spawn(list_itemstack(itemstack, game_config));
|
parent.spawn(list_itemstack(itemstack, game_config, asset_server));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn list_itemstack(itemstack: &ItemStack, game_config: &GameConfig) -> impl Bundle {
|
pub fn list_itemstack(
|
||||||
|
itemstack: &ItemStack,
|
||||||
|
game_config: &GameConfig,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
) -> impl Bundle {
|
||||||
let name = match itemstack.amount {
|
let name = match itemstack.amount {
|
||||||
1 => itemstack.item_type.singular(game_config),
|
1 => itemstack.item_type.singular(game_config),
|
||||||
_ => itemstack.item_type.plural(game_config),
|
_ => itemstack.item_type.plural(game_config),
|
||||||
@@ -8,21 +12,22 @@ pub fn list_itemstack(itemstack: &ItemStack, game_config: &GameConfig) -> impl B
|
|||||||
|
|
||||||
(
|
(
|
||||||
Node {
|
Node {
|
||||||
|
width: percent(100),
|
||||||
padding: UiRect::all(px(4)),
|
padding: UiRect::all(px(4)),
|
||||||
..Node::hstack(px(8))
|
..Node::hstack(px(8))
|
||||||
},
|
},
|
||||||
BackgroundColor(ButtonVariant::Secondary.normal_background()),
|
|
||||||
BorderRadius::all(px(10)),
|
BorderRadius::all(px(10)),
|
||||||
children![
|
children![
|
||||||
(
|
(
|
||||||
// Placeholder for icon
|
|
||||||
Node {
|
Node {
|
||||||
height: percent(100),
|
height: percent(100),
|
||||||
aspect_ratio: Some(1.0),
|
aspect_ratio: Some(1.0),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
BackgroundColor(ButtonVariant::Secondary.hover_background()),
|
BackgroundColor(ButtonVariant::Secondary.hover_background()),
|
||||||
BorderRadius::all(px(10))
|
BorderRadius::all(px(10)),
|
||||||
|
itemstack.item_type.get_sprite(asset_server, game_config),
|
||||||
|
ImageNode::default()
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Node {
|
Node {
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ pub enum RootMarker {
|
|||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub enum ButtonType {
|
pub enum ButtonType {
|
||||||
|
ShopOpen,
|
||||||
ShopClose,
|
ShopClose,
|
||||||
|
ShopBuyItem(ShopOffer),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use components::*;
|
||||||
|
use ui::open_shop;
|
||||||
|
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
@@ -6,5 +8,34 @@ pub mod ui;
|
|||||||
pub struct ShopPlugin;
|
pub struct ShopPlugin;
|
||||||
|
|
||||||
impl Plugin for ShopPlugin {
|
impl Plugin for ShopPlugin {
|
||||||
fn build(&self, app: &mut App) {}
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(Update, buttons.run_if(in_state(AppState::GameScreen)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buttons(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
|
||||||
|
root_query: Query<(Entity, &RootMarker)>,
|
||||||
|
game_config: Res<GameConfig>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
) {
|
||||||
|
for (interaction, button_type) in &mut interaction_query {
|
||||||
|
match *interaction {
|
||||||
|
Interaction::Pressed => match button_type {
|
||||||
|
ButtonType::ShopOpen => {
|
||||||
|
open_shop(&mut commands, &game_config, &asset_server);
|
||||||
|
}
|
||||||
|
ButtonType::ShopClose => {
|
||||||
|
for (entity, root) in root_query.iter() {
|
||||||
|
match *root {
|
||||||
|
RootMarker::Shop => commands.entity(entity).despawn(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
pub mod offer;
|
||||||
pub mod shop;
|
pub mod shop;
|
||||||
|
|
||||||
|
pub use offer::shop_offer;
|
||||||
pub use shop::open_shop;
|
pub use shop::open_shop;
|
||||||
|
|||||||
47
src/features/shop/ui/offer.rs
Normal file
47
src/features/shop/ui/offer.rs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
use super::super::components::*;
|
||||||
|
use crate::{features::inventory::ui::item::list_itemstack, prelude::*};
|
||||||
|
|
||||||
|
pub fn shop_offer(
|
||||||
|
offer: &ShopOffer,
|
||||||
|
game_config: &GameConfig,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
) -> impl Bundle {
|
||||||
|
button(
|
||||||
|
ButtonType::ShopBuyItem(offer.clone()),
|
||||||
|
ButtonVariant::Secondary,
|
||||||
|
Node::default(),
|
||||||
|
|_| {
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
width: percent(100),
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
..Node::hstack(px(10))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
list_itemstack(&offer.item, game_config, asset_server),
|
||||||
|
shop_price(offer.cost, asset_server, game_config)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shop_price(
|
||||||
|
price: u32,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
game_config: &GameConfig,
|
||||||
|
) -> impl Bundle {
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
..Node::hstack(px(0))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
text(price.to_string(), 12.0, Color::WHITE),
|
||||||
|
(
|
||||||
|
ImageNode::default(),
|
||||||
|
ItemType::Berry.get_sprite(asset_server, game_config)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
use super::super::components::*;
|
use super::super::components::*;
|
||||||
use crate::prelude::*;
|
use crate::{features::shop::ui::shop_offer, prelude::*};
|
||||||
|
|
||||||
|
pub fn open_shop(
|
||||||
|
commands: &mut Commands,
|
||||||
|
game_config: &GameConfig,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
) {
|
||||||
|
// TODO: calculate tile_count
|
||||||
|
let offers = ShopOffer::list_all(game_config, 0);
|
||||||
|
|
||||||
pub fn open_shop(commands: &mut Commands) {
|
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
RootMarker::Shop,
|
RootMarker::Shop,
|
||||||
@@ -47,7 +54,11 @@ pub fn open_shop(commands: &mut Commands) {
|
|||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
|
||||||
parent.spawn(Node::vstack(px(10))).with_children(|_| {});
|
parent.spawn(Node::vstack(px(10))).with_children(|parent| {
|
||||||
|
for offer in offers {
|
||||||
|
parent.spawn(shop_offer(&offer, game_config, asset_server));
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user