Merge branch '51-berry-seed-type-generation' into 'dev'

Berry Seed Type Generation

See merge request softwaregrundprojekt/2025-2026/einzelprojekt/tutorium-moritz/bernroider-dominik/bernroider-dominik!19
This commit is contained in:
Dominik Bernroider
2025-11-30 16:16:44 +00:00
8 changed files with 143 additions and 20 deletions

BIN
assets/berry.aseprite Normal file

Binary file not shown.

View File

@@ -1,5 +1,28 @@
{
"grid_width": 12,
"grid_height": 4,
"pom_speed": 1.5
}
"pom_speed": 1.5,
"berry_seeds": [
{
"name": "Normale Samen",
"cost": 1,
"grants": 2,
"slice": "Seed1",
"growth_stages": 2
},
{
"name": "Super-Samen",
"cost": 3,
"grants": 9,
"slice": "Seed2",
"growth_stages": 4
},
{
"name": "Zauber-Samen",
"cost": 5,
"grants": 20,
"slice": "Seed3",
"growth_stages": 6
}
]
}

BIN
assets/seed.aseprite Normal file

Binary file not shown.

View File

@@ -7,6 +7,16 @@ pub struct GameConfig {
pub grid_width: u32,
pub grid_height: u32,
pub pom_speed: f32,
pub berry_seeds: Vec<BerrySeedConfig>,
}
#[derive(Deserialize, Debug, Clone)]
pub struct BerrySeedConfig {
pub name: String,
pub cost: u32,
pub grants: u32,
pub slice: String,
pub growth_stages: u32,
}
impl Default for GameConfig {
@@ -15,6 +25,29 @@ impl Default for GameConfig {
grid_width: 12,
grid_height: 4,
pom_speed: 1.5,
berry_seeds: vec![
BerrySeedConfig {
name: "Normale Samen".to_string(),
cost: 1,
grants: 2,
slice: "Seed1".to_string(),
growth_stages: 2,
},
BerrySeedConfig {
name: "Super-Samen".to_string(),
cost: 3,
grants: 9,
slice: "Seed2".to_string(),
growth_stages: 4,
},
BerrySeedConfig {
name: "Zauber-Samen".to_string(),
cost: 5,
grants: 20,
slice: "Seed3".to_string(),
growth_stages: 6,
},
],
}
}
}

View File

@@ -1,30 +1,91 @@
use crate::prelude::*;
use crate::{features::config::components::BerrySeedConfig, prelude::*};
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ItemType {
Berry,
BerrySeed { name: String },
}
impl ItemType {
pub fn singular(&self) -> String {
pub fn singular(&self, game_config: &GameConfig) -> String {
match self {
ItemType::Berry => "Beere",
ItemType::Berry => "Beere".into(),
ItemType::BerrySeed { name } => {
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
seed_config
.map(|s| s.name.clone())
.unwrap_or_else(|| format!("Unbekannter Samen ({})", name))
}
}
.into()
}
pub fn plural(&self) -> String {
pub fn plural(&self, game_config: &GameConfig) -> String {
match self {
ItemType::Berry => "Beeren",
ItemType::Berry => "Beeren".into(),
ItemType::BerrySeed { name } => {
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
seed_config
.map(|s| s.name.clone())
.unwrap_or_else(|| format!("Unbekannte Samen ({})", name))
}
}
.into()
}
pub fn description(&self) -> String {
pub fn description(&self, game_config: &GameConfig) -> String {
match self {
ItemType::Berry => "Von Pflanzen erntbar. Kann im Shop zum Einkaufen benutzt werden.",
ItemType::Berry => {
"Von Pflanzen erntbar. Kann im Shop zum Einkaufen benutzt werden.".into()
}
ItemType::BerrySeed { name } => {
let seed_config = game_config.berry_seeds.iter().find(|s| s.name == *name);
if let Some(s) = seed_config {
format!(
"Im Shop kaufbar. Kann eingepflanzt werden. Benötigt {} Fokus-Phasen zum Wachsen. Erhalte beim Ernten {} {}.",
s.growth_stages,
s.grants,
match s.grants {
1 => ItemType::Berry.singular(game_config),
_ => ItemType::Berry.plural(game_config),
}
)
} else {
format!("Unbekannter Samen ({})", name)
}
}
}
}
pub fn get_seed_config<'a>(&self, game_config: &'a GameConfig) -> Option<&'a BerrySeedConfig> {
match self {
ItemType::Berry => None,
ItemType::BerrySeed { name } => {
game_config.berry_seeds.iter().find(|s| s.name == *name)
}
}
}
pub fn get_sprite(&self, asset_server: Res<AssetServer>, game_config: &GameConfig) -> AseSlice {
match self {
ItemType::Berry => 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 {
AseSlice {
name: s.slice.clone(),
aseprite: asset_server.load("seed.aseprite"),
}
} else {
// Fallback for unknown seed
AseSlice {
name: "Seed1".into(),
aseprite: asset_server.load("seed.aseprite"),
}
}
}
}
.into()
}
}

View File

@@ -19,12 +19,13 @@ fn buttons(
mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
itemstack_query: Query<&ItemStack>,
root_query: Query<(Entity, &RootMarker)>,
game_config: Res<GameConfig>,
) {
for (interaction, button_type) in &mut interaction_query {
match *interaction {
Interaction::Pressed => match button_type {
ButtonType::InventoryOpen => {
open_inventory(&mut commands, itemstack_query);
open_inventory(&mut commands, itemstack_query, &game_config);
}
ButtonType::InventoryClose => {
for (entity, root) in root_query.iter() {

View File

@@ -1,7 +1,8 @@
use super::super::components::{ButtonType, RootMarker};
use crate::prelude::GameConfig;
use crate::{features::inventory::ui::list_itemstack, prelude::*};
pub fn open_inventory(commands: &mut Commands, items: Query<&ItemStack>) {
pub fn open_inventory(commands: &mut Commands, items: Query<&ItemStack>, game_config: &Res<GameConfig>) {
commands
.spawn((
RootMarker::Inventory,
@@ -57,7 +58,7 @@ pub fn open_inventory(commands: &mut Commands, items: Query<&ItemStack>) {
})
.with_children(|parent| {
for itemstack in items.iter() {
parent.spawn(list_itemstack(itemstack));
parent.spawn(list_itemstack(itemstack, game_config));
}
});
});

View File

@@ -1,9 +1,9 @@
use crate::prelude::*;
pub fn list_itemstack(itemstack: &ItemStack) -> impl Bundle {
pub fn list_itemstack(itemstack: &ItemStack, game_config: &GameConfig) -> impl Bundle {
let name = match itemstack.amount {
1 => itemstack.item_type.singular(),
_ => itemstack.item_type.plural(),
1 => itemstack.item_type.singular(game_config),
_ => itemstack.item_type.plural(game_config),
};
(
@@ -36,7 +36,11 @@ pub fn list_itemstack(itemstack: &ItemStack) -> impl Bundle {
14.0,
Color::WHITE
),
text(itemstack.item_type.description(), 10.0, Color::WHITE)
text(
itemstack.item_type.description(game_config),
10.0,
Color::WHITE
)
]
)
],