Compare commits
6 Commits
7697b35336
...
feature/13
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ae1eec48a | |||
| 8921f02821 | |||
| 211af18c26 | |||
| b337ae8516 | |||
| 10316d3075 | |||
| 589b225ab0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ docs
|
|||||||
minify.lua
|
minify.lua
|
||||||
*.tic
|
*.tic
|
||||||
*.zip
|
*.zip
|
||||||
|
NOTES_*
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ globals = {
|
|||||||
"MenuWindow",
|
"MenuWindow",
|
||||||
"GameWindow",
|
"GameWindow",
|
||||||
"PopupWindow",
|
"PopupWindow",
|
||||||
"ConfigurationWindow",
|
"ControlsWindow",
|
||||||
"AudioTestWindow",
|
"AudioTestWindow",
|
||||||
"MinigameButtonMashWindow",
|
"MinigameButtonMashWindow",
|
||||||
"MinigameRhythmWindow",
|
"MinigameRhythmWindow",
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ window/window.intro.title.lua
|
|||||||
window/window.intro.ttg.lua
|
window/window.intro.ttg.lua
|
||||||
window/window.intro.brief.lua
|
window/window.intro.brief.lua
|
||||||
window/window.menu.lua
|
window/window.menu.lua
|
||||||
window/window.configuration.lua
|
window/window.controls.lua
|
||||||
window/window.audiotest.lua
|
window/window.audiotest.lua
|
||||||
window/window.popup.lua
|
window/window.popup.lua
|
||||||
window/window.minigame.mash.lua
|
window/window.minigame.mash.lua
|
||||||
|
|||||||
@@ -144,25 +144,20 @@ function Decision.update(decisions, selected_decision_index)
|
|||||||
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Mouse.clicked() then
|
local bar_h = 16
|
||||||
local mx = Mouse.x()
|
local bar_y = Config.screen.height - bar_h
|
||||||
local my = Mouse.y()
|
local prev_zone = { x = 0, y = bar_y, w = 15, h = bar_h }
|
||||||
local bar_height = 16
|
local next_zone = { x = Config.screen.width-15, y = bar_y, w = 15, h = bar_h }
|
||||||
local bar_y = Config.screen.height - bar_height
|
local confirm_zone = { x = 15, y = bar_y, w = Config.screen.width-30, h = bar_h }
|
||||||
if my >= bar_y then
|
|
||||||
if mx < 15 then
|
if Mouse.zone(prev_zone) then
|
||||||
Audio.sfx_beep()
|
Audio.sfx_beep()
|
||||||
Mouse.consume()
|
selected_decision_index = Util.safeindex(decisions, selected_decision_index - 1)
|
||||||
selected_decision_index = Util.safeindex(decisions, selected_decision_index - 1)
|
elseif Mouse.zone(next_zone) then
|
||||||
elseif mx > Config.screen.width - 15 then
|
Audio.sfx_beep()
|
||||||
Audio.sfx_beep()
|
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
||||||
Mouse.consume()
|
elseif Mouse.zone(confirm_zone) then
|
||||||
selected_decision_index = Util.safeindex(decisions, selected_decision_index + 1)
|
return selected_decision_index, true
|
||||||
else
|
|
||||||
Mouse.consume()
|
|
||||||
return selected_decision_index, true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return selected_decision_index, false
|
return selected_decision_index, false
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ function Context.initial_data()
|
|||||||
return {
|
return {
|
||||||
current_menu_item = 1,
|
current_menu_item = 1,
|
||||||
test_mode = false,
|
test_mode = false,
|
||||||
|
mouse_trace = false,
|
||||||
popup = {
|
popup = {
|
||||||
show = false,
|
show = false,
|
||||||
content = {}
|
content = {}
|
||||||
@@ -46,6 +47,8 @@ function Context.initial_data()
|
|||||||
have_done_work_today = false,
|
have_done_work_today = false,
|
||||||
should_ascend = false,
|
should_ascend = false,
|
||||||
have_met_sumphore = false,
|
have_met_sumphore = false,
|
||||||
|
office_sprites = {},
|
||||||
|
walking_to_office_sprites = {},
|
||||||
game = {
|
game = {
|
||||||
current_screen = "home",
|
current_screen = "home",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,21 +8,43 @@ Screen.register({
|
|||||||
},
|
},
|
||||||
init = function()
|
init = function()
|
||||||
Audio.music_play_room_work()
|
Audio.music_play_room_work()
|
||||||
|
Context.have_been_to_office = true
|
||||||
|
|
||||||
|
local possible_sprites = {
|
||||||
|
"dev_project_manager",
|
||||||
|
"dev_hr_girl",
|
||||||
|
"dev_introvert",
|
||||||
|
"dev_extrovert",
|
||||||
|
"dev_guru",
|
||||||
|
"dev_operator",
|
||||||
|
{id="dev_buddy", y_correct=1 * 8},
|
||||||
|
{id="dev_boy", y_correct=1 * 8},
|
||||||
|
{id="dev_girl", y_correct=1 * 8}
|
||||||
|
}
|
||||||
|
|
||||||
|
local possible_positions = {
|
||||||
|
{x = 6 * 8, y = 4 * 8},
|
||||||
|
{x = 10 * 8, y = 11 * 8 + 4},
|
||||||
|
{x = 12 * 8, y = 4 * 8},
|
||||||
|
{x = 15 * 8, y = 9 * 8},
|
||||||
|
{x = 16 * 8, y = 4 * 8},
|
||||||
|
{x = 17 * 8, y = 8 * 8},
|
||||||
|
{x = 17 * 8, y = 11 * 8},
|
||||||
|
{x = 20 * 8, y = 4 * 8},
|
||||||
|
{x = 23 * 8, y = 5 * 8},
|
||||||
|
{x = 22 * 8, y = 10 * 8 + 4},
|
||||||
|
{x = 27 * 8, y = 10 * 8 + 4},
|
||||||
|
{x = -4 + 5 * 8, y = 9 * 8}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.office_sprites = Sprite.list_randomize(possible_sprites, possible_positions)
|
||||||
end,
|
end,
|
||||||
background = "office",
|
background = "office",
|
||||||
draw = function()
|
draw = function()
|
||||||
if Window.get_current_id() == "game" then
|
if Window.get_current_id() == "game" then
|
||||||
Sprite.draw_at("norman", 13 * 8, 9 * 8)
|
Sprite.draw_at("norman", 13 * 8, 9 * 8)
|
||||||
Sprite.draw_at("dev_buddy", 15 * 8, 9 * 8)
|
|
||||||
Sprite.draw_at("dev_project_manager", 6 * 8, 4 * 8)
|
Sprite.draw_list(Context.office_sprites)
|
||||||
Sprite.draw_at("dev_hr_girl", 12 * 8, 4 * 8)
|
|
||||||
Sprite.draw_at("dev_introvert", -4 + 5 * 8, 9 * 8)
|
|
||||||
Sprite.draw_at("dev_extrovert", 20 * 8, 4 * 8)
|
|
||||||
Sprite.draw_at("dev_girl", 23 * 8, 5 * 8)
|
|
||||||
Sprite.draw_at("dev_boy", 10 * 8, 11 * 8 + 4)
|
|
||||||
Sprite.draw_at("dev_guru", 22 * 8, 10 * 8 + 4)
|
|
||||||
Sprite.draw_at("dev_operator", 27 * 8, 10 * 8 + 4)
|
|
||||||
end
|
end
|
||||||
Context.have_been_to_office = true
|
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,6 +8,28 @@ Screen.register({
|
|||||||
},
|
},
|
||||||
init = function()
|
init = function()
|
||||||
Audio.music_play_room_work()
|
Audio.music_play_room_work()
|
||||||
|
|
||||||
|
local possible_sprites = {
|
||||||
|
"matrix_trinity",
|
||||||
|
"matrix_neo",
|
||||||
|
{id="matrix_oraculum", y_correct=1 * 8},
|
||||||
|
"matrix_architect"
|
||||||
|
}
|
||||||
|
|
||||||
|
local possible_positions = {
|
||||||
|
{x = 5 * 8, y = 11 * 8},
|
||||||
|
{x = 7 * 8, y = 11 * 8},
|
||||||
|
{x = 9 * 8, y = 11 * 8},
|
||||||
|
{x = 11 * 8, y = 11 * 8},
|
||||||
|
{x = 13 * 8, y = 11 * 8},
|
||||||
|
{x = 15 * 8, y = 11 * 8},
|
||||||
|
{x = 18 * 8, y = 11 * 8},
|
||||||
|
{x = 21 * 8, y = 11 * 8},
|
||||||
|
{x = 24 * 8, y = 11 * 8},
|
||||||
|
{x = 27 * 8, y = 11 * 8},
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.walking_to_office_sprites = Sprite.list_randomize(possible_sprites, possible_positions)
|
||||||
end,
|
end,
|
||||||
background = "street",
|
background = "street",
|
||||||
draw = function()
|
draw = function()
|
||||||
@@ -16,10 +38,8 @@ Screen.register({
|
|||||||
Sprite.draw_at("sumphore", 9 * 8, 2 * 8)
|
Sprite.draw_at("sumphore", 9 * 8, 2 * 8)
|
||||||
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
|
Sprite.draw_at("pizza_vendor", 19 * 8, 1 * 8)
|
||||||
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
|
Sprite.draw_at("dev_guard", 22 * 8, 2 * 8)
|
||||||
Sprite.draw_at("matrix_trinity", 5 * 8, 11 * 8)
|
|
||||||
Sprite.draw_at("matrix_neo", 7 * 8, 11 * 8)
|
Sprite.draw_list(Context.walking_to_office_sprites)
|
||||||
Sprite.draw_at("matrix_oraculum", 9 * 8, 12 * 8)
|
|
||||||
Sprite.draw_at("matrix_architect", 11 * 8, 11 * 8)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -73,6 +73,70 @@ function Sprite.generate_table(width, height, starting_s, x_base, y_base, x_step
|
|||||||
return sprites
|
return sprites
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Immediately draws a list of sprites
|
||||||
|
--- @within Sprite
|
||||||
|
--- @param sprite_list table An array of tables, each containing: `id` (string) sprite identifier, `x` (number) x-coordinate, `y` (number) y-coordinate, and optional `colorkey`, `scale`, `flip_x`, `flip_y`, `rot` parameters.
|
||||||
|
function Sprite.draw_list(sprite_list)
|
||||||
|
for _, sprite_info in ipairs(sprite_list) do
|
||||||
|
local sprite_data = _sprites[sprite_info.id]
|
||||||
|
if not sprite_data then
|
||||||
|
trace("Error: Attempted to draw non-registered sprite with id: " .. sprite_info.id)
|
||||||
|
else
|
||||||
|
draw_sprite_instance(sprite_data, sprite_info)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Given a list of sprite IDs (or sprite entries with correction offsets) and a list of possible positions, randomly assigns each sprite to a unique position and returns a drawable list.
|
||||||
|
--- @within Sprite
|
||||||
|
--- @param sprite_ids table An array of sprite identifier values or tables.
|
||||||
|
--- Each entry may be either:
|
||||||
|
--- - string: sprite ID to draw.
|
||||||
|
--- - table: { sprite_id = string, x_correct = number, y_correct = number }.
|
||||||
|
--- @param positions table An array of tables, each containing `x` and `y` fields for possible sprite positions.
|
||||||
|
function Sprite.list_randomize(sprite_ids, positions)
|
||||||
|
if #sprite_ids > #positions then
|
||||||
|
trace("Error: More sprite IDs than available positions in Sprite.draw_randomized")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local shuffled_positions = {}
|
||||||
|
for i, pos in ipairs(positions) do
|
||||||
|
shuffled_positions[i] = pos
|
||||||
|
end
|
||||||
|
for i = #shuffled_positions, 2, -1 do
|
||||||
|
local j = math.random(i)
|
||||||
|
shuffled_positions[i], shuffled_positions[j] = shuffled_positions[j], shuffled_positions[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
local drawable_list = {}
|
||||||
|
for i, sprite_entry in ipairs(sprite_ids) do
|
||||||
|
local sprite_id = sprite_entry
|
||||||
|
local x_correct = 0
|
||||||
|
local y_correct = 0
|
||||||
|
|
||||||
|
if type(sprite_entry) == "table" then
|
||||||
|
sprite_id = sprite_entry.sprite_id or sprite_entry.id
|
||||||
|
x_correct = sprite_entry.x_correct or 0
|
||||||
|
y_correct = sprite_entry.y_correct or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local sprite_data = _sprites[sprite_id]
|
||||||
|
if not sprite_data then
|
||||||
|
trace("Error: Attempted to draw non-registered sprite with id: " .. tostring(sprite_id))
|
||||||
|
else
|
||||||
|
local pos = shuffled_positions[i]
|
||||||
|
table.insert(drawable_list, {
|
||||||
|
id = sprite_id,
|
||||||
|
x = pos.x + x_correct,
|
||||||
|
y = pos.y + y_correct
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return drawable_list
|
||||||
|
end
|
||||||
|
|
||||||
--- Schedules a sprite for drawing.
|
--- Schedules a sprite for drawing.
|
||||||
--- @within Sprite
|
--- @within Sprite
|
||||||
--- @param id string The unique identifier of the sprite.<br/>
|
--- @param id string The unique identifier of the sprite.<br/>
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ local INPUT_KEY_UP = 0
|
|||||||
local INPUT_KEY_DOWN = 1
|
local INPUT_KEY_DOWN = 1
|
||||||
local INPUT_KEY_LEFT = 2
|
local INPUT_KEY_LEFT = 2
|
||||||
local INPUT_KEY_RIGHT = 3
|
local INPUT_KEY_RIGHT = 3
|
||||||
local INPUT_KEY_Y = 7
|
local INPUT_KEY_A = 4
|
||||||
|
local INPUT_KEY_B = 5
|
||||||
local INPUT_KEY_SPACE = 48
|
local INPUT_KEY_SPACE = 48
|
||||||
|
local INPUT_KEY_ENTER = 50
|
||||||
local INPUT_KEY_BACKSPACE = 51
|
local INPUT_KEY_BACKSPACE = 51
|
||||||
|
|
||||||
--- Checks if Up is pressed.
|
--- Checks if Up is pressed.
|
||||||
@@ -21,7 +23,10 @@ function Input.left() return btnp(INPUT_KEY_LEFT) end
|
|||||||
function Input.right() return btnp(INPUT_KEY_RIGHT) end
|
function Input.right() return btnp(INPUT_KEY_RIGHT) end
|
||||||
--- Checks if Select is pressed.
|
--- Checks if Select is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
function Input.select() return btnp(INPUT_KEY_Y) or keyp(INPUT_KEY_SPACE) or Mouse.clicked() end
|
function Input.select() return btnp(INPUT_KEY_A) or keyp(INPUT_KEY_SPACE) or Mouse.clicked() end
|
||||||
--- Checks if Back is pressed.
|
--- Checks if Back is pressed.
|
||||||
--- @within Input
|
--- @within Input
|
||||||
function Input.back() return keyp(INPUT_KEY_BACKSPACE) end
|
function Input.back() return btnp(INPUT_KEY_B) or keyp(INPUT_KEY_BACKSPACE) end
|
||||||
|
--- Checks if Enter is pressed.
|
||||||
|
--- @within Input
|
||||||
|
function Input.enter() return keyp(INPUT_KEY_ENTER) end
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ function Mouse.update()
|
|||||||
_consumed = false
|
_consumed = false
|
||||||
local mt = {mouse()}
|
local mt = {mouse()}
|
||||||
_mx, _my, _mleft = mt[1], mt[2], mt[3]
|
_mx, _my, _mleft = mt[1], mt[2], mt[3]
|
||||||
|
|
||||||
|
-- trace mouse position and tile for testing purposes
|
||||||
|
if Context.test_mode and Context.mouse_trace then
|
||||||
|
trace("Mouse: (" .. _mx .. "," .. _my .. "), tile: (" .. math.floor(_mx / 8) .. "," .. math.floor(_my / 8) .. ")")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns current mouse X position.
|
--- Returns current mouse X position.
|
||||||
@@ -41,3 +46,36 @@ function Mouse.consume() _consumed = true end
|
|||||||
function Mouse.in_rect(x, y, w, h)
|
function Mouse.in_rect(x, y, w, h)
|
||||||
return _mx >= x and _mx < x + w and _my >= y and _my < y + h
|
return _mx >= x and _mx < x + w and _my >= y and _my < y + h
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns true if the mouse is within the given circle.
|
||||||
|
--- @within Mouse
|
||||||
|
--- @param cx number Center x.
|
||||||
|
--- @param cy number Center y.
|
||||||
|
--- @param r number Radius.
|
||||||
|
function Mouse.in_circle(cx, cy, r)
|
||||||
|
local dx = _mx - cx
|
||||||
|
local dy = _my - cy
|
||||||
|
return (dx * dx + dy * dy) <= (r * r)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns true if the mouse was clicked inside the given rectangle, and consumes the click.
|
||||||
|
--- @within Mouse
|
||||||
|
--- @param rect table A table with fields: x, y, w, h.
|
||||||
|
function Mouse.zone(rect)
|
||||||
|
if Mouse.clicked() and Mouse.in_rect(rect.x, rect.y, rect.w, rect.h) then
|
||||||
|
Mouse.consume()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns true if the mouse was clicked inside the given circle, and consumes the click.
|
||||||
|
--- @within Mouse
|
||||||
|
--- @param circle table A table with fields: x, y, r.
|
||||||
|
function Mouse.zone_circle(circle)
|
||||||
|
if Mouse.clicked() and Mouse.in_circle(circle.x, circle.y, circle.r) then
|
||||||
|
Mouse.consume()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ function Print.text(text, x, y, color, fixed, scale)
|
|||||||
local shadow_color = Config.colors.black
|
local shadow_color = Config.colors.black
|
||||||
if color == shadow_color then shadow_color = Config.colors.light_grey end
|
if color == shadow_color then shadow_color = Config.colors.light_grey end
|
||||||
scale = scale or 1
|
scale = scale or 1
|
||||||
print(text, x + 1, y + 1, shadow_color, fixed, scale)
|
print(text, x + scale, y + scale, shadow_color, fixed, scale)
|
||||||
print(text, x, y, color, fixed, scale)
|
print(text, x, y, color, fixed, scale)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ end
|
|||||||
--- @param[opt] scale number The scaling factor.<br/>
|
--- @param[opt] scale number The scaling factor.<br/>
|
||||||
function Print.text_center(text, x, y, color, fixed, scale)
|
function Print.text_center(text, x, y, color, fixed, scale)
|
||||||
scale = scale or 1
|
scale = scale or 1
|
||||||
local text_width = print(text, 0, -6, 0, fixed, scale)
|
local text_width = print(text, 0, -6 * scale, 0, fixed, scale)
|
||||||
local centered_x = x - (text_width / 2)
|
local centered_x = x - (text_width / 2)
|
||||||
Print.text(text, centered_x, y, color, fixed, scale)
|
Print.text(text, centered_x, y, color, fixed, scale)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -58,9 +58,7 @@ function UI.update_menu(items, selected_item, x, y, centered)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if x ~= nil and y ~= nil and Mouse.clicked() then
|
if x ~= nil and y ~= nil then
|
||||||
local mx = Mouse.x()
|
|
||||||
local my = Mouse.y()
|
|
||||||
local menu_x = x
|
local menu_x = x
|
||||||
if centered then
|
if centered then
|
||||||
local max_w = 0
|
local max_w = 0
|
||||||
@@ -71,9 +69,7 @@ function UI.update_menu(items, selected_item, x, y, centered)
|
|||||||
menu_x = (Config.screen.width - max_w) / 2
|
menu_x = (Config.screen.width - max_w) / 2
|
||||||
end
|
end
|
||||||
for i, _ in ipairs(items) do
|
for i, _ in ipairs(items) do
|
||||||
local item_y = y + (i - 1) * 10
|
if Mouse.zone({ x = menu_x - 8, y = y + (i-1) * 10, w = Config.screen.width, h = 10 }) then
|
||||||
if my >= item_y and my < item_y + 10 and mx >= menu_x - 8 then
|
|
||||||
Mouse.consume()
|
|
||||||
return i, true
|
return i, true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
--- @section ConfigurationWindow
|
|
||||||
ConfigurationWindow.controls = {}
|
|
||||||
ConfigurationWindow.selected_control = 1
|
|
||||||
|
|
||||||
--- Initializes configuration window.
|
|
||||||
--- @within ConfigurationWindow
|
|
||||||
function ConfigurationWindow.init()
|
|
||||||
ConfigurationWindow.controls = {
|
|
||||||
{
|
|
||||||
label = "Save",
|
|
||||||
action = function() Config.save() end,
|
|
||||||
type = "action_item"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label = "Restore Defaults",
|
|
||||||
action = function() Config.reset() end,
|
|
||||||
type = "action_item"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Draws configuration window.
|
|
||||||
--- @within ConfigurationWindow
|
|
||||||
function ConfigurationWindow.draw()
|
|
||||||
UI.draw_top_bar("Configuration")
|
|
||||||
|
|
||||||
local x_start = 10
|
|
||||||
local y_start = 40
|
|
||||||
local x_value_right_align = Config.screen.width - 10
|
|
||||||
local char_width = 4
|
|
||||||
for i, control in ipairs(ConfigurationWindow.controls) do
|
|
||||||
local current_y = y_start + (i - 1) * 12
|
|
||||||
local color = Config.colors.light_blue
|
|
||||||
if control.type == "numeric_stepper" then
|
|
||||||
local value = control.get()
|
|
||||||
local label_text = control.label
|
|
||||||
local value_text = string.format(control.format, value)
|
|
||||||
local value_x = x_value_right_align - (#value_text * char_width)
|
|
||||||
|
|
||||||
if i == ConfigurationWindow.selected_control then
|
|
||||||
color = Config.colors.item
|
|
||||||
Print.text("<", x_start - 8, current_y, color)
|
|
||||||
Print.text(label_text, x_start, current_y, color)
|
|
||||||
Print.text(value_text, value_x, current_y, color)
|
|
||||||
Print.text(">", x_value_right_align + 4, current_y, color)
|
|
||||||
else
|
|
||||||
Print.text(label_text, x_start, current_y, color)
|
|
||||||
Print.text(value_text, value_x, current_y, color)
|
|
||||||
end
|
|
||||||
elseif control.type == "action_item" then
|
|
||||||
local label_text = control.label
|
|
||||||
if i == ConfigurationWindow.selected_control then
|
|
||||||
color = Config.colors.item
|
|
||||||
Print.text("<", x_start - 8, current_y, color)
|
|
||||||
Print.text(label_text, x_start, current_y, color)
|
|
||||||
Print.text(">", x_start + 8 + (#label_text * char_width) + 4, current_y, color)
|
|
||||||
else
|
|
||||||
Print.text(label_text, x_start, current_y, color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Print.text("Press B to go back", x_start, 120, Config.colors.light_grey)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Updates configuration window logic.
|
|
||||||
--- @within ConfigurationWindow
|
|
||||||
function ConfigurationWindow.update()
|
|
||||||
if Input.back() then
|
|
||||||
GameWindow.set_state("menu")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if Input.up() then
|
|
||||||
ConfigurationWindow.selected_control = ConfigurationWindow.selected_control - 1
|
|
||||||
if ConfigurationWindow.selected_control < 1 then
|
|
||||||
ConfigurationWindow.selected_control = #ConfigurationWindow.controls
|
|
||||||
end
|
|
||||||
elseif Input.down() then
|
|
||||||
ConfigurationWindow.selected_control = ConfigurationWindow.selected_control + 1
|
|
||||||
if ConfigurationWindow.selected_control > #ConfigurationWindow.controls then
|
|
||||||
ConfigurationWindow.selected_control = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local control = ConfigurationWindow.controls[ConfigurationWindow.selected_control]
|
|
||||||
if control then
|
|
||||||
if control.type == "numeric_stepper" then
|
|
||||||
local current_value = control.get()
|
|
||||||
if Input.left() then
|
|
||||||
local new_value = math.max(control.min, current_value - control.step)
|
|
||||||
control.set(new_value)
|
|
||||||
elseif Input.right() then
|
|
||||||
local new_value = math.min(control.max, current_value + control.step)
|
|
||||||
control.set(new_value)
|
|
||||||
end
|
|
||||||
elseif control.type == "action_item" then
|
|
||||||
if Input.select() then
|
|
||||||
control.action()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
44
inc/window/window.controls.lua
Normal file
44
inc/window/window.controls.lua
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
--- @section ControlsWindow
|
||||||
|
local _controls = {
|
||||||
|
{ action = "Navigate", keyboard = "Arrow keys", gamepad = "D-pad" },
|
||||||
|
{ action = "Select / OK", keyboard = "Space", gamepad = "Z button" },
|
||||||
|
{ action = "Back", keyboard = "Backspace", gamepad = "B button" },
|
||||||
|
{ action = "Click", keyboard = "Mouse", gamepad = "" },
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Draws the controls window.
|
||||||
|
--- @within ControlsWindow
|
||||||
|
function ControlsWindow.draw()
|
||||||
|
UI.draw_top_bar("Controls")
|
||||||
|
|
||||||
|
local col_action = 4
|
||||||
|
local col_keyboard = 80
|
||||||
|
local col_gamepad = 170
|
||||||
|
local row_h = 10
|
||||||
|
local y_header = 18
|
||||||
|
local y_start = 30
|
||||||
|
|
||||||
|
Print.text("Action", col_action, y_header, Config.colors.light_grey)
|
||||||
|
Print.text("Keyboard", col_keyboard, y_header, Config.colors.light_grey)
|
||||||
|
Print.text("Gamepad", col_gamepad, y_header, Config.colors.light_grey)
|
||||||
|
line(col_action, y_header + 8, Config.screen.width - 4, y_header + 8, Config.colors.dark_grey)
|
||||||
|
|
||||||
|
for i, entry in ipairs(_controls) do
|
||||||
|
local y = y_start + (i - 1) * row_h
|
||||||
|
Print.text(entry.action, col_action, y, Config.colors.white)
|
||||||
|
Print.text(entry.keyboard, col_keyboard, y, Config.colors.light_blue)
|
||||||
|
if entry.gamepad ~= "" then
|
||||||
|
Print.text(entry.gamepad, col_gamepad, y, Config.colors.light_blue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Print.text("Space / Z button or click to go back", col_action, Config.screen.height - 10, Config.colors.light_grey)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Updates the controls window logic.
|
||||||
|
--- @within ControlsWindow
|
||||||
|
function ControlsWindow.update()
|
||||||
|
if Input.back() or Input.select() then
|
||||||
|
Window.set_current("menu")
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -27,8 +27,8 @@ function TTGIntroWindow.update()
|
|||||||
TTGIntroWindow.glitch_started = true
|
TTGIntroWindow.glitch_started = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Count menu_back presses during the intro
|
-- Count enter presses during the intro
|
||||||
if Input.back() then
|
if Input.enter() then
|
||||||
TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1
|
TTGIntroWindow.space_count = TTGIntroWindow.space_count + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,62 @@
|
|||||||
--- @section MenuWindow
|
--- @section MenuWindow
|
||||||
local _menu_items = {}
|
local _menu_items = {}
|
||||||
local _click_timer = 0
|
local _click_timer = 0
|
||||||
|
local _anim = 0
|
||||||
|
local _menu_max_w = 0
|
||||||
|
local ANIM_SPEED = 2.5
|
||||||
|
local HEADER_H = 28
|
||||||
|
|
||||||
|
--- Calculates the animated x position of the menu block.
|
||||||
|
--- @within MenuWindow
|
||||||
|
--- @return number x The left edge x coordinate for the menu.
|
||||||
|
function MenuWindow.calc_menu_x()
|
||||||
|
local center_start = Config.screen.width / 2
|
||||||
|
local center_end = Config.screen.width * 0.72
|
||||||
|
local center = center_start + _anim * (center_end - center_start)
|
||||||
|
return math.floor(center - _menu_max_w / 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Draws the header with title and separator.
|
||||||
|
--- @within MenuWindow
|
||||||
|
function MenuWindow.draw_header()
|
||||||
|
rect(0, 0, Config.screen.width, HEADER_H, Config.colors.dark_grey)
|
||||||
|
rect(0, HEADER_H - 2, Config.screen.width, 2, Config.colors.light_blue)
|
||||||
|
|
||||||
|
local cx = Config.screen.width / 2
|
||||||
|
local subtitle = "Definitely not an"
|
||||||
|
if Context.test_mode then subtitle = subtitle .. " [TEST]" end
|
||||||
|
local sub_w = print(subtitle, 0, -6, 0, false, 1, true)
|
||||||
|
print(subtitle, math.floor(cx - sub_w / 2) + 1, 5, Config.colors.dark_grey, false, 1, true)
|
||||||
|
print(subtitle, math.floor(cx - sub_w / 2), 4, Config.colors.light_grey, false, 1, true)
|
||||||
|
|
||||||
|
Print.text_center("IMPOSTOR", cx, 12, Config.colors.item, false, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Draws the 4x scaled Norman sprite on the left side of the screen.
|
||||||
|
--- @within MenuWindow
|
||||||
|
function MenuWindow.draw_norman()
|
||||||
|
local nx = math.floor(Config.screen.width * 0.45 / 2) - 32
|
||||||
|
local ny = HEADER_H + math.floor((Config.screen.height - HEADER_H - 96) / 2)
|
||||||
|
spr(272, nx, ny, 0, 4)
|
||||||
|
spr(273, nx + 32, ny, 0, 4)
|
||||||
|
spr(288, nx, ny + 32, 0, 4)
|
||||||
|
spr(289, nx + 32, ny + 32, 0, 4)
|
||||||
|
spr(304, nx, ny + 64, 0, 4)
|
||||||
|
spr(305, nx + 32, ny + 64, 0, 4)
|
||||||
|
end
|
||||||
|
|
||||||
--- Draws the menu window.
|
--- Draws the menu window.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.draw()
|
function MenuWindow.draw()
|
||||||
local title = "Definitely not an Impostor"
|
MenuWindow.draw_header()
|
||||||
if Context.test_mode then
|
|
||||||
title = title .. " (TEST MODE)"
|
if _anim > 0 then
|
||||||
|
MenuWindow.draw_norman()
|
||||||
end
|
end
|
||||||
UI.draw_top_bar(title)
|
|
||||||
|
|
||||||
local menu_h = #_menu_items * 10
|
local menu_h = #_menu_items * 10
|
||||||
local y = 10 + (Config.screen.height - 10 - 10 - menu_h) / 2
|
local y = HEADER_H + math.floor((Config.screen.height - HEADER_H - 10 - menu_h) / 2)
|
||||||
UI.draw_menu(_menu_items, Context.current_menu_item, 0, y, true)
|
UI.draw_menu(_menu_items, Context.current_menu_item, MenuWindow.calc_menu_x(), y, false)
|
||||||
|
|
||||||
local ttg_text = "TTG"
|
local ttg_text = "TTG"
|
||||||
local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false)
|
local ttg_w = print(ttg_text, 0, -10, 0, false, 1, false)
|
||||||
@@ -23,8 +66,12 @@ end
|
|||||||
--- Updates the menu window logic.
|
--- Updates the menu window logic.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.update()
|
function MenuWindow.update()
|
||||||
|
if _anim < 1 then
|
||||||
|
_anim = math.min(1, _anim + ANIM_SPEED * Context.delta_time)
|
||||||
|
end
|
||||||
|
|
||||||
local menu_h = #_menu_items * 10
|
local menu_h = #_menu_items * 10
|
||||||
local y = 10 + (Config.screen.height - 10 - 10 - menu_h) / 2
|
local y = HEADER_H + math.floor((Config.screen.height - HEADER_H - 10 - menu_h) / 2)
|
||||||
|
|
||||||
if _click_timer > 0 then
|
if _click_timer > 0 then
|
||||||
_click_timer = _click_timer - Context.delta_time
|
_click_timer = _click_timer - Context.delta_time
|
||||||
@@ -38,7 +85,7 @@ function MenuWindow.update()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local new_item, mouse_confirmed = UI.update_menu(_menu_items, Context.current_menu_item, 0, y, true)
|
local new_item, mouse_confirmed = UI.update_menu(_menu_items, Context.current_menu_item, MenuWindow.calc_menu_x(), y, false)
|
||||||
Context.current_menu_item = new_item
|
Context.current_menu_item = new_item
|
||||||
|
|
||||||
if mouse_confirmed then
|
if mouse_confirmed then
|
||||||
@@ -84,11 +131,10 @@ function MenuWindow.exit()
|
|||||||
exit()
|
exit()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Opens the configuration menu.
|
--- Opens the controls screen.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.configuration()
|
function MenuWindow.controls()
|
||||||
ConfigurationWindow.init()
|
Window.set_current("controls")
|
||||||
GameWindow.set_state("configuration")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Opens the audio test menu.
|
--- Opens the audio test menu.
|
||||||
@@ -105,7 +151,7 @@ function MenuWindow.continued()
|
|||||||
GameWindow.set_state("continued")
|
GameWindow.set_state("continued")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Opens the minigame ddr test menu.
|
--- Opens the DDR minigame test.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.ddr_test()
|
function MenuWindow.ddr_test()
|
||||||
AudioTestWindow.init()
|
AudioTestWindow.init()
|
||||||
@@ -113,27 +159,34 @@ function MenuWindow.ddr_test()
|
|||||||
MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" })
|
MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" })
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Refreshes menu items.
|
--- Refreshes the list of menu items based on current game state.
|
||||||
--- @within MenuWindow
|
--- @within MenuWindow
|
||||||
function MenuWindow.refresh_menu_items()
|
function MenuWindow.refresh_menu_items()
|
||||||
_menu_items = {}
|
_menu_items = {}
|
||||||
if Context.game_in_progress then
|
if Context.game_in_progress then
|
||||||
table.insert(_menu_items, {label = "Resume Game", decision = MenuWindow.resume_game})
|
table.insert(_menu_items, {label = "Resume Game", decision = MenuWindow.resume_game})
|
||||||
table.insert(_menu_items, {label = "Save Game", decision = MenuWindow.save_game})
|
table.insert(_menu_items, {label = "Save Game", decision = MenuWindow.save_game})
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(_menu_items, {label = "New Game", decision = MenuWindow.new_game})
|
table.insert(_menu_items, {label = "New Game", decision = MenuWindow.new_game})
|
||||||
table.insert(_menu_items, {label = "Load Game", decision = MenuWindow.load_game})
|
table.insert(_menu_items, {label = "Load Game", decision = MenuWindow.load_game})
|
||||||
table.insert(_menu_items, {label = "Configuration", decision = MenuWindow.configuration})
|
table.insert(_menu_items, {label = "Controls", decision = MenuWindow.controls})
|
||||||
|
|
||||||
if Context.test_mode then
|
if Context.test_mode then
|
||||||
table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test})
|
table.insert(_menu_items, {label = "Audio Test", decision = MenuWindow.audio_test})
|
||||||
table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued})
|
table.insert(_menu_items, {label = "To Be Continued...", decision = MenuWindow.continued})
|
||||||
table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test})
|
table.insert(_menu_items, {label = "DDR Test", decision = MenuWindow.ddr_test})
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit})
|
table.insert(_menu_items, {label = "Exit", decision = MenuWindow.exit})
|
||||||
|
|
||||||
|
_menu_max_w = 0
|
||||||
|
for _, item in ipairs(_menu_items) do
|
||||||
|
local w = print(item.label, 0, -10, 0, false, 1, false)
|
||||||
|
if w > _menu_max_w then _menu_max_w = w end
|
||||||
|
end
|
||||||
|
|
||||||
Context.current_menu_item = 1
|
Context.current_menu_item = 1
|
||||||
_click_timer = 0
|
_click_timer = 0
|
||||||
|
_anim = 0
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -355,14 +355,9 @@ function MinigameDDRWindow.update()
|
|||||||
right = Input.right()
|
right = Input.right()
|
||||||
}
|
}
|
||||||
|
|
||||||
if Mouse.clicked() then
|
for _, target in ipairs(mg.target_arrows) do
|
||||||
local mx = Mouse.x()
|
if Mouse.zone({ x = target.x, y = mg.target_y, w = mg.arrow_size, h = mg.arrow_size }) then
|
||||||
local my = Mouse.y()
|
input_map[target.dir] = true
|
||||||
for _, target in ipairs(mg.target_arrows) do
|
|
||||||
if mx >= target.x and mx < target.x + mg.arrow_size and
|
|
||||||
my >= mg.target_y and my < mg.target_y + mg.arrow_size then
|
|
||||||
input_map[target.dir] = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -83,12 +83,7 @@ function MinigameButtonMashWindow.update()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local mouse_on_button = false
|
local mouse_on_button = Mouse.zone_circle({ x = mg.button_x, y = mg.button_y, r = mg.button_size })
|
||||||
if Mouse.clicked() then
|
|
||||||
local dx = Mouse.x() - mg.button_x
|
|
||||||
local dy = Mouse.y() - mg.button_y
|
|
||||||
mouse_on_button = (dx * dx + dy * dy) <= (mg.button_size * mg.button_size)
|
|
||||||
end
|
|
||||||
|
|
||||||
if Input.select() or mouse_on_button then
|
if Input.select() or mouse_on_button then
|
||||||
Audio.sfx_drum_high()
|
Audio.sfx_drum_high()
|
||||||
|
|||||||
@@ -95,12 +95,7 @@ function MinigameRhythmWindow.update()
|
|||||||
if mg.press_cooldown > 0 then
|
if mg.press_cooldown > 0 then
|
||||||
mg.press_cooldown = mg.press_cooldown - 1
|
mg.press_cooldown = mg.press_cooldown - 1
|
||||||
end
|
end
|
||||||
local mouse_on_button = false
|
local mouse_on_button = Mouse.zone_circle({ x = mg.button_x, y = mg.button_y, r = mg.button_size })
|
||||||
if Mouse.clicked() then
|
|
||||||
local dx = Mouse.x() - mg.button_x
|
|
||||||
local dy = Mouse.y() - mg.button_y
|
|
||||||
mouse_on_button = (dx * dx + dy * dy) <= (mg.button_size * mg.button_size)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (Input.select() or mouse_on_button) and mg.press_cooldown == 0 then
|
if (Input.select() or mouse_on_button) and mg.press_cooldown == 0 then
|
||||||
mg.button_pressed_timer = mg.button_press_duration
|
mg.button_pressed_timer = mg.button_press_duration
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ Window.register("game", GameWindow)
|
|||||||
PopupWindow = {}
|
PopupWindow = {}
|
||||||
Window.register("popup", PopupWindow)
|
Window.register("popup", PopupWindow)
|
||||||
|
|
||||||
ConfigurationWindow = {}
|
ControlsWindow = {}
|
||||||
Window.register("configuration", ConfigurationWindow)
|
Window.register("controls", ControlsWindow)
|
||||||
|
|
||||||
AudioTestWindow = {}
|
AudioTestWindow = {}
|
||||||
Window.register("audiotest", AudioTestWindow)
|
Window.register("audiotest", AudioTestWindow)
|
||||||
|
|||||||
Reference in New Issue
Block a user