From 22ae4f213bbec0e1c30efbf2cd791e4d96731105 Mon Sep 17 00:00:00 2001 From: Wally Hackenslacker Date: Sun, 5 Oct 2025 17:47:17 -0400 Subject: [PATCH] Added assets manager singleton. --- assets/imgs/floppy.png | Bin 0 -> 14289 bytes licenses/OFL.TXT | 97 ++++++++++++++++++++++++++++ src/graphics/drawable.lua | 3 +- src/graphics/sprite.lua | 6 +- src/gstates/gstate.lua | 15 ++++- src/gstates/menu.lua | 46 +++++++------- src/sound/sfx.lua | 4 +- src/ui/font.lua | 53 ++++++++++++++++ src/utils/asset.lua | 5 +- src/utils/asstmngr.lua | 130 ++++++++++++++++++++++++++++++++++++++ src/utils/classes.lua | 4 +- 11 files changed, 329 insertions(+), 34 deletions(-) create mode 100644 assets/imgs/floppy.png create mode 100644 licenses/OFL.TXT create mode 100644 src/ui/font.lua create mode 100644 src/utils/asstmngr.lua diff --git a/assets/imgs/floppy.png b/assets/imgs/floppy.png new file mode 100644 index 0000000000000000000000000000000000000000..d3974e5399559f934f9d993506cb5caf3ae9f1b1 GIT binary patch literal 14289 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

(adAP#pe}X?;*{3`$DrzG% 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 literal 0 HcmV?d00001 diff --git a/licenses/OFL.TXT b/licenses/OFL.TXT new file mode 100644 index 0000000..40bd8a6 --- /dev/null +++ b/licenses/OFL.TXT @@ -0,0 +1,97 @@ +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/graphics/drawable.lua b/src/graphics/drawable.lua index a93f4ab..71f4c02 100644 --- a/src/graphics/drawable.lua +++ b/src/graphics/drawable.lua @@ -16,7 +16,8 @@ local Drawable = make_class(Asset) -- Class methods ------------------------------------------------------------------------------ -function Drawable:_init() +function Drawable:_init(file_name) + Asset._init(self, file_name) end diff --git a/src/graphics/sprite.lua b/src/graphics/sprite.lua index cedc6b7..914eda8 100644 --- a/src/graphics/sprite.lua +++ b/src/graphics/sprite.lua @@ -17,15 +17,15 @@ local Sprite = make_class(Drawable) -- Class methods ------------------------------------------------------------------------------ -function Sprite:_init(sprite_name, x, y) - self.sprite_name = string.format('assets/%s', sprite_name) +function Sprite:_init(file_name, x, y) + Drawable._init(self, file_name) self.x = (x ~= nil and x) or 0 self.y = (y ~= nil and y) or 0 end function Sprite:load() - self.sprite = love.graphics.newImage(self.sprite_name) + self.sprite = love.graphics.newImage(self.file_name) end diff --git a/src/gstates/gstate.lua b/src/gstates/gstate.lua index 12cdaa1..ca2abf3 100644 --- a/src/gstates/gstate.lua +++ b/src/gstates/gstate.lua @@ -3,8 +3,10 @@ ------------------------------------------------------------------------------ local make_class = require 'src.utils.classes' +local assets = require 'src.utils.asstmngr' local Drawable = require 'src.graphics.drawable' + ------------------------------------------------------------------------------ -- Class definitions ------------------------------------------------------------------------------ @@ -18,8 +20,8 @@ local GameState = make_class(Drawable) function GameState:_init(name, index) Drawable._init(self) - self.name = name - self.index = index + self.name = name + self.index = index end @@ -28,6 +30,15 @@ function GameState:update(_) end +function GameState:load() +end + + +function GameState:unload() + assets:unload(self.name) +end + + ------------------------------------------------------------------------------ -- Module return ------------------------------------------------------------------------------ diff --git a/src/gstates/menu.lua b/src/gstates/menu.lua index e339e66..df90fb0 100644 --- a/src/gstates/menu.lua +++ b/src/gstates/menu.lua @@ -3,6 +3,7 @@ ------------------------------------------------------------------------------ local love = require 'love' +local assets = require 'src.utils.asstmngr' local make_class = require 'src.utils.classes' local GameState = require 'src.gstates.gstate' local Fader = require 'src.graphics.fader' @@ -36,40 +37,37 @@ function MainMenu:_init(name, index) -- Create sound effects. self.bgm = SoundEffect('bgm/eskisky.wav') -end - -function MainMenu:load() - -- Load sprites. - self.background:load() - self.cursor:load() - - -- Load sound effects and start playing the background music - self.bgm:load() - self.bgm:play() + -- Register all assets. + assets:register(self.name, self.background) + assets:register(self.name, self.cursor) + assets:register(self.name, self.bgm) end function MainMenu:update(dt) - -- Update the fader. - self.fade:update(dt) + if assets:done(self.name) then + if not self.bgm:isPlaying() then self.bgm:play() end - -- Move on to the next game state if the user skipped the intro or all stages are complete. - if not self.skip then return self.index else return -1 end + -- Update the fader. + self.fade:update(dt) + + -- Move on to the next game state if the user skipped the intro or all stages are complete. + if not self.skip then return self.index else return -1 end + else + assets:update(self.name) + end end function MainMenu:draw() - self.background:draw() - self.cursor:draw() - self.fade:draw() -end - - -function MainMenu:unload() - self.background:unload() - self.cursor:unload() - self.bgm:unload() + if assets:done(self.name) then + self.background:draw() + self.cursor:draw() + self.fade:draw() + else + assets:draw() + end end diff --git a/src/sound/sfx.lua b/src/sound/sfx.lua index a9536c4..b1a7421 100644 --- a/src/sound/sfx.lua +++ b/src/sound/sfx.lua @@ -11,7 +11,7 @@ local Asset = require 'src.utils.asset' ------------------------------------------------------------------------------ -- SoundEffect is a simple wrapper around Löve's Source class to allow for --- easy loading/unloading and automatically hecking if a sound effect is valid +-- easy loading/unloading and automatically checking if a sound effect is valid -- before using it. local SoundEffect = make_class(Asset) @@ -21,7 +21,7 @@ local SoundEffect = make_class(Asset) ------------------------------------------------------------------------------ function SoundEffect:_init(file_name) - self.file_name = string.format('assets/%s', file_name) + Asset._init(self, file_name) end diff --git a/src/ui/font.lua b/src/ui/font.lua new file mode 100644 index 0000000..bc2d95a --- /dev/null +++ b/src/ui/font.lua @@ -0,0 +1,53 @@ +------------------------------------------------------------------------------ +-- Imports +------------------------------------------------------------------------------ + +local love = require 'love' +local make_class = require 'src.utils.classes' +local Asset = require 'src.utils.asset' + +------------------------------------------------------------------------------ +-- Class definitions +------------------------------------------------------------------------------ + +-- 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 +-- before using it. +local Font = make_class(Asset) + + +------------------------------------------------------------------------------ +-- Class methods +------------------------------------------------------------------------------ + +function Font:_init(file_name, size) + self.file_name = string.format('assets/%s', file_name) + self.size = (size ~= nil and size) or 20 +end + + +function Font:load() + self.f = love.graphics.newFont(self.file_name, self.size) +end + + +function Font:unload() + self.f = nil +end + + +function Font:set() + if self.f ~= nil then love.graphics.setFont(self.f) end +end + + +function Font:unset() + love.graphics.setFont() +end + + +------------------------------------------------------------------------------ +-- Module return +------------------------------------------------------------------------------ + +return Font diff --git a/src/utils/asset.lua b/src/utils/asset.lua index 324c08f..cfa74c2 100644 --- a/src/utils/asset.lua +++ b/src/utils/asset.lua @@ -16,15 +16,18 @@ local Asset = make_class() -- Class methods ------------------------------------------------------------------------------ -function Asset:_init() +function Asset:_init(file_name) + self.file_name = string.format('assets/%s', file_name) end function Asset:load() + error 'Attempted to load unimplemented asset.' end function Asset:unload() + error 'Attempted to unload unimplemented asset.' end diff --git a/src/utils/asstmngr.lua b/src/utils/asstmngr.lua new file mode 100644 index 0000000..b53884a --- /dev/null +++ b/src/utils/asstmngr.lua @@ -0,0 +1,130 @@ +------------------------------------------------------------------------------ +-- Imports +------------------------------------------------------------------------------ + +local love = require 'love' +local make_class = require 'src.utils.classes' +local Drawable = require 'src.graphics.drawable' +local Sprite = require 'src.graphics.sprite' +local Font = require 'src.ui.font' + +------------------------------------------------------------------------------ +-- Class definitions +------------------------------------------------------------------------------ + +local AssetManager = make_class(Drawable) +local Asset = require 'src.utils.asset' + + +------------------------------------------------------------------------------ +-- Helper functions +------------------------------------------------------------------------------ + +local function _load(manager, owner) + if manager.assets[owner] ~= nil then + for k, _ in pairs(manager.assets[owner]) do + if k.is_a ~= nil and k.is_a[Asset] then + k:load() + end + coroutine.yield(false) + end + end + + return true +end + + +------------------------------------------------------------------------------ +-- Class methods +------------------------------------------------------------------------------ + +function AssetManager:_init() + Drawable._init(self) + self.assets = {} + self.bckg = Sprite('imgs/floppy.png') + self.font = Font('fonts/Concrete.ttf', 40) + self.co = nil + + self.bckg:load() + self.font:load() +end + + +function AssetManager:unload(owner) + -- If the owner is known... + if self.assets[owner] ~= nil then + -- Iterate over it's asset set and unload everything. + for k, _ in pairs(self.assets[owner]) do + if k.is_a ~= nil and k.is_a[Asset] then + k:unload() + end + end + end +end + + +function AssetManager:update(owner) + if self.assets[owner] ~= nil then + if self.co == nil then + self.co = coroutine.create(_load) + end + + local errorfree, retval = coroutine.resume(self.co, self, owner) + + if errorfree then + self.assets[owner].done = retval + else + error(retval) + end + end +end + + +function AssetManager:draw() + self.bckg:draw() + + love.graphics.setColor(195, 147, 123) + self.font:set() + love.graphics.print('Loading...', 5, 150) + self.font:unset() + love.graphics.setColor() +end + + +function AssetManager:register(owner, asset) + -- If the owner is new, then create an asset set for it. + if self.assets[owner] == nil then + self.assets[owner] = { + done = false, + } + end + + -- Store the asset in the set. + self.assets[owner][asset] = true +end + + +function AssetManager:remove(owner, asset) + -- If the owner is new, then create an asset set for it. + if self.assets[owner] ~= nil then + -- Unload the asset just in case. + if self.assets[owner][asset] ~= nil then + self.assets[owner][asset]:unload() + end + + -- Then remove it from the set. + self.assets[owner][asset] = nil + end +end + + +function AssetManager:done(owner) + return self.assets[owner] ~= nil and self.assets[owner].done +end + + +------------------------------------------------------------------------------ +-- Module return +------------------------------------------------------------------------------ + +return AssetManager() diff --git a/src/utils/classes.lua b/src/utils/classes.lua index 0923b10..760e2c6 100644 --- a/src/utils/classes.lua +++ b/src/utils/classes.lua @@ -20,7 +20,9 @@ local function make_class(BaseClass) cls.__index, cls.is_a = cls, {[cls] = true} if BaseClass ~= nil then - cls.is_a[BaseClass] = true + for k, _ in pairs(BaseClass.is_a) do + cls.is_a[k] = true + end end -- the class's __call metamethod