Skip to content

Commit 33f7c08

Browse files
committed
Expand the How To series
1 parent eacc343 commit 33f7c08

File tree

5 files changed

+103
-84
lines changed

5 files changed

+103
-84
lines changed

how_to/004_tags.luau

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ world:add(entity, Dead) -- Adds the tag
4343

4444
print(world:has(entity, Dead)) -- true
4545

46+
-- jecs.is_tag(world, id) returns true if the id is a tag (no data).
47+
print(jecs.is_tag(world, Dead)) -- true
48+
49+
local Position = world:component() :: jecs.Id<number>
50+
print(jecs.is_tag(world, Position)) -- false
51+
4652
-- Tags are removed using world:remove(entity, component)
4753

4854
world:remove(entity, Dead)

how_to/012_entity_liveliness.luau

Whitespace-only changes.

how_to/041_entity_relationships.luau

Lines changed: 2 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Relationships makes it possible to describe entity graphs natively in ECS.
33
44
Adding/removing relationships is similar to adding/removing regular components,
5-
with as difference that instead of a single component id, a relationship adds
5+
with the difference that instead of a single component id, a relationship adds
66
a pair of two things to an entity. In this pair, the first element represents
77
the relationship (e.g. "Eats"), and the second element represents the relationship
88
target (e.g. "Apples").
@@ -36,9 +36,6 @@ world:add(alice, pair(Likes, bob))
3636
-- Test if entity has a relationship pair
3737
print(world:has(bob, pair(Eats, Apples))) -- true
3838

39-
-- Test if entity has a relationship wildcard
40-
print(world:has(bob, pair(Eats, jecs.Wildcard))) -- true
41-
4239
--[[
4340
Querying for relationship targets
4441
@@ -77,26 +74,6 @@ for child in world:query(pair(ChildOf, parent)) do
7774
print(`Entity {child} is a child of parent {parent}`)
7875
end
7976

80-
--[[
81-
Querying with wildcards and getting targets
82-
83-
When you query with a wildcard, you can use world:target() to get the
84-
actual target entity. This is useful when you want to find all entities
85-
with a relationship, regardless of the target.
86-
]]
87-
88-
-- Find all entities that eat something (any target)
89-
for entity in world:query(pair(Eats, jecs.Wildcard)) do
90-
local food = world:target(entity, Eats) -- Get the actual target
91-
print(`Entity {entity} eats {food}`)
92-
end
93-
94-
-- Find all entities that like someone (any target)
95-
for entity in world:query(pair(Likes, jecs.Wildcard)) do
96-
local target = world:target(entity, Likes)
97-
print(`Entity {entity} likes {target}`)
98-
end
99-
10077
--[[
10178
Combining relationship queries with regular components
10279
@@ -118,39 +95,6 @@ for entity, pos, health in world:query(Position, Health, pair(ChildOf, parent))
11895
print(`Child {entity} has position {pos} and health {health}`)
11996
end
12097

121-
--[[
122-
Querying for entities with multiple relationship targets
123-
124-
An entity can have multiple relationships with the same relationship type
125-
but different targets. For example, bob might like both alice and charlie.
126-
127-
When querying with a wildcard, you'll get the entity once, but world:target()
128-
will return the first matching target. If you need all targets, you'll need
129-
to use a different approach (see the targets example for advanced usage).
130-
]]
131-
132-
local charlie = world:entity()
133-
world:add(bob, pair(Likes, charlie))
134-
135-
-- This query will return bob once, even though bob likes both alice and charlie
136-
for entity in world:query(pair(Likes, jecs.Wildcard)) do
137-
local target = world:target(entity, Likes)
138-
print(`Entity {entity} likes {target}`) -- Will show one target per entity
139-
end
140-
141-
--[[
142-
Querying for all relationships with a specific target
143-
144-
You can also query for all entities that have any relationship with a
145-
specific target using a wildcard for the relationship part.
146-
]]
147-
148-
-- Find all entities that have any relationship with alice as the target
149-
for entity in world:query(pair(jecs.Wildcard, alice)) do
150-
-- Note: This is less common and may have performance implications
151-
print(`Entity {entity} has some relationship with alice`)
152-
end
153-
15498
--[[
15599
Relationship pairs, just like regular component, can be associated with data.
156100
]]
@@ -178,30 +122,4 @@ for entity, eats_data in world:query(pair(Eats, Apples)) do
178122
print(`Entity {entity} eats apples: amount = {eats_data.amount}`)
179123
end
180124

181-
--[[
182-
When querying for relationship pairs, it is often useful to be able to find
183-
all instances for a given relationship or target. To accomplish this, a game
184-
can use wildcard expressions.
185-
186-
Wildcards may used for the relationship or target part of a pair:
187-
188-
pair(Likes, jecs.Wildcard) -- Matches all Likes relationships
189-
pair(jecs.Wildcard, Alice) -- Matches all relationships with Alice as target
190-
191-
Using world:target() is the recommended way to get the target in a wildcard
192-
query. However, if you're in a very hot path and need maximum performance,
193-
you can access the relationship column directly (see advanced examples).
194-
]]
195-
196-
for entity in world:query(pair(Eats, jecs.Wildcard)) do
197-
local nth = 0
198-
local food = world:target(entity, Eats, nth)
199-
while food do
200-
local eats_data = world:get(entity, pair(Eats, food))
201-
assert(eats_data) -- This coerces the type to be non-nilable for the type checker
202-
print(`Entity {entity} eats {food}: amount = {eats_data.amount}`)
203-
204-
nth += 1
205-
food = world:target(entity, Eats, nth)
206-
end
207-
end
125+
-- For wildcard queries and world:target (0-based index), see 042_target.luau and 043_wildcards.luau.

how_to/042_target.luau

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--[[
2+
world:target(entity, relation, index?) returns the target of a relationship
3+
on an entity. The index is 0-based. If no target exists at that index, it
4+
returns nil.
5+
6+
Use target when you have queried with a wildcard (e.g. pair(Eats, jecs.Wildcard))
7+
and need the actual target entity for each result. Without an index, the
8+
default is 0 (the first target).
9+
]]
10+
11+
local jecs = require("@jecs")
12+
local pair = jecs.pair
13+
local world = jecs.world()
14+
15+
local Eats = world:entity()
16+
local Apples = world:entity()
17+
local Oranges = world:entity()
18+
local bob = world:entity()
19+
20+
world:add(bob, pair(Eats, Apples))
21+
world:add(bob, pair(Eats, Oranges))
22+
23+
-- First target is at index 0
24+
local first = world:target(bob, Eats, 0)
25+
print(first == Apples) -- true
26+
27+
-- Second target is at index 1
28+
local second = world:target(bob, Eats, 1)
29+
print(second == Oranges) -- true
30+
31+
-- No third target: index 2 returns nil
32+
local third = world:target(bob, Eats, 2)
33+
print(third == nil) -- true
34+
35+
-- Omitting the index is the same as index 0
36+
local default = world:target(bob, Eats)
37+
print(default == Apples) -- true

how_to/043_wildcards.luau

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--[[
2+
Wildcards let you query relationships without specifying the exact target or
3+
relationship. jecs.Wildcard matches any entity in that slot.
4+
5+
- pair(relation, jecs.Wildcard) matches that relationship with any target.
6+
- pair(jecs.Wildcard, target) matches any relationship with that target.
7+
8+
Use world:target(entity, relation, index) to get the actual target when
9+
querying with a wildcard. The index is 0-based (see 042_target.luau).
10+
]]
11+
12+
local jecs = require("@jecs")
13+
local pair = jecs.pair
14+
local world = jecs.world()
15+
16+
local Eats = world:component() :: jecs.Id<{ amount: number }>
17+
local Likes = world:entity()
18+
local Apples = world:entity()
19+
local alice = world:entity()
20+
local bob = world:entity()
21+
22+
world:add(bob, pair(Eats, Apples))
23+
world:set(bob, pair(Eats, Apples), { amount = 1 })
24+
world:add(bob, pair(Likes, alice))
25+
26+
-- world:has with wildcard
27+
print(world:has(bob, pair(Eats, jecs.Wildcard))) -- true
28+
29+
-- Query with wildcard: all entities that eat something
30+
for entity in world:query(pair(Eats, jecs.Wildcard)) do
31+
local food = world:target(entity, Eats)
32+
print(`Entity {entity} eats {food}`)
33+
end
34+
35+
-- Query with wildcard: all entities that like someone
36+
for entity in world:query(pair(Likes, jecs.Wildcard)) do
37+
local target = world:target(entity, Likes)
38+
print(`Entity {entity} likes {target}`)
39+
end
40+
41+
-- Multiple targets: index is 0-based. Iterate until nil.
42+
local charlie = world:entity()
43+
world:add(bob, pair(Likes, charlie))
44+
45+
for entity in world:query(pair(Likes, jecs.Wildcard)) do
46+
local nth = 0
47+
local target = world:target(entity, Likes, nth)
48+
while target do
49+
print(`Entity {entity} likes {target}`)
50+
nth += 1
51+
target = world:target(entity, Likes, nth)
52+
end
53+
end
54+
55+
-- pair(jecs.Wildcard, target): all relationships that have this target
56+
for entity in world:query(pair(jecs.Wildcard, alice)) do
57+
print(`Entity {entity} has some relationship with alice`)
58+
end

0 commit comments

Comments
 (0)