Compare commits

...

7 Commits

Author SHA1 Message Date
9ae6c12582 sprite handling
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
2026-02-21 23:12:46 +01:00
4e35cd4bd3 Merge pull request 'situation handling' (#9) from feature/situation-handling into master
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: http://git.teletype.hu/games/impostor/pulls/9
2026-02-21 21:34:10 +00:00
ed2354b0fa situation handling
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
2026-02-21 22:33:24 +01:00
7854dc8a9f situation handling
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-21 22:33:01 +01:00
3b9b67e2fa Merge pull request 'remove manager postfixes' (#8) from feature-remove-manager-postfixes into master
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: http://git.teletype.hu/games/impostor/pulls/8
2026-02-21 20:36:29 +00:00
1a4565428d remove manager postfixes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
2026-02-21 21:35:48 +01:00
f02bb75e4f Merge pull request 'feat/imp-28-context-minigame-meter-table' (#7) from feat/imp-28-context-minigame-meter-table into master
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: http://git.teletype.hu/games/impostor/pulls/7
2026-02-18 22:24:11 +00:00
27 changed files with 199 additions and 45 deletions

View File

@@ -3,19 +3,24 @@
globals = {
"Util",
"DecisionManager",
"ScreenManager",
"Decision",
"Situation",
"Screen",
"Sprite",
"UI",
"Print",
"Input",
"Audio",
"Context",
"Meters",
"Minigames",
"mset",
"mget",
"btnp",
"keyp",
"music",
"sfx",
"spr",
"rect",
"rectb",
"circ",
@@ -30,7 +35,7 @@ globals = {
"exit",
"trace",
"index_menu",
"MapManager",
"Map",
"map",
}

View File

@@ -5,7 +5,12 @@ init/init.minigames.lua
init/init.meters.lua
system/system.util.lua
init/init.windows.lua
sprite/sprite.manager.lua
sprite/sprite.norman.lua
situation/situation.manager.lua
situation/situation.drink_coffee.lua
decision/decision.manager.lua
decision/decision.have_a_coffee.lua
decision/decision.go_to_home.lua
decision/decision.go_to_toilet.lua
decision/decision.go_to_walking_to_office.lua

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "go_to_home",
label = "Go to Home",
handle = function()

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "go_to_office",
label = "Go to Office",
handle = function()

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "go_to_toilet",
label = "Go to Toilet",
handle = function()

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "go_to_walking_to_home",
label = "Walking to home",
handle = function()

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "go_to_walking_to_office",
label = "Walking to office",
handle = function()

View File

@@ -0,0 +1,8 @@
Decision.register({
id = "have_a_coffee",
label = "Have a Coffee",
handle = function()
Situation.apply("drink_coffee")
end,
condition = function() return true end
})

View File

@@ -1,6 +1,6 @@
local _decisions = {}
function DecisionManager.register(decision)
function Decision.register(decision)
if not decision or not decision.id then
PopupWindow.show({"Error: Invalid decision object registered (missing id)!"})
return
@@ -22,10 +22,10 @@ function DecisionManager.register(decision)
_decisions[decision.id] = decision
end
function DecisionManager.get(id)
function Decision.get(id)
return _decisions[id]
end
function DecisionManager.get_all()
function Decision.get_all()
return _decisions
end

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "play_button_mash",
label = "Play Button Mash",
handle = function() Meters.hide() MinigameButtonMashWindow.start(WINDOW_GAME) end,

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "play_ddr",
label = "Play DDR (Random)",
handle = function() Meters.hide() MinigameDDRWindow.start(WINDOW_GAME, nil) end,

View File

@@ -1,4 +1,4 @@
DecisionManager.register({
Decision.register({
id = "play_rhythm",
label = "Play Rhythm Game",
handle = function() Meters.hide() MinigameRhythmWindow.start(WINDOW_GAME) end,

View File

@@ -45,7 +45,9 @@ on than meets the eye.]]
minigame_ddr = Minigames.get_default_ddr(),
minigame_button_mash = Minigames.get_default_button_mash(),
minigame_rhythm = Minigames.get_default_rhythm(),
meters = Meters.get_initial()
meters = Meters.get_initial(),
sprites = {},
current_situation = nil,
}
end
@@ -67,7 +69,7 @@ local function reset_context_to_initial_state()
Context.screen_indices_by_id = {}
local screen_order = {"home", "toilet", "walking_to_office", "office", "walking_to_home"}
for i, screen_id in ipairs(screen_order) do
local screen_data = ScreenManager.get_by_id(screen_id)
local screen_data = Screen.get_by_id(screen_id)
if screen_data then
table.insert(Context.screens, screen_data)
Context.screen_indices_by_id[screen_id] = i

View File

@@ -11,11 +11,12 @@ local MinigameDDRWindow = {}
Util = {}
Meters = {}
Minigames = {}
DecisionManager = {}
ScreenManager = {}
MapManager = {}
Decision = {}
Situation = {}
Screen = {}
Map = {}
UI = {}
Print = {}
Input = {}
Sprite = {}
Audio = {}

View File

@@ -1,4 +1,4 @@
MapManager.register({
Map.register({
id = "bedroom",
from_x = 0,
from_y = 0,

View File

@@ -1,6 +1,6 @@
local _maps = {}
function MapManager.get_maps_array()
function Map.get_maps_array()
local maps_array = {}
for _, map_data in pairs(_maps) do
table.insert(maps_array, map_data)
@@ -8,19 +8,19 @@ function MapManager.get_maps_array()
return maps_array
end
function MapManager.register(map_data)
function Map.register(map_data)
if _maps[map_data.id] then
trace("Warning: Overwriting map with id: " .. map_data.id)
end
_maps[map_data.id] = map_data
end
function MapManager.get_by_id(map_id)
function Map.get_by_id(map_id)
return _maps[map_id]
end
function MapManager.draw(map_id)
local map_data = MapManager.get_by_id(map_id)
function Map.draw(map_id)
local map_data = Map.get_by_id(map_id)
if not map_data then
return
end

View File

@@ -1,4 +1,4 @@
ScreenManager.register({
Screen.register({
id = "home",
name = "Home",
decisions = {

View File

@@ -1,20 +1,15 @@
local _screens = {}
function ScreenManager.get_screens_array()
local screens_array = {}
for _, screen_data in pairs(_screens) do
table.insert(screens_array, screen_data)
end
return screens_array
end
function ScreenManager.register(screen_data)
function Screen.register(screen_data)
if _screens[screen_data.id] then
trace("Warning: Overwriting screen with id: " .. screen_data.id)
end
if not screen_data.situations then
screen_data.situations = {}
end
_screens[screen_data.id] = screen_data
end
function ScreenManager.get_by_id(screen_id)
function Screen.get_by_id(screen_id)
return _screens[screen_id]
end

View File

@@ -1,4 +1,4 @@
ScreenManager.register({
Screen.register({
id = "office",
name = "Office",
decisions = {
@@ -6,5 +6,9 @@ ScreenManager.register({
"play_rhythm",
"play_ddr",
"go_to_walking_to_home",
}
"have_a_coffee",
},
situations = {
"drink_coffee",
},
})

View File

@@ -1,4 +1,4 @@
ScreenManager.register({
Screen.register({
id = "toilet",
name = "Toilet",
decisions = {

View File

@@ -1,4 +1,4 @@
ScreenManager.register({
Screen.register({
id = "walking_to_home",
name = "Walking to home",
decisions = {

View File

@@ -1,4 +1,4 @@
ScreenManager.register({
Screen.register({
id = "walking_to_office",
name = "Walking to office",
decisions = {

View File

@@ -0,0 +1,7 @@
Situation.register({
id = "drink_coffee",
handle = function()
Audio.sfx_select()
Sprite.show("norman", 100, 100)
end,
})

View File

@@ -0,0 +1,37 @@
local _situations = {}
function Situation.register(situation)
if not situation or not situation.id then
PopupWindow.show({"Error: Invalid situation object registered (missing id)!"})
return
end
if not situation.handle then
situation.handle = function() end
end
if _situations[situation.id] then
trace("Warning: Overwriting situation with id: " .. situation.id)
end
_situations[situation.id] = situation
end
function Situation.get(id)
return _situations[id]
end
function Situation.apply(id)
local situation = Situation.get(id)
if not situation then
trace("Error: No situation found with id: " .. id)
return
end
local current_screen_obj = Screen.get_by_id(Context.current_screen)
if current_screen_obj and not current_screen_obj.situations[id] then
trace("Info: Situation " .. id .. " cannot be applied to current screen (id: " .. Context.current_screen .. ").")
return
end
Context.current_situation = id
situation.handle()
end

View File

@@ -0,0 +1,72 @@
local _sprites = {}
function Sprite.register(sprite_data)
if not sprite_data or not sprite_data.id then
trace("Error: Invalid sprite object registered (missing id)!")
return
end
if _sprites[sprite_data.id] then
trace("Warning: Overwriting sprite with id: " .. sprite_data.id)
end
_sprites[sprite_data.id] = sprite_data
end
function Sprite.show(id, x, y, colorkey, scale, flip_x, flip_y, rot)
-- Ensure the sprite exists before attempting to show it
if not _sprites[id] then
trace("Error: Attempted to show non-registered sprite with id: " .. id)
return
end
Context.sprites[id] = {
id = id,
x = x,
y = y,
colorkey = colorkey,
scale = scale,
flip_x = flip_x,
flip_y = flip_y,
rot = rot,
}
end
function Sprite.hide(id)
Context.sprites[id] = nil
end
function Sprite.draw()
for id, params in pairs(Context.sprites) do
local sprite_data = _sprites[id]
if not sprite_data then
trace("Error: Sprite id " .. id .. " in Context.sprites is not registered.")
Context.sprites[id] = nil -- Clean up invalid entry
-- We should probably continue to the next sprite instead of returning
-- so that other valid sprites can still be drawn.
end
-- Use parameters from Context.sprites, or fall back to sprite_data, then to defaults
local colorkey = params.colorkey or sprite_data.colorkey or 0
local scale = params.scale or sprite_data.scale or 1
local flip_x = params.flip_x or sprite_data.flip_x or 0
local flip_y = params.flip_y or sprite_data.flip_y or 0
local rot = params.rot or sprite_data.rot or 0
if sprite_data.sprites then -- Complex sprite
for i = 1, #sprite_data.sprites do
local sub_sprite = sprite_data.sprites[i]
spr(
sub_sprite.s,
params.x + (sub_sprite.x_offset or 0),
params.y + (sub_sprite.y_offset or 0),
sub_sprite.colorkey or colorkey,
sub_sprite.scale or scale,
sub_sprite.flip_x or flip_x,
sub_sprite.flip_y or flip_y,
sub_sprite.rot or rot
)
end
else -- Simple sprite
spr(sprite_data.s, params.x, params.y, colorkey, scale, flip_x, flip_y, rot)
end
end
end

View File

@@ -0,0 +1,17 @@
Sprite.register({
id = "norman",
sprites = {
-- Body
{ s = 0, x_offset = 0, y_offset = 0 },
-- Head
{ s = 1, x_offset = 0, y_offset = -8 },
-- Left Arm
{ s = 2, x_offset = -4, y_offset = 4 },
-- Right Arm
{ s = 3, x_offset = 4, y_offset = 4, flip_x = 1 }, -- Flipped arm
-- Left Leg
{ s = 4, x_offset = -2, y_offset = 8 },
-- Right Leg
{ s = 5, x_offset = 2, y_offset = 8, flip_x = 1 } -- Flipped leg
}
})

View File

@@ -1,11 +1,11 @@
function GameWindow.draw()
local screen = Context.screens[Context.current_screen]
MapManager.draw(screen.background)
Map.draw(screen.background)
UI.draw_top_bar(screen.name)
if screen and screen.decisions and #screen.decisions > 0 then
local available_decisions = {}
for _, decision_id in ipairs(screen.decisions) do
local decision = DecisionManager.get(decision_id)
local decision = Decision.get(decision_id)
if decision and decision.condition() then
table.insert(available_decisions, decision)
end
@@ -14,6 +14,7 @@ function GameWindow.draw()
UI.draw_decision_selector(available_decisions, Context.selected_decision_index)
end
end
Sprite.draw()
end
function GameWindow.update()
@@ -39,7 +40,7 @@ function GameWindow.update()
if screen and screen.decisions and #screen.decisions > 0 then
local available_decisions = {}
for _, decision_id in ipairs(screen.decisions) do
local decision = DecisionManager.get(decision_id)
local decision = Decision.get(decision_id)
if decision and decision.condition() then table.insert(available_decisions, decision)
end
end