local EventBus = {}
EventBus.__index = EventBus
function EventBus.new()
return setmetatable({ listeners = {} }, EventBus)
end
-- 購読
function EventBus:on(event, callback)
if not self.listeners[event] then
self.listeners[event] = {}
end
table.insert(self.listeners[event], callback)
-- 解除用関数を返す
local removed = false
return function()
if removed then return end
removed = true
self:off(event, callback)
end
end
-- 一度だけ実行
function EventBus:once(event, callback)
local unsubscribe
unsubscribe = self:on(event, function(...)
unsubscribe()
callback(...)
end)
end
-- 購読解除
function EventBus:off(event, callback)
local list = self.listeners[event]
if not list then return end
for i = #list, 1, -1 do
if list[i] == callback then
table.remove(list, i)
break
end
end
end
-- 発行
function EventBus:emit(event, ...)
local list = self.listeners[event]
if not list then return end
for _, callback in ipairs(list) do
callback(...)
end
end
return EventBus
--------------------------------------------------------------------■使い方
local EventBus = require("EventBus")
local bus = EventBus.new()
-- 購読
local unsubscribe = bus:on("player_damage", function(amount)
print("Player damaged:", amount)
end)
-- 発行
bus:emit("player_damage", 10)
-- 解除
unsubscribe()
--------------------------------------------------------------------■一度だけ実行(once)が必要になる場面
1. ゲーム開始時に一度だけ処理したい 例:ロード完了イベントが来たら UI を表示する → 2回目以降は不要 2. 敵が死んだ瞬間に一度だけ演出を入れたい 例:ボスが死んだ瞬間にカットシーン再生 → 何度も呼ばれたら困る 3. プレイヤーが初めてアイテムを拾った時だけチュートリアルを出す → 2回目以降はチュートリアル不要■参考
https://github.com/ThomasKomarnicki/GameEventBus
0 件のコメント:
コメントを投稿