Merge branch '26-planting-crops' into 'dev'
Implement planting crops See merge request softwaregrundprojekt/2025-2026/einzelprojekt/tutorium-moritz/bernroider-dominik/bernroider-dominik!22
This commit is contained in:
BIN
assets/crop.aseprite
Normal file
BIN
assets/crop.aseprite
Normal file
Binary file not shown.
@@ -7,18 +7,23 @@ pub struct Tile {
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
#[derive(Component, Default, Serialize, Deserialize, Clone, Copy, Debug)]
|
||||
#[derive(Component)]
|
||||
pub struct CropVisual;
|
||||
|
||||
#[derive(Component, Default, Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum TileState {
|
||||
#[default]
|
||||
Unclaimed,
|
||||
Empty,
|
||||
Occupied,
|
||||
Occupied {
|
||||
seed: ItemType,
|
||||
},
|
||||
}
|
||||
|
||||
impl TileState {
|
||||
pub fn is_blocking(&self) -> bool {
|
||||
match self {
|
||||
TileState::Occupied => true,
|
||||
TileState::Occupied { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -60,4 +65,4 @@ impl Grid {
|
||||
*tile_state = mapper(&*tile_state);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::prelude::*;
|
||||
use components::CropVisual;
|
||||
|
||||
pub mod components;
|
||||
pub mod consts;
|
||||
@@ -12,10 +13,7 @@ impl Plugin for GridPlugin {
|
||||
app.add_systems(OnEnter(AppState::GameScreen), setup);
|
||||
app.add_systems(OnExit(AppState::GameScreen), cleanup);
|
||||
|
||||
app.add_systems(
|
||||
Update,
|
||||
update_tile_colors.run_if(in_state(AppState::GameScreen)),
|
||||
);
|
||||
app.add_systems(Update, update_tiles.run_if(in_state(AppState::GameScreen)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +43,19 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<Gam
|
||||
grid_height,
|
||||
)),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
CropVisual,
|
||||
AseSlice {
|
||||
name: "Crop".into(),
|
||||
aseprite: asset_server.load("crop.aseprite"),
|
||||
},
|
||||
Sprite::default(),
|
||||
Transform::default(),
|
||||
Visibility::Hidden,
|
||||
ZIndex(1),
|
||||
));
|
||||
})
|
||||
.id();
|
||||
column.push(tile_entity);
|
||||
}
|
||||
@@ -65,22 +76,32 @@ fn cleanup(mut commands: Commands, tile_query: Query<Entity, With<Tile>>) {
|
||||
commands.remove_resource::<Grid>();
|
||||
}
|
||||
|
||||
fn update_tile_colors(
|
||||
mut query: Query<(&TileState, &mut AseSlice)>,
|
||||
fn update_tiles(
|
||||
mut query: Query<(&TileState, &mut AseSlice, &Children)>,
|
||||
mut crop_query: Query<&mut Visibility, With<CropVisual>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
for (state, mut slice) in &mut query {
|
||||
for (state, mut slice, children) in &mut query {
|
||||
slice.name = match state {
|
||||
TileState::Unclaimed => "Unclaimed",
|
||||
TileState::Empty => "Empty",
|
||||
TileState::Occupied => "Occupied",
|
||||
TileState::Occupied { .. } => "Occupied",
|
||||
}
|
||||
.into();
|
||||
|
||||
slice.aseprite = match state {
|
||||
TileState::Unclaimed => asset_server.load("tiles/tile-unclaimed.aseprite"),
|
||||
TileState::Empty => asset_server.load("tiles/tile-empty.aseprite"),
|
||||
TileState::Occupied => asset_server.load("tiles/tile-occupied.aseprite"),
|
||||
TileState::Occupied { .. } => asset_server.load("tiles/tile-occupied.aseprite"),
|
||||
};
|
||||
|
||||
for child in children.iter() {
|
||||
if let Ok(mut visibility) = crop_query.get_mut(child) {
|
||||
*visibility = match state {
|
||||
TileState::Occupied { .. } => Visibility::Visible,
|
||||
_ => Visibility::Hidden,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,8 +121,12 @@ fn debug_click(
|
||||
(x, y),
|
||||
|state| match state {
|
||||
TileState::Unclaimed => TileState::Empty,
|
||||
TileState::Empty => TileState::Occupied,
|
||||
TileState::Occupied => TileState::Unclaimed,
|
||||
TileState::Empty => TileState::Occupied {
|
||||
seed: ItemType::BerrySeed {
|
||||
name: "Debug".into(),
|
||||
},
|
||||
},
|
||||
TileState::Occupied { .. } => TileState::Unclaimed,
|
||||
},
|
||||
tile_query,
|
||||
)
|
||||
|
||||
@@ -114,6 +114,14 @@ pub struct Inventory {
|
||||
}
|
||||
|
||||
impl Inventory {
|
||||
pub fn has_item(&self, items_query: Query<&ItemStack>) -> bool {
|
||||
self.items
|
||||
.iter()
|
||||
.map(|entity| items_query.get(*entity).ok())
|
||||
.find(|option| option.is_some())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn update_item_stack(
|
||||
&mut self,
|
||||
commands: &mut Commands,
|
||||
|
||||
94
src/features/pom/actions.rs
Normal file
94
src/features/pom/actions.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum InteractionAction {
|
||||
Plant(ItemType),
|
||||
}
|
||||
|
||||
impl InteractionAction {
|
||||
pub fn get_name(&self, game_config: &GameConfig) -> String {
|
||||
match self {
|
||||
InteractionAction::Plant(item) => format!("Pflanze {}", item.singular(game_config)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sprite(
|
||||
&self,
|
||||
asset_server: &Res<AssetServer>,
|
||||
game_config: &GameConfig,
|
||||
) -> Option<AseSlice> {
|
||||
match self {
|
||||
InteractionAction::Plant(item) => Some(item.get_sprite(asset_server, game_config)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_options(
|
||||
tile_state: &TileState,
|
||||
inventory: &Inventory,
|
||||
item_query: Query<&ItemStack>,
|
||||
) -> Vec<InteractionAction> {
|
||||
let mut options: Vec<InteractionAction> = vec![];
|
||||
|
||||
for &entity in &inventory.items {
|
||||
let Ok(stack) = item_query.get(entity) else {
|
||||
continue;
|
||||
};
|
||||
if stack.amount <= 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
match tile_state {
|
||||
TileState::Empty => match &stack.item_type {
|
||||
ItemType::BerrySeed { .. } => {
|
||||
options.push(InteractionAction::Plant(stack.item_type.clone()));
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
options
|
||||
}
|
||||
|
||||
pub fn execute(
|
||||
&self,
|
||||
pos: (u32, u32),
|
||||
grid: &Grid,
|
||||
tile_query: &mut Query<&mut TileState>,
|
||||
inventory: &mut Inventory,
|
||||
item_stack_query: &mut Query<&mut ItemStack>,
|
||||
commands: &mut Commands,
|
||||
) {
|
||||
let Ok(tile_entity) = grid.get_tile(pos) else {
|
||||
println!("Error during interaction: Couldn't get tile_entity");
|
||||
return;
|
||||
};
|
||||
let Ok(mut tile_state) = tile_query.get_mut(tile_entity) else {
|
||||
println!("Error during interaction: Couldn't get mut tile_state");
|
||||
return;
|
||||
};
|
||||
|
||||
match self {
|
||||
InteractionAction::Plant(seed_type) => {
|
||||
if let TileState::Empty = *tile_state {
|
||||
if inventory.update_item_stack(
|
||||
commands,
|
||||
item_stack_query,
|
||||
seed_type.clone(),
|
||||
-1,
|
||||
) {
|
||||
println!("Planting {:?}", seed_type);
|
||||
*tile_state = TileState::Occupied {
|
||||
seed: seed_type.clone(),
|
||||
};
|
||||
} else {
|
||||
println!("No {:?} in inventory!", seed_type);
|
||||
}
|
||||
} else {
|
||||
println!("Tile is not empty, cannot plant.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::features::pom::actions::InteractionAction;
|
||||
use crate::prelude::*;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
@@ -40,4 +41,5 @@ impl MovingState {
|
||||
#[derive(Component, Default)]
|
||||
pub struct InteractionTarget {
|
||||
pub target: Option<(u32, u32)>,
|
||||
pub action: Option<InteractionAction>,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::features::pom::actions::InteractionAction;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Message)]
|
||||
@@ -15,6 +16,7 @@ pub struct InvalidMoveMessage {
|
||||
pub struct InteractStartMessage {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub action: InteractionAction,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::collections::VecDeque;
|
||||
use utils::find_path;
|
||||
use utils::manhattan_distance;
|
||||
|
||||
pub mod actions;
|
||||
pub mod components;
|
||||
pub mod messages;
|
||||
pub mod ui;
|
||||
@@ -71,6 +72,7 @@ fn handle_move(
|
||||
for (grid_pos, mut path_queue, mut interaction_target) in pom_query.iter_mut() {
|
||||
// Clear any pending interaction when moving manually
|
||||
interaction_target.target = None;
|
||||
interaction_target.action = None;
|
||||
|
||||
let grid_start = (grid_pos.x, grid_pos.y);
|
||||
let start = path_queue.steps.front().unwrap_or(&grid_start);
|
||||
@@ -108,6 +110,7 @@ fn handle_interact(
|
||||
if manhattan_distance(current_pos.0, current_pos.1, target_pos.0, target_pos.1) == 1 {
|
||||
path_queue.steps.clear();
|
||||
interaction_target.target = Some(target_pos);
|
||||
interaction_target.action = Some(message.action.clone());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -138,10 +141,12 @@ fn handle_interact(
|
||||
if let Some(path) = best_path {
|
||||
path_queue.steps = path;
|
||||
interaction_target.target = Some(target_pos);
|
||||
interaction_target.action = Some(message.action.clone());
|
||||
} else {
|
||||
println!("Cannot reach interaction target at {:?}", target_pos);
|
||||
// Don't set target if unreachable
|
||||
interaction_target.target = None;
|
||||
interaction_target.action = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,8 +154,11 @@ fn handle_interact(
|
||||
|
||||
fn perform_interaction(
|
||||
mut pom_query: Query<(&GridPosition, &mut InteractionTarget, &PathQueue)>,
|
||||
// grid: Res<Grid>,
|
||||
// mut tile_query: Query<&mut TileState>,
|
||||
grid: Res<Grid>,
|
||||
mut tile_query: Query<&mut TileState>,
|
||||
mut inventory: ResMut<Inventory>,
|
||||
mut item_stack_query: Query<&mut ItemStack>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (pos, mut target_component, path_queue) in pom_query.iter_mut() {
|
||||
if let Some(target) = target_component.target {
|
||||
@@ -165,10 +173,20 @@ fn perform_interaction(
|
||||
target.0, target.1
|
||||
);
|
||||
|
||||
// TODO: Implement interaction logic
|
||||
if let Some(action) = &target_component.action {
|
||||
action.execute(
|
||||
target,
|
||||
&grid,
|
||||
&mut tile_query,
|
||||
&mut inventory,
|
||||
&mut item_stack_query,
|
||||
&mut commands,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
target_component.target = None;
|
||||
target_component.action = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,4 +266,3 @@ fn update_pom(asset_server: Res<AssetServer>, mut query: Query<(&MovingState, &m
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::features::pom::actions::InteractionAction;
|
||||
use crate::features::ui::utils::ui_blocks;
|
||||
use crate::prelude::*;
|
||||
use bevy::window::PrimaryWindow;
|
||||
@@ -9,7 +10,11 @@ pub enum RootMarker {
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum ButtonType {
|
||||
Interact { x: u32, y: u32 },
|
||||
Interact {
|
||||
x: u32,
|
||||
y: u32,
|
||||
action: InteractionAction,
|
||||
},
|
||||
Cancel,
|
||||
}
|
||||
|
||||
@@ -19,6 +24,11 @@ pub fn spawn_context_menu(
|
||||
root_query: Query<Entity, With<RootMarker>>,
|
||||
camera_query: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
|
||||
config: Res<GameConfig>,
|
||||
grid: Res<Grid>,
|
||||
tile_query: Query<&TileState>,
|
||||
inventory: Res<Inventory>,
|
||||
item_query: Query<&ItemStack>,
|
||||
game_config: Res<GameConfig>,
|
||||
) {
|
||||
for message in tile_click_messages.read() {
|
||||
// Despawn existing menu
|
||||
@@ -37,6 +47,14 @@ pub fn spawn_context_menu(
|
||||
let (camera, camera_transform) = *camera_query;
|
||||
|
||||
if let Ok(screen_pos) = camera.world_to_viewport(camera_transform, world_pos) {
|
||||
let Ok(tile_entity) = grid.get_tile((message.x, message.y)) else {
|
||||
return;
|
||||
};
|
||||
let Ok(tile_state) = tile_query.get(tile_entity) else {
|
||||
return;
|
||||
};
|
||||
let options = InteractionAction::list_options(tile_state, &inventory, item_query);
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
Node {
|
||||
@@ -53,18 +71,21 @@ pub fn spawn_context_menu(
|
||||
GlobalTransform::default(),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn(button(
|
||||
ButtonType::Interact {
|
||||
x: message.x,
|
||||
y: message.y,
|
||||
},
|
||||
ButtonVariant::Primary,
|
||||
Node {
|
||||
padding: UiRect::all(px(5)),
|
||||
..default()
|
||||
},
|
||||
|c| text("<Interact>", 20.0, c),
|
||||
));
|
||||
for option in options {
|
||||
parent.spawn(button(
|
||||
ButtonType::Interact {
|
||||
x: message.x,
|
||||
y: message.y,
|
||||
action: option.clone(),
|
||||
},
|
||||
ButtonVariant::Primary,
|
||||
Node {
|
||||
padding: UiRect::all(px(5)),
|
||||
..default()
|
||||
},
|
||||
|c| text(option.clone().get_name(&game_config), 20.0, c), // TODO: add sprite
|
||||
));
|
||||
}
|
||||
|
||||
parent.spawn(button(
|
||||
ButtonType::Cancel,
|
||||
@@ -109,8 +130,12 @@ pub fn buttons(
|
||||
for (interaction, button_type) in button_query.iter_mut() {
|
||||
if *interaction == Interaction::Pressed {
|
||||
match button_type {
|
||||
ButtonType::Interact { x, y } => {
|
||||
interact_messages.write(InteractStartMessage { x: *x, y: *y });
|
||||
ButtonType::Interact { x, y, action } => {
|
||||
interact_messages.write(InteractStartMessage {
|
||||
x: *x,
|
||||
y: *y,
|
||||
action: action.clone(),
|
||||
});
|
||||
}
|
||||
ButtonType::Cancel => (),
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ fn dump_savegame(
|
||||
for y in 0..grid.height {
|
||||
if let Ok(entity) = grid.get_tile((x, y)) {
|
||||
if let Ok(state) = tile_query.get(entity) {
|
||||
col.push(*state);
|
||||
col.push(state.clone());
|
||||
} else {
|
||||
col.push(TileState::Unclaimed);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ fn load_savegame(
|
||||
if x < grid.width && y < grid.height {
|
||||
if let Ok(entity) = grid.get_tile((x, y)) {
|
||||
if let Ok(mut state) = tile_query.get_mut(entity) {
|
||||
*state = save_data.tiles[x as usize][y as usize];
|
||||
*state = save_data.tiles[x as usize][y as usize].clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
166
tests/interaction.rs
Normal file
166
tests/interaction.rs
Normal file
@@ -0,0 +1,166 @@
|
||||
use bevy::ecs::system::RunSystemOnce;
|
||||
use pomomon_garden::features::grid::components::{Grid, Tile, TileState};
|
||||
use pomomon_garden::features::inventory::components::{Inventory, ItemStack, ItemType};
|
||||
use pomomon_garden::features::pom::actions::InteractionAction;
|
||||
use pomomon_garden::prelude::*;
|
||||
|
||||
fn setup_interaction_app(
|
||||
grid_width: u32,
|
||||
grid_height: u32,
|
||||
initial_tile_states: &[(u32, u32, TileState)],
|
||||
initial_inventory: Vec<(ItemType, u32)>,
|
||||
) -> App {
|
||||
let mut app = App::new();
|
||||
app.add_plugins(MinimalPlugins);
|
||||
app.add_plugins(AssetPlugin::default()); // Needed for asset server if used, though we mock or avoid visuals here
|
||||
|
||||
// Grid Setup
|
||||
let mut grid_tiles = Vec::with_capacity(grid_width as usize);
|
||||
for x in 0..grid_width {
|
||||
let mut column = Vec::with_capacity(grid_height as usize);
|
||||
for y in 0..grid_height {
|
||||
let entity = app
|
||||
.world_mut()
|
||||
.spawn((Tile { x, y }, TileState::Unclaimed))
|
||||
.id();
|
||||
column.push(entity);
|
||||
}
|
||||
grid_tiles.push(column);
|
||||
}
|
||||
app.world_mut().insert_resource(Grid {
|
||||
width: grid_width,
|
||||
height: grid_height,
|
||||
tiles: grid_tiles,
|
||||
});
|
||||
|
||||
for &(x, y, ref state) in initial_tile_states {
|
||||
if let Ok(entity) = app.world().resource::<Grid>().get_tile((x, y)) {
|
||||
*app.world_mut().get_mut::<TileState>(entity).unwrap() = state.clone();
|
||||
}
|
||||
}
|
||||
|
||||
// Inventory Setup
|
||||
let mut inventory_items = Vec::new();
|
||||
for (item_type, amount) in initial_inventory {
|
||||
let id = app.world_mut().spawn(ItemStack { item_type, amount }).id();
|
||||
inventory_items.push(id);
|
||||
}
|
||||
app.world_mut().insert_resource(Inventory {
|
||||
items: inventory_items,
|
||||
});
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plant_seed_interaction() {
|
||||
let seed_type = ItemType::BerrySeed {
|
||||
name: "TestSeed".into(),
|
||||
};
|
||||
let mut app = setup_interaction_app(
|
||||
3,
|
||||
3,
|
||||
&[(1, 1, TileState::Empty)],
|
||||
vec![(seed_type.clone(), 1)],
|
||||
);
|
||||
|
||||
// Run the interaction logic as a system or closure
|
||||
let _ = app.world_mut().run_system_once(
|
||||
move |grid: Res<Grid>,
|
||||
mut tile_query: Query<&mut TileState>,
|
||||
mut inventory: ResMut<Inventory>,
|
||||
mut item_stack_query: Query<&mut ItemStack>,
|
||||
mut commands: Commands| {
|
||||
let action = InteractionAction::Plant(seed_type.clone());
|
||||
action.execute(
|
||||
(1, 1),
|
||||
&grid,
|
||||
&mut tile_query,
|
||||
&mut inventory,
|
||||
&mut item_stack_query,
|
||||
&mut commands,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Apply commands (despawns etc.)
|
||||
app.update();
|
||||
|
||||
// Assert Tile State
|
||||
let grid = app.world().resource::<Grid>();
|
||||
let tile_entity = grid.get_tile((1, 1)).unwrap();
|
||||
let tile_state = app.world().entity(tile_entity).get::<TileState>().unwrap();
|
||||
|
||||
if let TileState::Occupied { seed } = tile_state {
|
||||
assert_eq!(
|
||||
*seed,
|
||||
ItemType::BerrySeed {
|
||||
name: "TestSeed".into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
panic!("Tile should be Occupied with seed, found {:?}", tile_state);
|
||||
}
|
||||
|
||||
// Assert Inventory Empty
|
||||
let inventory = app.world().resource::<Inventory>();
|
||||
// Item stack entity should be despawned or amount 0
|
||||
if !inventory.items.is_empty() {
|
||||
// If the entity still exists, check amount
|
||||
if let Some(entity) = inventory.items.first() {
|
||||
if let Some(stack) = app.world().entity(*entity).get::<ItemStack>() {
|
||||
assert_eq!(stack.amount, 0, "Item amount should be 0");
|
||||
} else {
|
||||
panic!(
|
||||
"Inventory items list should be empty or point to valid 0 amount entities. Found phantom entity."
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert!(inventory.items.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plant_seed_no_inventory() {
|
||||
let seed_type = ItemType::BerrySeed {
|
||||
name: "TestSeed".into(),
|
||||
};
|
||||
let mut app = setup_interaction_app(
|
||||
3,
|
||||
3,
|
||||
&[(1, 1, TileState::Empty)],
|
||||
vec![], // Empty inventory
|
||||
);
|
||||
|
||||
let _ = app.world_mut().run_system_once(
|
||||
move |grid: Res<Grid>,
|
||||
mut tile_query: Query<&mut TileState>,
|
||||
mut inventory: ResMut<Inventory>,
|
||||
mut item_stack_query: Query<&mut ItemStack>,
|
||||
mut commands: Commands| {
|
||||
let action = InteractionAction::Plant(seed_type.clone());
|
||||
action.execute(
|
||||
(1, 1),
|
||||
&grid,
|
||||
&mut tile_query,
|
||||
&mut inventory,
|
||||
&mut item_stack_query,
|
||||
&mut commands,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
app.update();
|
||||
|
||||
// Assert Tile State Unchanged
|
||||
let grid = app.world().resource::<Grid>();
|
||||
let tile_entity = grid.get_tile((1, 1)).unwrap();
|
||||
let tile_state = app.world().entity(tile_entity).get::<TileState>().unwrap();
|
||||
|
||||
if let TileState::Empty = tile_state {
|
||||
// Correct
|
||||
} else {
|
||||
panic!("Tile should remain Empty, found {:?}", tile_state);
|
||||
}
|
||||
}
|
||||
@@ -89,10 +89,15 @@ fn test_find_path_simple() {
|
||||
|
||||
#[test]
|
||||
fn test_find_path_around_obstacle() {
|
||||
let obstacle: TileState = TileState::Occupied {
|
||||
seed: ItemType::BerrySeed {
|
||||
name: "test".into(),
|
||||
},
|
||||
};
|
||||
let obstacles = vec![
|
||||
(2, 2, TileState::Occupied),
|
||||
(2, 3, TileState::Occupied),
|
||||
(2, 4, TileState::Occupied),
|
||||
(2, 2, obstacle.clone()),
|
||||
(2, 3, obstacle.clone()),
|
||||
(2, 4, obstacle.clone()),
|
||||
];
|
||||
let mut app = setup_pathfinding_app(5, 5, &obstacles);
|
||||
|
||||
@@ -135,12 +140,17 @@ fn test_find_path_around_obstacle() {
|
||||
|
||||
#[test]
|
||||
fn test_find_path_no_path() {
|
||||
let obstacle: TileState = TileState::Occupied {
|
||||
seed: ItemType::BerrySeed {
|
||||
name: "test".into(),
|
||||
},
|
||||
};
|
||||
let obstacles = vec![
|
||||
(2, 0, TileState::Occupied),
|
||||
(2, 1, TileState::Occupied),
|
||||
(2, 2, TileState::Occupied),
|
||||
(2, 3, TileState::Occupied),
|
||||
(2, 4, TileState::Occupied),
|
||||
(2, 0, obstacle.clone()),
|
||||
(2, 1, obstacle.clone()),
|
||||
(2, 2, obstacle.clone()),
|
||||
(2, 3, obstacle.clone()),
|
||||
(2, 4, obstacle.clone()),
|
||||
];
|
||||
let mut app = setup_pathfinding_app(5, 5, &obstacles);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user