https://github.com/HybridEidolon/love2d-vore-template
once more doing some groundwork to save some time, and sharing the code.
vore is a love2d game template leveraging the gulp build tool from the node ecosystem to watch your game source for changes and recompile and bake your assets automatically. accompanying it are extensions for tiny-ecs and (now) an asset manager that both fit well into this watch-reload pattern, allowing you to reload both system code and assets at runtime simply by saving them in your editor. vore also automatically packages and uploads your game to itch.io through butler. it supports moonscript, aseprite, and tiled compilation to loadable assets built-in, and is relatively easy to extend.
per the documentation:
Asset Manager
AssetManager is a stateful object that combines a few functions:
- Loading and caching of various asset types by string path
- Storage of runtime-generated assets by a unique transient index object
- Retrieval of cached assets (assuming they are already loaded)
- Reloading of loaded assets
Examples (Moonscript)
Construct a new instance:
import AssetManager from require 'AssetManager'
manager = AssetManager!
Add an extension-based loader. The return value of the loader func will be stored in the cache.
manager\setLoader 'png', love.graphics.newImage
manager\setLoader 'wav', (path) -> love.audio.newSource path, 'static'
manager\setLoader 'lua', love.filesystem.load
manager\setLoader 'json', myJsonLoader
Load an asset (for later retrieval). The loader used will be based on the extension.
manager\load 'sprite.png'
Retrieve an asset and use it
sprite = manager\get 'sprite.png'
love.graphics.draw sprite, 0, 0
Insert a dynamic asset into the cache and create an opaque index key for it. Store the key
if you want to reference the asset later. (Note: if you need to e.g. serialize entity state,
you'll need to delete this from the output)
image = love.image.newImageData 512, 512
key = manager\insert image
Retrieve a dynamic asset from the cache. You should not store this reference; keep it only
for as long as you need it, because you can retrieve it later. Holding onto the asset
will just make hot reloading not work.
dynamicImage = manager\get key
Replace a dynamic asset in the cache, reusing the key. release will NOT be called on the object.
You can replace an asset with nil to fully remove it from the cache.
anotherImage = love.image.newImageData 128, 128
oldImage = manager
eplace key, anotherImage
oldImage
elease!
-- remove it
oldImage = manager
eplace key, nil
oldImage
elease!
Check and reload updated assets. release will be called on the values if it exists.
If a file is removed, it will not be removed from the cache, but obviously it won't
be present in future runs.
manager\update!
Usage in ECS
Store the AssetManager on your World. Use a System to first gather all of the asset references
in your scene that need to be loaded, and load them. For example:
tiny = require 'tiny'
ProcessingSystem = require 'tinyx.ProcessingSystem'
class LoadSpriteImages extends ProcessingSystem
new: =>
super!
filter: tiny.filter 'sprite'
process: (e, dt) =>
if not @world.assetManager\get e.sprite.imageKey and type(e.sprite.imageKey) == 'string'
@world.assetManager\load e.sprite.imageKey
LoadSpriteImages
If you want to periodically hot reload all your assets (almost certainly why you're using this):
tiny = require 'tiny'
System = require 'tinyx.System'
class ReloadAssets extends System
new: (reloadInterval) =>
super!
@interval = reloadInterval
update: (dt) =>
@world.assetManager\update!
ReloadAssets
Of course, you can get the assets you need in the systems e.g. responsible for drawing or starting
sound sources.