mirror of
https://github.com/Ukendio/jecs.git
synced 2026-03-18 00:44:32 +00:00
Expand the How To series
This commit is contained in:
parent
eacc343551
commit
33f7c08025
5 changed files with 103 additions and 84 deletions
|
|
@ -43,6 +43,12 @@ world:add(entity, Dead) -- Adds the tag
|
|||
|
||||
print(world:has(entity, Dead)) -- true
|
||||
|
||||
-- jecs.is_tag(world, id) returns true if the id is a tag (no data).
|
||||
print(jecs.is_tag(world, Dead)) -- true
|
||||
|
||||
local Position = world:component() :: jecs.Id<number>
|
||||
print(jecs.is_tag(world, Position)) -- false
|
||||
|
||||
-- Tags are removed using world:remove(entity, component)
|
||||
|
||||
world:remove(entity, Dead)
|
||||
|
|
|
|||
0
how_to/012_entity_liveliness.luau
Normal file
0
how_to/012_entity_liveliness.luau
Normal file
|
|
@ -2,7 +2,7 @@
|
|||
Relationships makes it possible to describe entity graphs natively in ECS.
|
||||
|
||||
Adding/removing relationships is similar to adding/removing regular components,
|
||||
with as difference that instead of a single component id, a relationship adds
|
||||
with the difference that instead of a single component id, a relationship adds
|
||||
a pair of two things to an entity. In this pair, the first element represents
|
||||
the relationship (e.g. "Eats"), and the second element represents the relationship
|
||||
target (e.g. "Apples").
|
||||
|
|
@ -36,9 +36,6 @@ world:add(alice, pair(Likes, bob))
|
|||
-- Test if entity has a relationship pair
|
||||
print(world:has(bob, pair(Eats, Apples))) -- true
|
||||
|
||||
-- Test if entity has a relationship wildcard
|
||||
print(world:has(bob, pair(Eats, jecs.Wildcard))) -- true
|
||||
|
||||
--[[
|
||||
Querying for relationship targets
|
||||
|
||||
|
|
@ -77,26 +74,6 @@ for child in world:query(pair(ChildOf, parent)) do
|
|||
print(`Entity {child} is a child of parent {parent}`)
|
||||
end
|
||||
|
||||
--[[
|
||||
Querying with wildcards and getting targets
|
||||
|
||||
When you query with a wildcard, you can use world:target() to get the
|
||||
actual target entity. This is useful when you want to find all entities
|
||||
with a relationship, regardless of the target.
|
||||
]]
|
||||
|
||||
-- Find all entities that eat something (any target)
|
||||
for entity in world:query(pair(Eats, jecs.Wildcard)) do
|
||||
local food = world:target(entity, Eats) -- Get the actual target
|
||||
print(`Entity {entity} eats {food}`)
|
||||
end
|
||||
|
||||
-- Find all entities that like someone (any target)
|
||||
for entity in world:query(pair(Likes, jecs.Wildcard)) do
|
||||
local target = world:target(entity, Likes)
|
||||
print(`Entity {entity} likes {target}`)
|
||||
end
|
||||
|
||||
--[[
|
||||
Combining relationship queries with regular components
|
||||
|
||||
|
|
@ -118,39 +95,6 @@ for entity, pos, health in world:query(Position, Health, pair(ChildOf, parent))
|
|||
print(`Child {entity} has position {pos} and health {health}`)
|
||||
end
|
||||
|
||||
--[[
|
||||
Querying for entities with multiple relationship targets
|
||||
|
||||
An entity can have multiple relationships with the same relationship type
|
||||
but different targets. For example, bob might like both alice and charlie.
|
||||
|
||||
When querying with a wildcard, you'll get the entity once, but world:target()
|
||||
will return the first matching target. If you need all targets, you'll need
|
||||
to use a different approach (see the targets example for advanced usage).
|
||||
]]
|
||||
|
||||
local charlie = world:entity()
|
||||
world:add(bob, pair(Likes, charlie))
|
||||
|
||||
-- This query will return bob once, even though bob likes both alice and charlie
|
||||
for entity in world:query(pair(Likes, jecs.Wildcard)) do
|
||||
local target = world:target(entity, Likes)
|
||||
print(`Entity {entity} likes {target}`) -- Will show one target per entity
|
||||
end
|
||||
|
||||
--[[
|
||||
Querying for all relationships with a specific target
|
||||
|
||||
You can also query for all entities that have any relationship with a
|
||||
specific target using a wildcard for the relationship part.
|
||||
]]
|
||||
|
||||
-- Find all entities that have any relationship with alice as the target
|
||||
for entity in world:query(pair(jecs.Wildcard, alice)) do
|
||||
-- Note: This is less common and may have performance implications
|
||||
print(`Entity {entity} has some relationship with alice`)
|
||||
end
|
||||
|
||||
--[[
|
||||
Relationship pairs, just like regular component, can be associated with data.
|
||||
]]
|
||||
|
|
@ -178,30 +122,4 @@ for entity, eats_data in world:query(pair(Eats, Apples)) do
|
|||
print(`Entity {entity} eats apples: amount = {eats_data.amount}`)
|
||||
end
|
||||
|
||||
--[[
|
||||
When querying for relationship pairs, it is often useful to be able to find
|
||||
all instances for a given relationship or target. To accomplish this, a game
|
||||
can use wildcard expressions.
|
||||
|
||||
Wildcards may used for the relationship or target part of a pair:
|
||||
|
||||
pair(Likes, jecs.Wildcard) -- Matches all Likes relationships
|
||||
pair(jecs.Wildcard, Alice) -- Matches all relationships with Alice as target
|
||||
|
||||
Using world:target() is the recommended way to get the target in a wildcard
|
||||
query. However, if you're in a very hot path and need maximum performance,
|
||||
you can access the relationship column directly (see advanced examples).
|
||||
]]
|
||||
|
||||
for entity in world:query(pair(Eats, jecs.Wildcard)) do
|
||||
local nth = 0
|
||||
local food = world:target(entity, Eats, nth)
|
||||
while food do
|
||||
local eats_data = world:get(entity, pair(Eats, food))
|
||||
assert(eats_data) -- This coerces the type to be non-nilable for the type checker
|
||||
print(`Entity {entity} eats {food}: amount = {eats_data.amount}`)
|
||||
|
||||
nth += 1
|
||||
food = world:target(entity, Eats, nth)
|
||||
end
|
||||
end
|
||||
-- For wildcard queries and world:target (0-based index), see 042_target.luau and 043_wildcards.luau.
|
||||
|
|
|
|||
37
how_to/042_target.luau
Normal file
37
how_to/042_target.luau
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
--[[
|
||||
world:target(entity, relation, index?) returns the target of a relationship
|
||||
on an entity. The index is 0-based. If no target exists at that index, it
|
||||
returns nil.
|
||||
|
||||
Use target when you have queried with a wildcard (e.g. pair(Eats, jecs.Wildcard))
|
||||
and need the actual target entity for each result. Without an index, the
|
||||
default is 0 (the first target).
|
||||
]]
|
||||
|
||||
local jecs = require("@jecs")
|
||||
local pair = jecs.pair
|
||||
local world = jecs.world()
|
||||
|
||||
local Eats = world:entity()
|
||||
local Apples = world:entity()
|
||||
local Oranges = world:entity()
|
||||
local bob = world:entity()
|
||||
|
||||
world:add(bob, pair(Eats, Apples))
|
||||
world:add(bob, pair(Eats, Oranges))
|
||||
|
||||
-- First target is at index 0
|
||||
local first = world:target(bob, Eats, 0)
|
||||
print(first == Apples) -- true
|
||||
|
||||
-- Second target is at index 1
|
||||
local second = world:target(bob, Eats, 1)
|
||||
print(second == Oranges) -- true
|
||||
|
||||
-- No third target: index 2 returns nil
|
||||
local third = world:target(bob, Eats, 2)
|
||||
print(third == nil) -- true
|
||||
|
||||
-- Omitting the index is the same as index 0
|
||||
local default = world:target(bob, Eats)
|
||||
print(default == Apples) -- true
|
||||
58
how_to/043_wildcards.luau
Normal file
58
how_to/043_wildcards.luau
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
--[[
|
||||
Wildcards let you query relationships without specifying the exact target or
|
||||
relationship. jecs.Wildcard matches any entity in that slot.
|
||||
|
||||
- pair(relation, jecs.Wildcard) matches that relationship with any target.
|
||||
- pair(jecs.Wildcard, target) matches any relationship with that target.
|
||||
|
||||
Use world:target(entity, relation, index) to get the actual target when
|
||||
querying with a wildcard. The index is 0-based (see 042_target.luau).
|
||||
]]
|
||||
|
||||
local jecs = require("@jecs")
|
||||
local pair = jecs.pair
|
||||
local world = jecs.world()
|
||||
|
||||
local Eats = world:component() :: jecs.Id<{ amount: number }>
|
||||
local Likes = world:entity()
|
||||
local Apples = world:entity()
|
||||
local alice = world:entity()
|
||||
local bob = world:entity()
|
||||
|
||||
world:add(bob, pair(Eats, Apples))
|
||||
world:set(bob, pair(Eats, Apples), { amount = 1 })
|
||||
world:add(bob, pair(Likes, alice))
|
||||
|
||||
-- world:has with wildcard
|
||||
print(world:has(bob, pair(Eats, jecs.Wildcard))) -- true
|
||||
|
||||
-- Query with wildcard: all entities that eat something
|
||||
for entity in world:query(pair(Eats, jecs.Wildcard)) do
|
||||
local food = world:target(entity, Eats)
|
||||
print(`Entity {entity} eats {food}`)
|
||||
end
|
||||
|
||||
-- Query with wildcard: all entities that like someone
|
||||
for entity in world:query(pair(Likes, jecs.Wildcard)) do
|
||||
local target = world:target(entity, Likes)
|
||||
print(`Entity {entity} likes {target}`)
|
||||
end
|
||||
|
||||
-- Multiple targets: index is 0-based. Iterate until nil.
|
||||
local charlie = world:entity()
|
||||
world:add(bob, pair(Likes, charlie))
|
||||
|
||||
for entity in world:query(pair(Likes, jecs.Wildcard)) do
|
||||
local nth = 0
|
||||
local target = world:target(entity, Likes, nth)
|
||||
while target do
|
||||
print(`Entity {entity} likes {target}`)
|
||||
nth += 1
|
||||
target = world:target(entity, Likes, nth)
|
||||
end
|
||||
end
|
||||
|
||||
-- pair(jecs.Wildcard, target): all relationships that have this target
|
||||
for entity in world:query(pair(jecs.Wildcard, alice)) do
|
||||
print(`Entity {entity} has some relationship with alice`)
|
||||
end
|
||||
Loading…
Reference in a new issue