generated from 2ndbeam/bevy-template
feat: Implemented Inventory.find_free_space
- Added tests for find_free_space
This commit is contained in:
parent
13dd936044
commit
5f59e02788
3 changed files with 120 additions and 1 deletions
|
|
@ -1,3 +1,5 @@
|
|||
use std::mem::swap;
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Component, Clone)]
|
||||
|
|
@ -32,4 +34,16 @@ impl Item {
|
|||
|
||||
!rect.intersect(other_rect).is_empty()
|
||||
}
|
||||
|
||||
/// Swap size.x with size.y
|
||||
pub fn swap_size(&mut self) {
|
||||
swap(&mut self.size.x, &mut self.size.y);
|
||||
}
|
||||
|
||||
/// Get clone of item with swapped size
|
||||
pub fn clone_swapped(&self) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.swap_size();
|
||||
new
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,4 +53,39 @@ impl Inventory {
|
|||
.collect::<Vec<Entity>>();
|
||||
self.can_fit(item_query, children.as_slice(), *size, queried_position)
|
||||
}
|
||||
|
||||
fn find_free_space_inner(
|
||||
&self,
|
||||
item_query: Query<&item::Item>,
|
||||
contained_items: &[Entity],
|
||||
queried_size: UVec2,
|
||||
was_swapped: bool,
|
||||
) -> Option<(UVec2, bool)> {
|
||||
let Some(UVec2 {x: tries_x, y: tries_y}) = self.size.checked_sub(queried_size) else {
|
||||
return None;
|
||||
};
|
||||
for x in 0..=tries_x {
|
||||
for y in 0..=tries_y {
|
||||
let tested_pos = UVec2::new(x, y);
|
||||
if self.can_fit(item_query, contained_items, queried_size, tested_pos) {
|
||||
return Some((tested_pos, was_swapped));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn find_free_space(
|
||||
&self,
|
||||
item_query: Query<&item::Item>,
|
||||
contained_items: &[Entity],
|
||||
queried_size: UVec2,
|
||||
) -> Option<(UVec2, bool)> {
|
||||
let result = self.find_free_space_inner(item_query, contained_items, queried_size, false);
|
||||
if result.is_some() {
|
||||
return result;
|
||||
}
|
||||
let swapped_size = UVec2::new(queried_size.y, queried_size.x);
|
||||
self.find_free_space_inner(item_query, contained_items, swapped_size, true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
72
src/tests.rs
72
src/tests.rs
|
|
@ -84,30 +84,37 @@ mod inventory {
|
|||
Inventory::new(UVec2::splat(4))
|
||||
}
|
||||
|
||||
/// 1x2 0;0
|
||||
fn item_a() -> Item {
|
||||
Item::new_positioned(UVec2::new(1, 2), UVec2::new(0, 0))
|
||||
}
|
||||
|
||||
/// 2x2 0;2
|
||||
fn item_b() -> Item {
|
||||
Item::new_positioned(UVec2::new(2, 2), UVec2::new(0, 2))
|
||||
}
|
||||
|
||||
/// 3x2 1;0
|
||||
fn item_c() -> Item {
|
||||
Item::new_positioned(UVec2::new(3, 2), UVec2::new(1, 0))
|
||||
}
|
||||
|
||||
/// 2x2 2;2
|
||||
fn item_d() -> Item {
|
||||
Item::new_positioned(UVec2::new(2, 2), UVec2::new(2, 2))
|
||||
}
|
||||
|
||||
/// 1x1 0;0
|
||||
fn item_e() -> Item {
|
||||
Item::new_positioned(UVec2::new(1, 1), UVec2::new(0, 0))
|
||||
}
|
||||
|
||||
/// 5x5 0;0
|
||||
fn item_f() -> Item {
|
||||
Item::new_positioned(UVec2::new(5, 5), UVec2::new(0, 0))
|
||||
}
|
||||
|
||||
/// 2x2 3;3
|
||||
fn item_g() -> Item {
|
||||
Item::new_positioned(UVec2::new(2, 2), UVec2::new(3, 3))
|
||||
}
|
||||
|
|
@ -115,7 +122,7 @@ mod inventory {
|
|||
#[derive(Resource)]
|
||||
struct Items(Vec<Item>, usize, bool);
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Resource)]
|
||||
struct MovableItem(UVec2, bool);
|
||||
|
||||
fn insert_item(
|
||||
|
|
@ -154,6 +161,20 @@ mod inventory {
|
|||
}
|
||||
}
|
||||
|
||||
fn find_space(
|
||||
item_query: Query<&Item>,
|
||||
inventory_query: Query<(&Inventory, &Children)>,
|
||||
movable_item: Res<MovableItem>,
|
||||
) {
|
||||
let (inventory, children) = inventory_query.single().unwrap();
|
||||
let MovableItem(query_size, assertion) = *movable_item;
|
||||
if assertion {
|
||||
assert!(inventory.find_free_space(item_query, children, query_size).is_some());
|
||||
} else {
|
||||
assert!(inventory.find_free_space(item_query, children, query_size).is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn everything_fits() {
|
||||
let mut world = World::new();
|
||||
|
|
@ -230,4 +251,53 @@ mod inventory {
|
|||
|
||||
world.run_system(system).expect("Error on running system");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_find_space_for_item() {
|
||||
let mut world = World::new();
|
||||
|
||||
let system = world.register_system(find_space);
|
||||
|
||||
world.insert_resource(MovableItem(UVec2::new(2, 2), true));
|
||||
|
||||
world.spawn(inventory())
|
||||
.with_child(item_a())
|
||||
.with_child(item_b())
|
||||
.with_child(item_c());
|
||||
|
||||
world.run_system(system).expect("Error on running system");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_find_space_for_item() {
|
||||
let mut world = World::new();
|
||||
|
||||
let system = world.register_system(find_space);
|
||||
|
||||
world.insert_resource(MovableItem(UVec2::new(2, 2), false));
|
||||
|
||||
world.spawn(inventory())
|
||||
.with_child(item_a())
|
||||
.with_child(item_b())
|
||||
.with_child(item_c())
|
||||
.with_child(item_d());
|
||||
|
||||
world.run_system(system).expect("Error on running system");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn item_fits_if_rotated() {
|
||||
let mut world = World::new();
|
||||
|
||||
let system = world.register_system(find_space);
|
||||
|
||||
world.insert_resource(MovableItem(UVec2::new(2, 3), true));
|
||||
|
||||
world.spawn(inventory())
|
||||
.with_child(item_a())
|
||||
.with_child(item_b())
|
||||
.with_child(item_d());
|
||||
|
||||
world.run_system(system).expect("Error on running system");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue