3

is it possible to create complex queries that directly filter by the value of a field in a component?

For example, say - I have a 2D board game (say chess or something), and I want to figure out if there is a piece on a specific coordinate. My component will look as following:

#[derive(Component)]
struct BoardPosition {
    x: usize,
    y: usize,
}

And I'm looking to find, say the piece in position (4,5). Then, my query will look as following - iterating through the entire board:

fn some_system(pieces: Query<&BoardPosition>) {
    for piece in pieces.iter() {
        if piece.x == 4 && piece.y == 5 {
            // This is my piece, now I can do whatever I want with it
        }
    }

}

But clearly, this takes O(n) to find just one simple piece. If I would have stored the board as a double-list (i.e, [[T; N]; N]), then finding this piece would have taken O(1) by simply doing board[4][5], but since bevy owns the components, I can't simply access the entity (or its other components) in this way.

Is there a smarter way to do this, which will allow a fast query and allow me to get (or change) other components of the queried entity?

E_net4
  • 27,810
  • 13
  • 101
  • 139
nir shahar
  • 328
  • 3
  • 13

1 Answers1

5

You can have a "board" with an array for quick lookup while still having Bevy manage the pieces themselves. Simply create a Board resource (or an entity with a Board component) that keeps references to the other entities. Then you can use .get() on the pieces Query to get the piece.

It should look something like this:

struct Board {
    tiles: [[Option<Entity>; 8]; 8],
}

#[derive(Component)]
struct Piece {
    // they can still have x, y if you want
}

fn some_system(board: Res<Board>, pieces: Query<&Piece>) {
    let entity = board.tiles[4][5].expect("no entity at (4, 5)");
    let piece = pieces.get(entity).expect("entity at (4, 5) is not a Piece");
    // do whatever you want with the piece
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106
  • Cool! Many thanks! Do I have to require a Query param in order to do the `.get(entity)`, or are there other ways to get the entity's components? Also, to upgrade this answer - I think it would be more concise to insert the board as a resource instead of a regular entity component :) – nir shahar Oct 11 '22 at 18:25
  • 1
    @nirshahar As far as I'm aware, yes you have to have `Query<&Piece>` to get the `Piece`s. And you should absolutely use a resource if there's only the single board; I just didn't want to make assumptions in my answer. :) I'll update that though – kmdreko Oct 11 '22 at 18:35