JaimeGensler / thyseus

An archetypal Entity Component System, built entirely in Typescript
MIT License
74 stars 3 forks source link

[FEAT] `Query.p.groups()`/`Query.p.pairs()` #78

Closed JaimeGensler closed 9 months ago

JaimeGensler commented 9 months ago

Describe the problem this feature solves

Double-iterating queries (and possibly deeper?) is a fairly common pattern, but doing it in a sane way isn't super feasible.

If we want to avoid double comparisons, this is the best way to do it right now:

function detectCollisions(query: Query<Collider>) {
  let i = 0;
  for (const collider of query) {
    let j = 0;
    for (const collider of query) {
      if (i <= j) {
        continue;
      }
      // Code
    }
  }
}

Describe the solution you'd like to see

A method on queries to enable double (or deeper) iteration. The above could look like either:

function detectCollisions(query: Query<Collider>) {
  for (const [colliderA, colliderB] of query.pairs()) {
  }
}

or

function detectCollisions(query: Query<Collider>) {
  for (const [colliderA, colliderB] of query.groups(2)) {
  }
}

Implementing pairs is easier but less flexible and harder for inlining. Groups is way more flexible but harder to inline.

What alternatives exist? (optional)

It's possible to define a custom pairs() function that abstracts the iteration count tracking, but providing it as a first-party method is probably the right move, and opens it up to eventual iterator inlining