Compare commits

...

11 Commits

34 changed files with 1484 additions and 193 deletions

2
.gitignore vendored
View File

@@ -111,4 +111,4 @@ flycheck_*.el
# Swap Files # # Swap Files #
.*.kate-swp .*.kate-swp
.swp.* .swp.*
.kateproject*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

BIN
assets/imgs/tchcmp1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -87,13 +87,14 @@ function love.draw()
Fade:draw() Fade:draw()
if Debug then if Debug then
love.graphics.setColor(0, 0, 0) -- love.graphics.setColor(0, 0, 0)
love.graphics.rectangle('fill', 0, 0, 140, 50) -- love.graphics.rectangle('fill', 0, 0, 140, 50)
love.graphics.setColor() love.graphics.setColor(255, 250, 0)
love.graphics.print(string.format('OS: %s', love.system.getOS()), 5, 5) love.graphics.print(string.format('OS: %s', love.system.getOS()), 5, 5)
love.graphics.print(string.format('Love version: %s', love.getVersion()), 5, 15) love.graphics.print(string.format('Love version: %s', love.getVersion()), 5, 15)
love.graphics.print(string.format('Memory usage: %s KiB', love.system.getMemUsage()), 5, 25) love.graphics.print(string.format('Memory usage: %s KiB', love.system.getMemUsage()), 5, 25)
love.graphics.print(string.format('FPS: %.2f', 1.0 / love.timer.getAverageDelta()), 5, 35) love.graphics.print(string.format('FPS: %.2f', 1.0 / love.timer.getAverageDelta()), 5, 35)
love.graphics.setColor()
end end
end end

View File

@@ -8,6 +8,7 @@ local make_class = require 'src.utils.classes'
-- Class definitions -- Class definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
---@class Drawable
local Drawable = make_class() local Drawable = make_class()

View File

@@ -22,11 +22,12 @@ function GameState:_init(name, index)
Drawable._init(self) Drawable._init(self)
self.name = name self.name = name
self.index = index self.index = index
self.next_state = self.index
end end
function GameState:update(_) function GameState:update(_)
return self.index return self.next_state
end end

View File

@@ -4,43 +4,40 @@
local love = require 'love' local love = require 'love'
local assets = require 'src.utils.asstmngr' local assets = require 'src.utils.asstmngr'
local sound_manager = require 'src.sound.sndmngr'
local dialog_manager = require 'src.ui.dlgmngr'
local make_class = require 'src.utils.classes' local make_class = require 'src.utils.classes'
local constants = require 'src.gstates.menus.const'
local GameState = require 'src.gstates.gstate' local GameState = require 'src.gstates.gstate'
local MainMenu = require 'src.gstates.menus.mainmenu'
local OptionsMenu = require 'src.gstates.menus.options'
local Fader = require 'src.graphics.fader' local Fader = require 'src.graphics.fader'
local Sprite = require 'src.graphics.sprite'
local Cursor = require 'src.ui.cursor' local Cursor = require 'src.ui.cursor'
local Font = require 'src.ui.font' local Font = require 'src.ui.font'
local SoundEffect = require 'src.sound.sfx' local SoundEffect = require 'src.sound.sfx'
local ButtonGroup = require 'src.ui.btngrp'
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Class definitions -- Class definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local MainMenu = make_class(GameState) local Menu = make_class(GameState)
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Class methods -- Class methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
function MainMenu:_init(name, index) function Menu:_init(name, index)
GameState._init(self, name, index) GameState._init(self, name, index)
self.next_state = self.index
self.fade = Fader() self.fade = Fader()
self.current_menu = constants.MAIN_MENU
self.next_menu = constants.MAIN_MENU
self.all_loaded = false
-- Create sprites and buttons. -- Create sprites and buttons.
self.background = Sprite('imgs/concb03.png')
self.btn_font = Font('fonts/Concrete.ttf') self.btn_font = Font('fonts/Concrete.ttf')
self.title_font = Font('fonts/BBrick.ttf', 35)
-- Create UI elements.
self.btns = ButtonGroup(15, 15)
self.btns:add_text_button('New Game', self.btn_font)
self.btns:add_text_button('Load Game', self.btn_font)
self.btns:add_text_button('Options', self.btn_font)
self.btns:add_text_button('Help & Story', self.btn_font)
self.btns:add_text_button('Quit', self.btn_font, function() self.next_state = -1 end)
-- Create a mouse cursor object at the current mouse position. -- Create a mouse cursor object at the current mouse position.
local mx, my = love.mouse.getPosition() local mx, my = love.mouse.getPosition()
@@ -49,33 +46,64 @@ function MainMenu:_init(name, index)
-- Create sound effects. -- Create sound effects.
self.bgm = SoundEffect('bgm/eskisky.wav') self.bgm = SoundEffect('bgm/eskisky.wav')
-- Create the sub-menus.
self.menus = { }
self.menus[constants.MAIN_MENU] = MainMenu(self, self.title_font, self.btn_font)
self.menus[constants.OPTIONS_MENU] = OptionsMenu(self, self.title_font, self.btn_font)
-- Register all assets. -- Register all assets.
assets:register(self.name, self.btn_font) assets:register(self.name, self.btn_font)
assets:register(self.name, self.background) assets:register(self.name, self.title_font)
assets:register(self.name, self.cursor) assets:register(self.name, self.cursor)
assets:register(self.name, self.bgm) assets:register(self.name, self.bgm)
assets:register(self.name, self.btns)
end end
function MainMenu:update(dt) function Menu:update(dt)
if assets:done(self.name) then if not self.bgm:isPlaying() then sound_manager:play_music(self.bgm) end
if not self.bgm:isPlaying() then self.bgm:play() end
if self.all_loaded then
self.menus[self.current_menu]:update(dt)
dialog_manager:update(dt)
-- If the game state changed then trigger a fade out.
if self.next_menu ~= self.current_menu and self.fade.done then
self.fade:fade_out()
end
-- Update the fader.
self.fade:update(dt) self.fade:update(dt)
-- Update the game state.
if self.menus[self.next_menu] == nil then
error(string.format('%s: switched to unknown menu', self.next_menu))
else else
-- If the new state exists then unload it's data and set the new state.
if self.next_menu ~= self.current_menu and self.fade.done then
self.current_menu = self.next_menu
self.fade:fade_in()
end
end
else
local done = true
assets:update(self.name) assets:update(self.name)
for _, v in pairs(self.menus) do
assets:update(v.name)
done = done and assets:done(v.name)
end
self.all_loaded = assets:done(self.name) and done
end end
return self.next_state return self.next_state
end end
function MainMenu:draw() function Menu:draw()
if assets:done(self.name) then if self.all_loaded then
self.background:draw() self.menus[self.current_menu]:draw()
self.btns:draw() dialog_manager:draw()
self.cursor:draw() self.cursor:draw()
self.fade:draw() self.fade:draw()
else else
@@ -83,24 +111,70 @@ function MainMenu:draw()
end end
end end
function Menu:keypressed(key, code, isrepeat)
function MainMenu:keypressed(_) -- Send events to the active game state if there is no fade active.
if Fade.done then
if dialog_manager:empty() then
self.menus[self.current_menu]:keypressed(key, code, isrepeat)
else
dialog_manager:keypressed(key, code, isrepeat)
end
end
end end
function MainMenu:mousemoved(x, y, dx, dy) function Menu:keyreleased(key, code)
self.btns:mousemoved(x, y, dx, dy) -- Send events to the active game state if there is no fade active.
if Fade.done then
if dialog_manager:empty() then
self.menus[self.current_menu]:keyreleased(key, code)
else
dialog_manager:keyreleased(key, code)
end
end
end
function Menu:textinput(text)
-- Send events to the active game state if there is no fade active.
if Fade.done then
if dialog_manager:empty() then
self.menus[self.current_menu]:textinput(text)
else
dialog_manager:textinput(text)
end
end
end
function Menu:mousemoved(x, y, dx, dy)
if dialog_manager:empty() then
self.menus[self.current_menu]:mousemoved(x, y, dx, dy)
else
dialog_manager:mousemoved(x, y, dx, dy)
end
self.cursor:mousemoved(x, y, dx, dy) self.cursor:mousemoved(x, y, dx, dy)
end end
function MainMenu:mousepressed(x, y, btn) function Menu:mousepressed(x, y, btn)
self.btns:mousepressed(x, y, btn) if self.fade.done then
if dialog_manager:empty() then
self.menus[self.current_menu]:mousepressed(x, y, btn)
else
dialog_manager:mousepressed(x, y, btn)
end
end
end end
function MainMenu:mousereleased(x, y, btn) function Menu:mousereleased(x, y, btn)
self.btns:mousereleased(x, y, btn) if self.fade.done then
if dialog_manager:empty() then
self.menus[self.current_menu]:mousereleased(x, y, btn)
else
dialog_manager:mousereleased(x, y, btn)
end
end
end end
@@ -108,4 +182,4 @@ end
-- Module return -- Module return
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
return MainMenu return Menu

View File

@@ -0,0 +1,75 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local love = require 'love'
local assets = require 'src.utils.asstmngr'
local make_class = require 'src.utils.classes'
local GameState = require 'src.gstates.gstate'
local Sprite = require 'src.graphics.sprite'
local VBox = require 'src.ui.vbox'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local BaseMenu = make_class(GameState)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function BaseMenu:_init(parent, name, index, bckg)
GameState._init(self, name, index)
self.parent = parent
-- Create background sprite and container.
self.background = Sprite(bckg)
self.container = VBox(15, 5, love.graphics.getWidth() - 15)
-- Register the background and container into the asset manager.
assets:register(self.name, self.background)
assets:register(self.name, self.container)
end
function BaseMenu:mousemoved(x, y, dx, dy)
self.container:mousemoved(x, y, dx, dy)
end
function BaseMenu:mousepressed(x, y, btn)
self.container:mousepressed(x, y, btn)
end
function BaseMenu:mousereleased(x, y, btn)
self.container:mousereleased(x, y, btn)
end
function BaseMenu:update()
if not assets:done(self.name) then
assets:update(self.name)
end
end
function BaseMenu:draw()
if assets:done(self.name) then
self.background:draw()
self.container:draw()
else
assets:draw()
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return BaseMenu

View File

@@ -0,0 +1,17 @@
------------------------------------------------------------------------------
-- Constants
------------------------------------------------------------------------------
local constants = {
MAIN_MENU = 1,
OPTIONS_MENU = 2,
STORY = 3,
LOAD_MENU = 4,
}
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return constants

View File

@@ -0,0 +1,41 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local constants = require 'src.gstates.menus.const'
local BaseMenu = require 'src.gstates.menus.base'
local Color = require 'src.utils.color'
local Label = require 'src.ui.label'
local TextButton = require 'src.ui.textbtn'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local MainMenu = make_class(BaseMenu)
------------------------------------------------------------------------------
-- Main Menu Class methods
------------------------------------------------------------------------------
function MainMenu:_init(parent, title_font, button_font)
BaseMenu._init(self, parent, "Main Menu", constants.MAIN_MENU, 'imgs/concb03.png')
-- Create UI elements of the main menu.
self.container:add(Label(nil, nil, 'LoveDOS', title_font, Color(215, 0, 0), true))
self.container:add(TextButton('New Game', button_font))
self.container:add(TextButton('Load Game', button_font))
self.container:add(TextButton('Options', button_font, nil, nil, function() parent.next_menu = constants.OPTIONS_MENU end))
self.container:add(TextButton('Help & Story', button_font))
self.container:add(TextButton('Quit', button_font, nil, nil, function() parent.next_state = -1 end))
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return MainMenu

View File

@@ -0,0 +1,178 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local constants = require 'src.gstates.menus.const'
local settings = require 'src.utils.settings'
local sound_manager = require 'src.sound.sndmngr'
local assets = require 'src.utils.asstmngr'
local BaseMenu = require 'src.gstates.menus.base'
local Color = require 'src.utils.color'
local HBox = require 'src.ui.hbox'
local Label = require 'src.ui.label'
local TextButton = require 'src.ui.textbtn'
local TextInput = require 'src.ui.textinpt'
local Checkbox = require 'src.ui.chkbox'
local Bar = require 'src.ui.bar'
local Dialog = require 'src.ui.dialog'
local Font = require 'src.ui.font'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local OptionsMenu = make_class(BaseMenu)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function OptionsMenu:_init(parent, title_font, button_font)
BaseMenu._init(self, parent, "Options Menu", constants.OPTIONS_MENU, 'imgs/cpu.png')
self.subtitle_font = Font('fonts/BBrick.ttf', 25)
-- Create UI elements of the menu.
self.container:add(Label(nil, nil, 'Options', title_font, Color(215, 0, 0), true))
-- Permadeath checkbox.
local box = HBox()
box:add(Label(nil, nil, 'Enable Permadeath: ', button_font))
box:add(Checkbox(
function()
settings.permadeath = not settings.permadeath
end,
function()
return settings.permadeath
end,
17,
15))
self.container:add(box)
-- Control binding dialog.
local dlg = Dialog('imgs/tchcmp1.png', nil, 15, nil, nil, button_font)
dlg:add(Label(nil, nil, 'Set Controls', self.subtitle_font, Color(215, 0, 0), true))
box = HBox()
box.spacing = 30
-- text, font, x, y, callback, value, float, base_col, sel_color, press_col
box:add(TextInput('Step Forw.',
button_font,
nil, nil,
function(v) settings.forward = v end,
function() return settings.forward end))
box:add(TextInput('Step Back',
button_font,
nil, nil,
function(v) settings.backward = v end,
function() return settings.backward end))
dlg:add(box)
box = HBox()
box.spacing = 40
box:add(TextInput('Step Left',
button_font,
nil, nil,
function(v) settings.stepleft = v end,
function() return settings.stepleft end))
box:add(TextInput('Step Right',
button_font,
nil, nil,
function(v) settings.stepright = v end,
function() return settings.stepright end))
dlg:add(box)
box = HBox()
box.spacing = 42
box:add(TextInput('Turn Left',
button_font,
nil, nil,
function(v) settings.turnleft = v end,
function() return settings.turnleft end))
box:add(TextInput('Turn Right',
button_font,
nil, nil,
function(v) settings.turnright = v end,
function() return settings.turnright end))
dlg:add(box)
box = HBox()
box:add(TextButton(
'Set Controls',
button_font,
nil,
nil,
function()
dlg:show()
end))
self.container:add(box)
-- Sound volume bar.
box = HBox()
box:add(Label(nil, nil, 'Sound Volume: ', button_font))
box:add(Bar(
function(v)
settings.soundvol = math.ceil(v)
end,
function()
return settings.soundvol
end,
0, 100,
170, 15))
self.container:add(box)
-- Music volume bar.
box = HBox()
box.spacing = 13
box:add(Label(nil, nil, 'Music Volume: ', button_font))
box:add(Bar(
function(v)
settings.musicvol = math.ceil(v)
sound_manager:update_volumes()
end,
function()
return settings.musicvol
end,
0, 100,
170, 15))
self.container:add(box)
-- Back button.
box = HBox()
box:add(TextButton(
'Go Back',
button_font,
nil,
nil,
function()
settings:save_settings()
parent.next_menu = constants.MAIN_MENU
end))
self.container:add(box)
-- Register the dialog with the asset manager.
assets:register(self.name, dlg)
assets:register(self.name, self.subtitle_font)
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return OptionsMenu

View File

@@ -26,8 +26,10 @@ end
function SoundEffect:load() function SoundEffect:load()
if not self:is_loaded() then
self.sfx = love.audio.newSource(self.file_name) self.sfx = love.audio.newSource(self.file_name)
end end
end
function SoundEffect:unload() function SoundEffect:unload()
@@ -36,6 +38,11 @@ function SoundEffect:unload()
end end
function SoundEffect:is_loaded()
return self.sfx ~= nil
end
function SoundEffect:setVolume(volume) function SoundEffect:setVolume(volume)
if self.sfx ~= nil then self.sfx:setVolume(volume) end if self.sfx ~= nil then self.sfx:setVolume(volume) end
end end

57
src/sound/sndmngr.lua Normal file
View File

@@ -0,0 +1,57 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local settings = require 'src.utils.settings'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local SoundManager = make_class()
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function SoundManager:_init()
self.active_bgm = nil
end
function SoundManager:play_sound(sfx)
local vol = math.max(math.min(settings.soundvol / 100, 1.0), 0.0)
sfx:setVolume(vol)
sfx:play()
end
function SoundManager:play_music(bgm)
local vol = math.max(math.min(settings.musicvol / 100, 1.0), 0.0)
if self.active_bgm ~= nil then
self.active_bgm:stop()
end
self.active_bgm = bgm
self.active_bgm:setVolume(vol)
self.active_bgm:play()
end
function SoundManager:update_volumes()
if self.active_bgm ~= nil then
local vol = math.max(math.min(settings.musicvol / 100, 1.0), 0.0)
self.active_bgm:setVolume(vol)
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return SoundManager()

View File

@@ -3,7 +3,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local Intro = require 'src.gstates.intro' local Intro = require 'src.gstates.intro'
local MainMenu = require 'src.gstates.menu' local Menu = require 'src.gstates.menu'
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -13,7 +13,7 @@ local MainMenu = require 'src.gstates.menu'
-- Table of all valid game states. -- Table of all valid game states.
local states = { local states = {
Intro('intro', 1), Intro('intro', 1),
MainMenu('menu', 2), Menu('menu', 2),
} }

121
src/ui/bar.lua Normal file
View File

@@ -0,0 +1,121 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local love = require 'love'
local make_class = require 'src.utils.classes'
local collisions = require 'src.utils.colls'
local UIElement = require 'src.ui.element'
local Color = require 'src.utils.color'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local Bar = make_class(UIElement)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function Bar:_init(callback, val_fn, min, max, w, h, color, sel_color, press_col, float, x, y)
UIElement._init(self, x, y, float, false)
self.callback = callback
self.val_fn = val_fn
self.min = min
self.max = max
self.w = w
self.h = h
self.base_col = color ~= nil and color or Color(255, 255, 255)
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
self.disbl_col = Color(95, 63, 75)
end
function Bar:set_dimensions()
self.w = self.w
self.h = self.h
end
function Bar:draw()
local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
-- Convert the variable's value to the [0, 1] space.
local v = (self.val_fn() + math.abs(self.min)) / (self.max + math.abs(self.min))
love.graphics.setColor(color.r, color.g, color.b)
-- Render the bar's outline.
love.graphics.rectangle('line', self.x, self.y, self.w, self.h)
-- Render the bar's content using the [0, 1] value as a proportion of the bar's width.
love.graphics.rectangle('fill', self.x, self.y, self.w * v, self.h)
love.graphics.setColor()
end
function Bar:_mouse2bar(x)
-- Take the x coord to the [0, 1] space, with clamping.
local v = math.max(math.min(((x - self.x) / self.w), 1.0), 0.0)
-- Convert the value to a horizontal bar coordinate and return it.
return (v * (self.max + math.abs(self.min))) - self.min
end
function Bar:mousemoved(x, y)
-- Select if the pointer is inside the button's bounding rect.
self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
-- If the button was pressed then check if the pointer is no longer inside the button.
if self.pressed then
-- If it's not, then mark the button as "was pressed".
self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
self.was_pressed = true
self.callback(self:_mouse2bar(x))
end
-- If the button was pressed and the pointer is inside the button right now.
if self.was_pressed and collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) then
-- Then mark the button as pressed again.
self.pressed = true
self.was_pressed = false
self.callback(self:_mouse2bar(x))
end
end
function Bar:mousepressed(x, y, btn)
-- If the pointer was inside the button when it was pressed then mark the button as pressed.
if btn == 0 then
self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
end
end
function Bar:mousereleased(x, _, btn)
if btn == 0 then
if self.pressed then
-- If the button was pressed then execute the callback if any and unmark as pressed.
if self.callback ~= nil then
self.callback(self:_mouse2bar(x))
end
self.pressed = false
end
-- The button no longer was pressed.
self.was_pressed = false
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return Bar

View File

@@ -1,100 +0,0 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local Asset = require 'src.utils.asset'
local Drawable = require 'src.graphics.drawable'
local TextButton = require 'src.ui.textbtn'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local ButtonGroup = make_class(Drawable, Asset)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function ButtonGroup:_init(x, y, spacing)
self.x = x ~= nil and x or 0
self.y = y ~= nil and y or 0
self.s = spacing ~= nil and spacing or 10
self.btns = {}
end
function ButtonGroup:add_text_button(text, font, callback, base_col, sel_color, press_col)
table.insert(self.btns, TextButton(text, font, 0, 0, callback, base_col, sel_color, press_col))
end
function ButtonGroup:load()
local y = self.y
-- Load required assets if needed and then compute the coordinates of each button.
for i, v in pairs(self.btns) do
if v.is_a[Asset] then
v:load()
end
y = y + ((i > 1 and (self.btns[i - 1].h + self.s)) or 0)
v.x = self.x
v.y = y
end
end
function ButtonGroup:unload()
for _, v in pairs(self.btns) do
if v.is_a[Asset] then
v:unload()
end
end
end
function ButtonGroup:update(dt)
for _, v in pairs(self.btns) do
v:update(dt)
end
end
function ButtonGroup:draw()
for _, v in pairs(self.btns) do
v:draw()
end
end
function ButtonGroup:mousemoved(x, y, dx, dy)
for _, v in pairs(self.btns) do
v:mousemoved(x, y, dx, dy)
end
end
function ButtonGroup:mousepressed(x, y, btn)
for _, v in pairs(self.btns) do
v:mousepressed(x, y, btn)
end
end
function ButtonGroup:mousereleased(x, y, btn)
for _, v in pairs(self.btns) do
v:mousereleased(x, y, btn)
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return ButtonGroup

View File

@@ -4,26 +4,27 @@
local make_class = require 'src.utils.classes' local make_class = require 'src.utils.classes'
local collisions = require 'src.utils.colls' local collisions = require 'src.utils.colls'
local Asset = require 'src.utils.asset' local UIElement = require 'src.ui.element'
local Drawable = require 'src.graphics.drawable'
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Class definitions -- Class definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local Button = make_class(Drawable, Asset) ---@class Button: UIElement
local Button = make_class(UIElement)
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Class methods -- Class methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
function Button:_init(x, y, callback) ---@param x number
self.x = x ---@param y number
self.y = y ---@param callback function
self.w = nil ---@param float boolean
self.h = nil function Button:_init(x, y, callback, float)
UIElement._init(self, x, y, float, false)
self.selected = false self.selected = false
self.pressed = false self.pressed = false
self.was_pressed = false self.was_pressed = false

55
src/ui/chkbox.lua Normal file
View File

@@ -0,0 +1,55 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local love = require 'love'
local make_class = require 'src.utils.classes'
local Button = require 'src.ui.button'
local Color = require 'src.utils.color'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local Checkbox = make_class(Button)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function Checkbox:_init(callback, value, w, h, color, sel_color, press_col, float, x, y)
Button._init(self, x, y, callback, float)
self.value = value
self.w = w ~= nil and w or 20
self.h = h ~= nil and h or 20
self.base_col = color ~= nil and color or Color(255, 255, 255)
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
self.disbl_col = Color(95, 63, 75)
end
function Checkbox:set_dimensions()
self.w = self.w
self.h = self.h
end
function Checkbox:draw()
local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
local mode = nil
if self.value() then mode = 'fill' else mode = 'line' end
love.graphics.setColor(color.r, color.g, color.b)
love.graphics.rectangle(mode, self.x, self.y, self.w, self.h)
love.graphics.setColor()
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return Checkbox

117
src/ui/dialog.lua Normal file
View File

@@ -0,0 +1,117 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local love = require 'love'
local make_class = require 'src.utils.classes'
local dialog_manager = require 'src.ui.dlgmngr'
local VBox = require 'src.ui.vbox'
local Sprite = require 'src.graphics.sprite'
local TextButton = require 'src.ui.textbtn'
local HBox = require 'src.ui.hbox'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local Dialog = make_class(VBox)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function Dialog:_init(bckg, spacing, padding, close_btn, accept_btn, font)
VBox._init(self, nil, nil, nil, nil, spacing, false)
self.spacing = spacing ~= nil and spacing or 10
self.padding = padding ~= nil and padding or 15
self.background = Sprite(bckg)
self.shown = false
local close = nil
if close_btn ~= nil then
close = close_btn
else
close = TextButton(
'Close',
font,
nil,
nil,
function()
self:hide()
end)
end
local accept = nil
if accept_btn ~= nil then accept = accept_btn end
-- Create a container for the close and accept button and add them.
local box = HBox(nil, nil, nil, nil, 10, true)
box:add(close)
if accept ~= nil then box:add(accept) end
self.elements[9001] = box
end
function Dialog:add(element)
table.insert(self.elements, element)
end
function Dialog:load()
self.background:load()
self:set_dimensions()
VBox.load(self)
end
function Dialog:set_dimensions()
self.w = self.background.sprite:getWidth()
self.h = self.background.sprite:getHeight()
-- Center the dialog on the screen.
self.x = (320 - self.w) / 2
self.y = (200 - self.h) / 2
self.background.x = self.x
self.background.y = self.y
-- Add padding.
self.x = self.x + self.padding
self.y = self.y + self.padding / 2
end
function Dialog:draw()
love.graphics.setColor(0, 0, 0)
love.graphics.rectangle('line', self.x - self.padding - 1, self.y - (self.padding / 2) - 1, self.w + 2, self.h + 2)
love.graphics.setColor()
self.background:draw()
VBox.draw(self)
end
function Dialog:show()
if not self.shown then
dialog_manager:add(self)
self.shown = true
end
end
function Dialog:hide()
dialog_manager:remove(self)
self.shown = false
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return Dialog

104
src/ui/dlgmngr.lua Normal file
View File

@@ -0,0 +1,104 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local Drawable = require 'src.graphics.drawable'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local DialogManager = make_class(Drawable)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function DialogManager:_init()
Drawable._init(self)
self.dialogs = {}
self.count = 0
end
function DialogManager:add(dialog)
self.dialogs[dialog] = true
self.count = self.count + 1
end
function DialogManager:remove(dialog)
self.dialogs[dialog] = nil
self.count = math.max(self.count - 1, 0)
end
function DialogManager:empty()
return self.count == 0
end
function DialogManager:update(dt)
for d, _ in pairs(self.dialogs) do
d:update(dt)
end
end
function DialogManager:draw()
for d, _ in pairs(self.dialogs) do
d:draw()
end
end
function DialogManager:keypressed(key, code, isrepeat)
for d, _ in pairs(self.dialogs) do
d:keypressed(key, code, isrepeat)
end
end
function DialogManager:textinput(text)
for d, _ in pairs(self.dialogs) do
d:textinput(text)
end
end
function DialogManager:keyreleased(key, code)
for d, _ in pairs(self.dialogs) do
d:keyreleased(key, code)
end
end
function DialogManager:mousemoved(x, y, dx, dy)
for d, _ in pairs(self.dialogs) do
d:mousemoved(x, y, dx, dy)
end
end
function DialogManager:mousepressed(x, y, btn)
for d, _ in pairs(self.dialogs) do
d:mousepressed(x, y, btn)
end
end
function DialogManager:mousereleased(x, y, btn)
for d, _ in pairs(self.dialogs) do
d:mousereleased(x, y, btn)
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return DialogManager()

84
src/ui/element.lua Normal file
View File

@@ -0,0 +1,84 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local Asset = require 'src.utils.asset'
local Drawable = require 'src.graphics.drawable'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
local focused_element = nil
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
---@class UIElement: Drawable, Asset
local UIElement = make_class(Drawable, Asset)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
---@param x integer
---@param y integer
---@param float boolean
---@param focusable boolean
function UIElement:_init(x, y, float, focusable)
Asset._init(self)
self.x = x
self.y = y
self.w = nil
self.h = nil
self.float_right = float and float or false
self.focusable = focusable ~= nil and focusable or false
end
function UIElement:set_dimensions()
self.w = 0
self.h = 0
end
function UIElement:load()
end
function UIElement:unload()
end
function UIElement:is_loaded()
return true
end
function UIElement:focus()
if self.focusable then
focused_element = self
end
end
function UIElement:blur()
if self.focusable and focused_element == self then
focused_element = nil
end
end
function UIElement:is_focused()
return self.focusable and focused_element == self
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return UIElement

View File

@@ -10,6 +10,7 @@ local Asset = require 'src.utils.asset'
-- Class definitions -- Class definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
---@class Font: Asset
-- Font is a simple wrapper around Löve's own Font class to allow for -- Font is a simple wrapper around Löve's own Font class to allow for
-- easy loading/unloading and automatically checking if it's is valid -- easy loading/unloading and automatically checking if it's is valid
-- before using it. -- before using it.
@@ -20,6 +21,8 @@ local Font = make_class(Asset)
-- Class methods -- Class methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
---@param file_name string
---@param size number
function Font:_init(file_name, size) function Font:_init(file_name, size)
self.file_name = string.format('assets/%s', file_name) self.file_name = string.format('assets/%s', file_name)
self.size = (size ~= nil and size) or 20 self.size = (size ~= nil and size) or 20

63
src/ui/hbox.lua Normal file
View File

@@ -0,0 +1,63 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local Layout = require 'src.ui.layout'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
---@class HBox: Layout
local HBox = make_class(Layout)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function HBox:_init(x, y, w, h, spacing, float)
Layout._init(self, x, y, w, h, spacing, float)
end
function HBox:load()
Layout.load(self)
local _x = self.x
-- Load required assets if needed and then compute the coordinates of each button.
for _, v in pairs(self.elements) do
v.y = self.y
v.x = _x
_x = _x + v.w + self.spacing
end
end
function HBox:set_dimensions()
if self.w == nil then
self.w = 0
for i, v in pairs(self.elements) do
self.w = self.w + v.w
if i < #self.elements then self.w = self.w + self.spacing end
end
end
if self.h == nil then
self.h = 0
for _, v in pairs(self.elements) do
if v.h > self.h then self.h = v.h end
end
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return HBox

74
src/ui/label.lua Normal file
View File

@@ -0,0 +1,74 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local love = require 'love'
local make_class = require 'src.utils.classes'
local UIElement = require 'src.ui.element'
local Color = require 'src.utils.color'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
---@class Label: UIElement
local Label = make_class(UIElement)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
---@param x number
---@param y number
---@param text string
---@param font Font
---@param color Color
---@param float boolean
function Label:_init(x, y, text, font, color, float)
UIElement._init(self, x, y, float, false)
self.text = text
self.font = font
self.color = color ~= nil and color or Color(255, 255, 255)
end
function Label:set_dimensions()
self.w = self.font:get_width(self.text)
self.h = self.font:get_height(self.text)
end
function Label:load()
self.font:load()
-- If the label's size has not been computed then do it.
if self.w == nil or self.h == nil then self:set_dimensions() end
end
function Label:unload()
self.font:unload()
end
function Label:is_loaded()
return self.font:is_loaded() and self.w ~= nil and self.h ~= nil
end
function Label:draw()
love.graphics.setColor(self.color.r, self.color.g, self.color.b)
self.font:set()
love.graphics.print(self.text, self.x, self.y)
self.font:unset()
love.graphics.setColor()
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return Label

118
src/ui/layout.lua Normal file
View File

@@ -0,0 +1,118 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local UIElement = require 'src.ui.element'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
---@class Layout: UIElement
local Layout = make_class(UIElement)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function Layout:_init(x, y, w, h, spacing, float)
UIElement._init(self, x, y, float, false)
self.x = x ~= nil and x or 0
self.y = y ~= nil and y or 0
self.w = w
self.h = h
self.spacing = spacing ~= nil and spacing or 10
self.elements = {}
end
function Layout:add(element)
table.insert(self.elements, element)
end
function Layout:load()
-- Load required assets if needed and then compute the coordinates of each button.
for _, v in pairs(self.elements) do
if v.is_a[UIElement] then
v:load()
end
end
self:set_dimensions()
end
function Layout:unload()
for _, v in pairs(self.elements) do
if v.is_a[UIElement] then
v:unload()
end
end
end
function Layout:update(dt)
for _, v in pairs(self.elements) do
v:update(dt)
end
end
function Layout:draw()
for _, v in pairs(self.elements) do
v:draw()
end
end
function Layout:keypressed(key, code, isrepeat)
for _, v in pairs(self.elements) do
v:keypressed(key, code, isrepeat)
end
end
function Layout:textinput(text)
for _, v in pairs(self.elements) do
v:textinput(text)
end
end
function Layout:keyreleased(key, code)
for _, v in pairs(self.elements) do
v:keyreleased(key, code)
end
end
function Layout:mousemoved(x, y, dx, dy)
for _, v in pairs(self.elements) do
v:mousemoved(x, y, dx, dy)
end
end
function Layout:mousepressed(x, y, btn)
for _, v in pairs(self.elements) do
v:mousepressed(x, y, btn)
end
end
function Layout:mousereleased(x, y, btn)
for _, v in pairs(self.elements) do
v:mousereleased(x, y, btn)
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return Layout

View File

@@ -19,13 +19,14 @@ local TextButton = make_class(Button)
-- Class methods -- Class methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
function TextButton:_init(text, font, x, y, callback, base_col, sel_color, press_col) function TextButton:_init(text, font, x, y, callback, float, base_col, sel_color, press_col)
Button._init(self, x, y, callback) Button._init(self, x, y, callback, float)
self.font = font self.font = font
self.text = text self.text = text
self.base_col = base_col ~= nil and base_col or Color(255, 255, 255) self.base_col = base_col ~= nil and base_col or Color(255, 255, 255)
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0) self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139) self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
self.disbl_col = Color(95, 63, 75)
end end
@@ -56,7 +57,7 @@ end
function TextButton:draw() function TextButton:draw()
local color = (self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col) local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
love.graphics.setColor(color.r, color.g, color.b) love.graphics.setColor(color.r, color.g, color.b)
self.font:set() self.font:set()

118
src/ui/textinpt.lua Normal file
View File

@@ -0,0 +1,118 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local love = require 'love'
local make_class = require 'src.utils.classes'
local collisions = require 'src.utils.colls'
local UIElement = require 'src.ui.element'
local Color = require 'src.utils.color'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
---@class CharInput: UIElement
local TextInput = make_class(UIElement)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
---@param text string
---@param font Font
---@param x number
---@param y number
---@param callback function
---@param value function
---@param float boolean
---@param base_col Color
---@param sel_color Color
---@param press_col Color
function TextInput:_init(text, font, x, y, callback, value, float, base_col, sel_color, press_col)
UIElement._init(self, x, y, float, true)
self.callback = callback
self.value = value
self.font = font
self.text = text
self.base_col = base_col ~= nil and base_col or Color(255, 255, 255)
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
self.disbl_col = Color(95, 63, 75)
self.selected = false
self.pressed = false
end
function TextInput:load()
self.font:load()
-- If the label's size has not been computed then do it.
if self.w == nil or self.h == nil then self:set_dimensions() end
end
function TextInput:unload()
self.font:unload()
end
function TextInput:is_loaded()
return self.font:is_loaded() and self.w ~= nil and self.h ~= nil
end
function TextInput:set_dimensions()
self.w = self.font:get_width(self.text .. 'm')
self.h = self.font:get_height(self.text)
end
function TextInput:draw()
local color = self.callback == nil and self.disbl_col or (((self.pressed or self:is_focused()) and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
love.graphics.setColor(color.r, color.g, color.b)
self.font:set()
if self:is_focused() then
love.graphics.print(self.text .. ': ?', self.x, self.y)
else
love.graphics.print(self.text .. ': ' .. self.value(), self.x, self.y)
end
self.font:unset()
love.graphics.setColor()
end
function TextInput:mousemoved(x, y)
-- Select if the pointer is inside the button's bounding rect.
self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
end
function TextInput:mousepressed(_, _, btn)
-- If the pointer was inside the button when it was pressed then mark the button as pressed.
if btn == 0 and self.selected then
self:focus()
end
end
function TextInput:keypressed(key)
if self:is_focused() then
if #key == 1 then
if self.callback ~= nil then self.callback(key) end
self:blur()
end
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return TextInput

66
src/ui/vbox.lua Normal file
View File

@@ -0,0 +1,66 @@
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
local make_class = require 'src.utils.classes'
local Layout = require 'src.ui.layout'
------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------
---@class VBox: Layout
local VBox = make_class(Layout)
------------------------------------------------------------------------------
-- Class methods
------------------------------------------------------------------------------
function VBox:_init(x, y, w, h, spacing, float)
Layout._init(self, x, y, w, h, spacing, float)
end
function VBox:load()
Layout.load(self)
local _y = self.y
-- Load required assets if needed and then compute the coordinates of each button.
for _, v in pairs(self.elements) do
if v.float_right then
v.x = self.w - v.w
else
v.x = self.x
end
v.y = _y
_y = _y + v.h + self.spacing
end
end
function VBox:set_dimensions()
if self.w == nil then
self.w = 0
for _, v in pairs(self.elements) do
if v.w > self.w then self.w = v.w end
end
end
if self.h == nil then
self.h = 0
for i, v in pairs(self.elements) do
self.h = self.h + v.h
if i < #self.elements then self.h = self.h + self.spacing end
end
end
end
------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------
return VBox

View File

@@ -9,6 +9,7 @@ local make_class = require 'src.utils.classes'
-- Class definitions -- Class definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
---@class Asset
local Asset = make_class() local Asset = make_class()

View File

@@ -5,6 +5,7 @@
local love = require 'love' local love = require 'love'
local make_class = require 'src.utils.classes' local make_class = require 'src.utils.classes'
local Drawable = require 'src.graphics.drawable' local Drawable = require 'src.graphics.drawable'
local Asset = require 'src.utils.asset'
local Sprite = require 'src.graphics.sprite' local Sprite = require 'src.graphics.sprite'
local Font = require 'src.ui.font' local Font = require 'src.ui.font'
@@ -13,7 +14,6 @@ local Font = require 'src.ui.font'
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local AssetManager = make_class(Drawable) local AssetManager = make_class(Drawable)
local Asset = require 'src.utils.asset'
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -65,14 +65,18 @@ end
function AssetManager:update(owner) function AssetManager:update(owner)
if self.assets[owner] ~= nil then if self.assets[owner] ~= nil then
if self.co == nil then if self.assets[owner].co == nil then
self.co = coroutine.create(_load) self.assets[owner].co = coroutine.create(_load)
end end
local errorfree, retval = coroutine.resume(self.co, self, owner) local errorfree, retval = coroutine.resume(self.assets[owner].co, self, owner)
if errorfree then if errorfree then
self.assets[owner].done = retval self.assets[owner].done = retval
if retval then
self.assets[owner].co = nil
end
else else
error(retval) error(retval)
end end
@@ -96,6 +100,7 @@ function AssetManager:register(owner, asset)
if self.assets[owner] == nil then if self.assets[owner] == nil then
self.assets[owner] = { self.assets[owner] = {
done = false, done = false,
co = nil,
} }
end end

View File

@@ -2,7 +2,9 @@
-- Methods -- Methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Code from http://lua-users.org/wiki/ObjectOrientationTutorial --- Code from http://lua-users.org/wiki/ObjectOrientationTutorial
---@param ... table Optional base classes
---@return table cls A class definition
local function make_class(...) local function make_class(...)
-- "cls" is the new class -- "cls" is the new class
local cls, bases = {}, {...} local cls, bases = {}, {...}

View File

@@ -9,6 +9,7 @@ local make_class = require 'src.utils.classes'
-- Class definitions -- Class definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
---@class Color
local Color = make_class() local Color = make_class()

View File

@@ -4,6 +4,7 @@
local love = require 'love' local love = require 'love'
local magiclines = require 'src.utils.mgclines' local magiclines = require 'src.utils.mgclines'
local make_class = require 'src.utils.classes'
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -17,25 +18,29 @@ local SETTINGS_PATH = 'settings.ini'
-- Module definitions -- Module definitions
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local settings = { ---@class Settings
-- Default setting values. local Settings = make_class()
permadeath = true,
forward = 'w',
backward = 's',
stepleft = 'a',
stepright = 'd',
turnleft = 'q',
turnright = 'e',
musicvol = 75,
soundvol = 100,
}
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Private module methods -- Private module methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
function settings:_parse_settings_str(s) function Settings:_init()
-- Default setting values.
self.permadeath = true
self.forward = 'w'
self.backward = 's'
self.stepleft = 'a'
self.stepright = 'd'
self.turnleft = 'q'
self.turnright = 'e'
self.musicvol = 75
self.soundvol = 100
end
function Settings:_parse_settings_str(s)
-- For each line in the data string. -- For each line in the data string.
for line in magiclines(s) do for line in magiclines(s) do
-- Check if the line matches a key=value pair -- Check if the line matches a key=value pair
@@ -67,7 +72,7 @@ function settings:_parse_settings_str(s)
end end
function settings:_get_settings_str() function Settings:_get_settings_str()
-- Start with the settings category. -- Start with the settings category.
local s = '[settings]\n' local s = '[settings]\n'
@@ -84,7 +89,7 @@ function settings:_get_settings_str()
end end
function settings:_open_or_create() function Settings:_open_or_create()
if not love.filesystem.exists(SETTINGS_PATH) then if not love.filesystem.exists(SETTINGS_PATH) then
-- If the settings file doesn't exist then create it with the default values. -- If the settings file doesn't exist then create it with the default values.
local setts = self:_get_settings_str() local setts = self:_get_settings_str()
@@ -106,14 +111,14 @@ end
-- Public module methods -- Public module methods
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
function settings:load_settings() function Settings:load_settings()
-- Obtain the settings data and parse it. -- Obtain the settings data and parse it.
local s = self:_open_or_create() local s = self:_open_or_create()
self:_parse_settings_str(s) self:_parse_settings_str(s)
end end
function settings:save_settings() function Settings:save_settings()
if not love.filesystem.exists(SETTINGS_PATH) or love.filesystem.isFile(SETTINGS_PATH) then if not love.filesystem.exists(SETTINGS_PATH) or love.filesystem.isFile(SETTINGS_PATH) then
-- If the settings file doesn't exist or it exists and is a file then save the current data. -- If the settings file doesn't exist or it exists and is a file then save the current data.
love.filesystem.write(SETTINGS_PATH, self:_get_settings_str()) love.filesystem.write(SETTINGS_PATH, self:_get_settings_str())
@@ -128,4 +133,4 @@ end
-- Module return -- Module return
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
return settings return Settings()