Commit 9ab384d0 authored by Delisa Mason's avatar Delisa Mason

feat: Add trigger system

Links map object properties to scripts to trigger behavior.
parent 64f47124
This diff is collapsed.
local hooks = {}
function hooks:update()
if self:property('state') == 'remove' then
return
end
local switch1 = self:lookup_object('room1-switch1')
if switch1.state == 'on' then
self:set_property('state', 'remove')
end
end
return hooks
local hooks = {}
function hooks:action()
if self:property('state') == 'off' then
self:set_property('state', 'on')
else
self:set_property('state', 'off')
end
end
return hooks
--[[
Load action hooks for an object in a map
]]
return function(level_index, map)
local level_name = string.format("level%02d", level_index)
local function add_helpers(name, hooks)
function hooks:property(prop_name)
local layer = map.layers['sprites']
return layer.triggers[name][prop_name]
end
function hooks:set_property(prop_name, value)
local layer = map.layers['sprites']
layer.triggers[name][prop_name] = value
end
function hooks:lookup_targets()
local layer = map.layers['sprites']
local data = layer.triggers[name].targets
if data then
local targets = {}
for target in string.gmatch(data, "[^%W]+") do
table.insert(targets, self:lookup_object(target))
end
return targets
end
end
function hooks:lookup_object(id)
return map.layers['sprites'].triggers[id]
end
end
local loader = {}
function loader:load_hooks(name)
local path = 'game.assets.maps.' .. level_name .. '.' .. name
local status, hooks = pcall(require, path)
if status then
add_helpers(name, hooks)
return hooks
end
return nil
end
return loader
end
local sti = require 'lib.sti'
local Player = require 'game.objects.player'
local function load_map_objects(map, player)
map:addCustomLayer("sprites", 3)
local sprite_layer = map.layers["sprites"]
sprite_layer.player = player
sprite_layer.triggers = {}
for _, trigger in ipairs(map.layers['triggers'].objects) do
sprite_layer.triggers[trigger.name] = {
type = trigger.type,
name = trigger.name,
x = trigger.x,
y = trigger.y,
w = trigger.width,
h = trigger.height,
}
for k,v in pairs(trigger.properties) do
sprite_layer.triggers[trigger.name][k] = v
end
end
function sprite_layer:draw()
for _, trigger in pairs(self.triggers) do
if trigger.type == 'door' then
love.graphics.setColor(80, 0, 5)
love.graphics.rectangle('fill', trigger.x, trigger.y, trigger.w, trigger.h)
elseif trigger.type == 'switch' then
if trigger.state == 'off' then
love.graphics.setColor(0, 0, 0)
else
love.graphics.setColor(255, 255, 255)
end
love.graphics.rectangle('fill', trigger.x, trigger.y, trigger.w, trigger.h)
end
end
love.graphics.setColor(255, 255, 255)
local obj = self.player
local x = math.floor(obj.x)
local y = math.floor(obj.y)
love.graphics.draw(obj.sprite.image, obj.sprite.quads[obj.facing], x, y)
end
end
return function(map_path)
local map = sti(map_path)
local player = Player(map.layers["player"], 1)
load_map_objects(map, player)
return { map = map, player = player }
end
local sti = require 'lib.sti'
local RenderMapSystem = require 'game.systems.render_map'
local PlayerInputSystem = require 'game.systems.player_input'
local MovementSystem = require 'game.systems.movement'
local Player = require 'game.objects.player'
local TriggerSystem = require 'game.systems.trigger'
local MapLoader = require 'game.map_loader'
local HooksLoader = require 'game.hooks_loader'
local function load_map_objects(map, player)
map:addCustomLayer("sprites", 3)
local sprite_layer = map.layers["sprites"]
sprite_layer.player = player
function sprite_layer:draw()
local obj = self.player
local x = math.floor(obj.x)
local y = math.floor(obj.y)
love.graphics.draw(obj.sprite.image, obj.sprite.quads[obj.facing], x, y)
end
end
local systems
local state = {}
local levelstate = {}
function state:enter(_, map_path)
levelstate.map = sti(map_path)
levelstate.player = Player(levelstate.map.layers["player"], 1)
load_map_objects(levelstate.map, levelstate.player)
systems = require 'game.systems'
systems.add(PlayerInputSystem())
systems.add(RenderMapSystem())
systems.add(MovementSystem(levelstate.player, levelstate.map))
function state:enter(_, level_index)
self.level_index = level_index
local map_path = string.format("game/assets/maps/level%02d/init.lua", level_index)
self.levelstate = MapLoader(map_path)
self.hooks_loader = HooksLoader(level_index, self.levelstate.map)
self.systems = require 'game.systems'
self.systems.add(PlayerInputSystem())
self.systems.add(RenderMapSystem())
self.systems.add(MovementSystem(self.levelstate.player, self.levelstate.map))
self.systems.add(TriggerSystem(self.hooks_loader))
end
function state:draw()
local dt = love.timer.getDelta()
systems.draw(levelstate, dt)
self.systems.draw(self.levelstate, dt)
end
function state:update(dt)
systems.update(levelstate, dt)
self.systems.update(self.levelstate, dt)
end
function state:keydown(key, code)
......
......@@ -22,7 +22,7 @@ end
function state:keyreleased(key, code)
if key == 'space' then
Gamestate.push(LevelState, 'game/assets/maps/level01.lua')
Gamestate.push(LevelState, 1)
end
end
......
......@@ -3,7 +3,7 @@ local systems = {}
-- Loop over every system, invoking a function by name if present
local function system_func(name, ...)
for i, system in ipairs(systems) do
if type(system) == 'table' and type(system[name]) == 'function' then
if type(system[name]) == 'function' then
system[name](...)
end
end
......
......@@ -13,20 +13,30 @@ return function (player, map)
world:add(obj, obj.x, obj.y, obj.width, obj.height)
end
end
for _, obj in pairs(map.layers["sprites"].triggers) do
world:add(obj, obj.x, obj.y, obj.w, obj.h)
end
function system.update(levelstate, dt)
for _, obj in pairs(levelstate.map.layers["sprites"].triggers) do
if obj.type ~= nil and obj.state == 'remove' then
world:remove(obj)
obj.state = 'deleted'
obj.type = nil
end
end
if levelstate.player.velocity.dx ~= 0 or levelstate.player.velocity.dy ~= 0 then
local entity = levelstate.player
local goalX = entity.x + entity.velocity.dx
local goalY = entity.y + entity.velocity.dy
local actualX, actualY, _, _ = world:move(entity, goalX, goalY)
local actualX, actualY, cols, _ = world:move(entity, goalX, goalY)
entity.x = actualX
entity.y = actualY
entity.collisions = cols
end
end
system.bumpWorld = world
return system
end
......@@ -39,6 +39,7 @@ return function()
function system.postUpdate(levelstate, dt)
levelstate.player.velocity.dx = 0
levelstate.player.velocity.dy = 0
levelstate.player.action = false
end
return system
......
return function (hooks_loader)
local system = { trigger_cooldown = 0 }
local function run_action_hook(target)
local hooks = hooks_loader:load_hooks(target.name)
if hooks ~= nil then
hooks:action()
if target.targets ~= nil then
for t in string.gmatch(target.targets, "[^,]+") do
local thooks = hooks_loader:load_hooks(t)
thooks:update()
end
end
end
end
function system.update(levelstate, dt)
system.trigger_cooldown = system.trigger_cooldown - dt
local p = levelstate.player
if p.collisions ~= nil and #p.collisions > 0 and p.action then
for _, col in ipairs(p.collisions) do
if col.other.actionable and system.trigger_cooldown <= 0 then
system.trigger_cooldown = 0.25
run_action_hook(col.other)
end
end
end
end
return system
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment