first commit
This commit is contained in:
82
docs/gaming/games/ecs/src/bitset/bitset.md
Normal file
82
docs/gaming/games/ecs/src/bitset/bitset.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# BitSet
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`BitSet` is the foundational mask primitive used by archetypes, queries, and the component registry inside `@suaveplan/ecs`. Storing component membership as bits packed into `Uint32Array` words gives the engine cache-friendly storage and O(words) algebra for subset, superset, and intersection tests — the hot paths driving every archetype-graph transition.
|
||||
|
||||
The class is intentionally narrow: it offers only the operators needed by the engine itself (`set`, `unset`, `has`, `containsAll`, `intersects`, `equals`, `count`, `clone`, `clear`, `toKey`, iterator). It is universal — no `node:*`, browser, or React dependency — so it runs identically in Bun, Node, and the browser.
|
||||
|
||||
## Features
|
||||
|
||||
- `Uint32Array`-backed storage; one word per 32 bits.
|
||||
- O(words) `containsAll` and `intersects`, safe across mismatched sizes.
|
||||
- Population count (`count`) via the SWAR Hamming-weight trick.
|
||||
- Sorted-ascending iteration through `Symbol.iterator`.
|
||||
- Stable serialised key from `toKey()` used as the archetype-graph map key.
|
||||
- Defensive `set` / `unset` guards: out-of-range bit indices throw `RangeError`; the constructor rejects non-positive sizes.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { BitSet } from "@suaveplan/ecs";
|
||||
|
||||
const mask = new BitSet(64);
|
||||
mask.set(0);
|
||||
mask.set(5);
|
||||
mask.set(32);
|
||||
|
||||
console.log(mask.has(5)); // true
|
||||
console.log([...mask]); // [0, 5, 32]
|
||||
console.log(mask.toKey()); // "0,5,32"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { BitSet } from "@suaveplan/ecs";
|
||||
|
||||
const include = new BitSet(128);
|
||||
const archetype = new BitSet(128);
|
||||
include.set(3);
|
||||
include.set(7);
|
||||
for (const cid of [3, 7, 11, 18]) archetype.set(cid);
|
||||
|
||||
if (archetype.containsAll(include)) {
|
||||
// Archetype has every required component — yield its entities.
|
||||
}
|
||||
|
||||
const exclude = new BitSet(128);
|
||||
exclude.set(11);
|
||||
if (archetype.intersects(exclude)) {
|
||||
// Skip — archetype contains a banned component.
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Member | Description |
|
||||
|---|---|
|
||||
| `new BitSet(size)` | Allocate a bitset of `size` bits. Throws `RangeError` for non-positive integer sizes. |
|
||||
| `size` | Read-only declared bit-width. |
|
||||
| `set(bit)` / `unset(bit)` | Flip a single bit. `RangeError` on out-of-range index. |
|
||||
| `has(bit)` | Test a bit. Returns `false` for out-of-range indices. |
|
||||
| `containsAll(other)` | `true` when every bit set in `other` is also set here. Safe across mismatched word counts. |
|
||||
| `intersects(other)` | `true` when at least one bit is set in both bitsets. |
|
||||
| `equals(other)` | Structural word-by-word equality. |
|
||||
| `count()` | Population count via SWAR. |
|
||||
| `clone()` | Deep copy with the same size. |
|
||||
| `clear()` | Reset every bit to zero. |
|
||||
| `toKey()` | Comma-separated string of set indices, ascending. |
|
||||
| `[Symbol.iterator]()` | Yield set indices in ascending order. |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Words are accessed with `>>> 5` (divide by 32) and `& 31` (mod 32). Using bitwise math keeps everything in the 32-bit-integer fast path.
|
||||
- `containsAll` walks each word in lock-step and treats trailing words of `other` as zero when `this` is shorter — this lets the world build mask-only diffs between archetypes without forcing both sides to the same allocation size.
|
||||
- `count` is the classic 5-step parallel bit-population trick, fast and branch-free.
|
||||
- `toKey` produces a stable, comparable string used as the archetype-graph map key. It is O(size) but only paid once per archetype-create event.
|
||||
- The iterator is a generator; `for (const bit of set)` consumes it lazily.
|
||||
Reference in New Issue
Block a user