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::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
#[derive(Component, Clone)]
|
#[derive(Component, Clone)]
|
||||||
|
|
@ -32,4 +34,16 @@ impl Item {
|
||||||
|
|
||||||
!rect.intersect(other_rect).is_empty()
|
!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>>();
|
.collect::<Vec<Entity>>();
|
||||||
self.can_fit(item_query, children.as_slice(), *size, queried_position)
|
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))
|
Inventory::new(UVec2::splat(4))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 1x2 0;0
|
||||||
fn item_a() -> Item {
|
fn item_a() -> Item {
|
||||||
Item::new_positioned(UVec2::new(1, 2), UVec2::new(0, 0))
|
Item::new_positioned(UVec2::new(1, 2), UVec2::new(0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 2x2 0;2
|
||||||
fn item_b() -> Item {
|
fn item_b() -> Item {
|
||||||
Item::new_positioned(UVec2::new(2, 2), UVec2::new(0, 2))
|
Item::new_positioned(UVec2::new(2, 2), UVec2::new(0, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 3x2 1;0
|
||||||
fn item_c() -> Item {
|
fn item_c() -> Item {
|
||||||
Item::new_positioned(UVec2::new(3, 2), UVec2::new(1, 0))
|
Item::new_positioned(UVec2::new(3, 2), UVec2::new(1, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 2x2 2;2
|
||||||
fn item_d() -> Item {
|
fn item_d() -> Item {
|
||||||
Item::new_positioned(UVec2::new(2, 2), UVec2::new(2, 2))
|
Item::new_positioned(UVec2::new(2, 2), UVec2::new(2, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 1x1 0;0
|
||||||
fn item_e() -> Item {
|
fn item_e() -> Item {
|
||||||
Item::new_positioned(UVec2::new(1, 1), UVec2::new(0, 0))
|
Item::new_positioned(UVec2::new(1, 1), UVec2::new(0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 5x5 0;0
|
||||||
fn item_f() -> Item {
|
fn item_f() -> Item {
|
||||||
Item::new_positioned(UVec2::new(5, 5), UVec2::new(0, 0))
|
Item::new_positioned(UVec2::new(5, 5), UVec2::new(0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 2x2 3;3
|
||||||
fn item_g() -> Item {
|
fn item_g() -> Item {
|
||||||
Item::new_positioned(UVec2::new(2, 2), UVec2::new(3, 3))
|
Item::new_positioned(UVec2::new(2, 2), UVec2::new(3, 3))
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +122,7 @@ mod inventory {
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct Items(Vec<Item>, usize, bool);
|
struct Items(Vec<Item>, usize, bool);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component, Resource)]
|
||||||
struct MovableItem(UVec2, bool);
|
struct MovableItem(UVec2, bool);
|
||||||
|
|
||||||
fn insert_item(
|
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]
|
#[test]
|
||||||
fn everything_fits() {
|
fn everything_fits() {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
|
|
@ -230,4 +251,53 @@ mod inventory {
|
||||||
|
|
||||||
world.run_system(system).expect("Error on running system");
|
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