Cleanup on API plans.
This commit is contained in:
+47
-27
@@ -39,22 +39,27 @@ world = ElementWorld.new
|
|||||||
# this is a custom component
|
# this is a custom component
|
||||||
|
|
||||||
world.component :health do |c|
|
world.component :health do |c|
|
||||||
field :health, int: 100
|
# one of int or float or boolean which use c stuff and generally faster
|
||||||
|
# also allow for bulk operations to be done in hotloops.
|
||||||
allow_redefine [:health]
|
# can use `any` which allows for any ruby value but uses runtime gc etc and so is worse to use performance wise for each entity.
|
||||||
|
field :health, :int, 100 # stored for each entity it is attached to.
|
||||||
|
field :max_health, :int, 100, global: true # stored only once per component
|
||||||
end
|
end
|
||||||
|
|
||||||
world.spawn do |e| # Name is optional
|
world.spawn do |e| # Name is optional
|
||||||
e.tags = [:enemy]
|
e.tags = [:enemy]
|
||||||
|
e.z = 0.5
|
||||||
|
|
||||||
e.position = {x: 100, y: 100} # entities always have a position, even if they don't have a body component, this is useful for rendering and for entities that don't need physics but still need to be positioned in the world
|
e.position = {x: 100, y: 100} # entities always have a position, even if they don't have
|
||||||
|
# a body component, this is useful for rendering and for entities
|
||||||
|
# that don't need physics but still need to be positioned in the world
|
||||||
e.add_component :body do |c|
|
e.add_component :body do |c|
|
||||||
c.shape = :rectangle
|
c.shape = :rectangle
|
||||||
c.size = {width: 50, height: 50}
|
c.size = {width: 50, height: 50}
|
||||||
c.angle = 0
|
c.angle = 0
|
||||||
c.mass = 1
|
c.mass = 1
|
||||||
c.velocity = {x: 0, y: 0}
|
c.velocity = {x: 0, y: 0}
|
||||||
c.collision = true
|
c.collision_layer = 1
|
||||||
end
|
end
|
||||||
e.add_component :sprite do |c|
|
e.add_component :sprite do |c|
|
||||||
tiles = Tiles.from "assets/sprite.png", tile_width: 50, tile_height: 50
|
tiles = Tiles.from "assets/sprite.png", tile_width: 50, tile_height: 50
|
||||||
@@ -76,6 +81,7 @@ end
|
|||||||
|
|
||||||
world.spawn "Trap Preview" do |e|
|
world.spawn "Trap Preview" do |e|
|
||||||
e.position = {x: 0, y: 0}
|
e.position = {x: 0, y: 0}
|
||||||
|
e.z = 0
|
||||||
e.tags = [:trap_preview]
|
e.tags = [:trap_preview]
|
||||||
e.active = false
|
e.active = false
|
||||||
e.add_component :sprite do |c|
|
e.add_component :sprite do |c|
|
||||||
@@ -84,10 +90,12 @@ world.spawn "Trap Preview" do |e|
|
|||||||
c.animations = {idle: animation1}
|
c.animations = {idle: animation1}
|
||||||
c.current_animation = :idle
|
c.current_animation = :idle
|
||||||
end
|
end
|
||||||
# e.remove_component :sprite # compoenents can also be removed
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# systems are called on the world every update frame, some systems are built into the engine for things like physics, rendering, etc, but you can also create your own custom systems for things like trap placement, enemy spawning, etc
|
# systems are called on the world every update frame, some systems
|
||||||
|
# are built into the engine for things like physics, rendering, etc,
|
||||||
|
# but you can also create your own custom systems for things like
|
||||||
|
# trap placement, enemy spawning, etc
|
||||||
|
|
||||||
# systems can be created on queries
|
# systems can be created on queries
|
||||||
# the query can be for compoenents or tags or both
|
# the query can be for compoenents or tags or both
|
||||||
@@ -96,24 +104,27 @@ end
|
|||||||
# for entities it does similarly
|
# for entities it does similarly
|
||||||
# mouse state can be read in systems always
|
# mouse state can be read in systems always
|
||||||
|
|
||||||
query = Query.from(tag(:enemy) & component(:health, true) & anti(name("Trap Preview", true)))
|
query = Query.from(tag(:enemy) & component(:health, capture: true) & anti(name("Trap Preview")))
|
||||||
# in the match name will return just the one entity
|
# in the match name will return just the one entity
|
||||||
# tag and componet return list-like tables but they will be parallel and in order
|
# tag and componet return list-like tables but they will be parallel and in order
|
||||||
# empty columns will be filled with nil (not possible if only & is used)
|
# empty columns will be filled with nil (not possible if only & is used)
|
||||||
# the last part is to show how anti() works
|
# the last part is to show how anti() works
|
||||||
# it doesnt actually do anything as tag(:enemy) and component(:health) will never match name("Trap Preview") but it shows how you can use anti() to negate a query
|
# it doesnt actually do anything as tag(:enemy) and component(:health) will
|
||||||
|
# never match name("Trap Preview") but it shows how you can use anti() to negate a query
|
||||||
|
|
||||||
world.system :health_regen, for: query do |match, dt| # no trigger means always
|
world.system :health_regen, for: query do |match, dt| # no trigger means always
|
||||||
# example of a simple health regeneration system that regenerates health for all entities with a health component
|
# example of a simple health regeneration system that regenerates health for all entities with a health component
|
||||||
healths = query.get[0] # get the first component in the query, in this case health, this will be a list of all health components for entities that match the query
|
healths = match[0] # get the first component in the query, in this case health
|
||||||
healths.add_scalar! :health, 1 * dt
|
# , this will be a list of all health components for
|
||||||
healths.clamp! :health, 0, 100
|
# entities that match the query
|
||||||
|
healths[:health].add! 1 * dt
|
||||||
|
healths[:health].clamp! 0, :max_health
|
||||||
end
|
end
|
||||||
|
|
||||||
trigger = [:place]
|
trigger = Trigger.from(key(:place))
|
||||||
|
|
||||||
world.system :trap_placement, trigger: trigger do |dt|
|
world.system :trap_placement, trigger: trigger do |dt|
|
||||||
return unless world.holding_trap?
|
return unless world.globals.holding_trap?
|
||||||
|
|
||||||
world.spawn do |e|
|
world.spawn do |e|
|
||||||
e.tags = [:trap]
|
e.tags = [:trap]
|
||||||
@@ -126,39 +137,44 @@ world.system :trap_placement, trigger: trigger do |dt|
|
|||||||
c.current_animation = :idle
|
c.current_animation = :idle
|
||||||
end
|
end
|
||||||
e.add_component :body do |c|
|
e.add_component :body do |c|
|
||||||
c.shape = :rectangle
|
|
||||||
c.size = {width: 50, height: 50}
|
c.size = {width: 50, height: 50}
|
||||||
c.angle = 0
|
c.angle = 0
|
||||||
c.mass = 1
|
c.mass = 1
|
||||||
c.velocity = {x: 0, y: 0}
|
c.velocity = {x: 0, y: 0}
|
||||||
c.collision = true
|
c.collision_layer = 0 # layer 0 doesnt collide.
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
name_query = Query.from(name("Trap Preview", true) & component(:sprite, true))
|
name_query = Query.from(name("Trap Preview") & component(:sprite, capture: true))
|
||||||
|
|
||||||
# could be done as so or
|
# could be done as so or
|
||||||
world.system :trap_preview do |match, dt| # example from teh game mist trying to be made with this engine
|
world.system :trap_preview, for: name_query do |dt, matches| # example from the game mist trying to be made with this engine
|
||||||
# do trap placement logic when a trap is held
|
# do trap placement logic when a trap is held
|
||||||
return unless world.holding_trap?
|
return unless world.globals.holding_trap?
|
||||||
# show a preview of the trap at the mouse position, you can use the mouse position relative to the world for this
|
# show a preview of the trap at the mouse position, you can use the mouse position relative to the world for this
|
||||||
e = name_query.get[0] # get the first entity that matches the name query, in this case the trap preview entity, this will be nil if no entity matches
|
e = matches[0] # get the first entity that matches the name query, in
|
||||||
|
# this case the trap preview entity, this will be nil if no entity matches
|
||||||
e.position = world.mouse_position_world
|
e.position = world.mouse_position_world
|
||||||
e.active = true # enable the trap preview entity to show it at the mouse position
|
e.active = true # enable the trap preview entity to show it at the mouse position
|
||||||
end
|
end
|
||||||
|
|
||||||
# OR, this one isnt the exact same but shows that .active works on both entites and components
|
# OR, this one isnt the exact same but shows that .active works on both entites and components
|
||||||
|
|
||||||
world.system :trap_preview, for: name("Trap Preview", true) & component(:sprite, true) do |match, dt|
|
world.system :trap_preview, for: name("Trap Preview", capture: true) & component(:sprite, capture: true) do |dt, matches|
|
||||||
return unless world.holding_trap?
|
return unless world.globals.holding_trap?
|
||||||
# if | was used between teh queries then the arrays would still be parallel but empty rows fit with nil
|
# if | was used between teh queries then the arrays would still be parallel but empty rows fit with nil
|
||||||
# for & between they will always match and so the arrays will always be the same length and so you can just use the first one to set the position of the entity and then use the second one to set the active of the sprite component, etc (without nil check)
|
# for & between they will always match and so the arrays
|
||||||
match.second.each_with_index do |s, i|
|
# will always be the same length and so you can just use
|
||||||
match.first[i].position = world.mouse_position_world
|
# the first one to set the position of the entity and then
|
||||||
|
# use the second one to set the active of the sprite component,
|
||||||
|
# etc (without nil check)
|
||||||
|
matches.second.each_with_index do |s, i|
|
||||||
|
matches.first[i].position = world.mouse_position_world
|
||||||
s.active = true
|
s.active = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
## ------ ##
|
## ------ ##
|
||||||
|
|
||||||
world.shader :fog do |shader|
|
world.shader :fog do |shader|
|
||||||
@@ -174,12 +190,16 @@ world.shader :fog do |shader|
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame do |shader|
|
frame do |shader|
|
||||||
# example of custom shader code for this shader, this is called every frame and is where you would update the shader data based on the current state of the world or whatever
|
# example of custom shader code for this shader, this is called every
|
||||||
|
# frame and is where you would update the shader data based on the
|
||||||
|
# current state of the world or whatever
|
||||||
shader.set_data :time, Time.now.to_f
|
shader.set_data :time, Time.now.to_f
|
||||||
shader.set_data :resolution, {x: width, y: height}
|
shader.set_data :resolution, {x: width, y: height}
|
||||||
end
|
end
|
||||||
|
|
||||||
z = 100 # shaders always appear above normal sprites but z is used to sort them relative to each other, so a shader with z 100 will appear above a shader with z 50, but both will appear above normal sprites
|
z = 100 # shaders always appear above normal sprites but z is used to
|
||||||
|
# sort them relative to each other, so a shader with z 100 will
|
||||||
|
# appear above a shader with z 50, but both will appear above normal sprites
|
||||||
end
|
end
|
||||||
|
|
||||||
App.start menu_scene # first scene to show when the game starts, stops the loading bg
|
App.start menu_scene # first scene to show when the game starts, stops the loading bg
|
||||||
|
|||||||
Reference in New Issue
Block a user