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
|
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)
|
-- Tags are removed using world:remove(entity, component)
|
||||||
|
|
||||||
world:remove(entity, Dead)
|
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.
|
Relationships makes it possible to describe entity graphs natively in ECS.
|
||||||
|
|
||||||
Adding/removing relationships is similar to adding/removing regular components,
|
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
|
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
|
the relationship (e.g. "Eats"), and the second element represents the relationship
|
||||||
target (e.g. "Apples").
|
target (e.g. "Apples").
|
||||||
|
|
@ -36,9 +36,6 @@ world:add(alice, pair(Likes, bob))
|
||||||
-- Test if entity has a relationship pair
|
-- Test if entity has a relationship pair
|
||||||
print(world:has(bob, pair(Eats, Apples))) -- true
|
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
|
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}`)
|
print(`Entity {child} is a child of parent {parent}`)
|
||||||
end
|
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
|
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}`)
|
print(`Child {entity} has position {pos} and health {health}`)
|
||||||
end
|
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.
|
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}`)
|
print(`Entity {entity} eats apples: amount = {eats_data.amount}`)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
-- For wildcard queries and world:target (0-based index), see 042_target.luau and 043_wildcards.luau.
|
||||||
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
|
|
||||||
|
|
|
||||||
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