Page 3 of 3
Re: Share your Utils
Posted: Mon Feb 28, 2011 10:14 am
by BlackBulletIV
Thanks for the help guys!
Robin wrote:BlackBulletIV wrote:slime wrote:It probably won't work.
Funny thing is, it actually does work.
The subtle difference between "you shouldn't use it" and "you can't use it".
Don't get me wrong, I'm all for sticking to standards. I was just clarifying that you can use it (wasn't that what was meant by "It probably won't work"?).
Re: Share your Utils
Posted: Wed Jun 22, 2011 11:47 am
by vrld
To revive this, here's my
"sound manager" that overloads love.audio.play to create sources if a file(name) instead of a source is given as argument and manages references to the sources so you don't have to worry about them anymore when playing sound effects.
Example:
Code: Select all
function love.load()
bgm = love.audio.play("background-music.ogg", "stream", true) -- stream and loop background music and get a handle to the source
end
function love.update(dt)
love.audio.update()
end
function love.keypressed(key)
if key == 's' then
love.audio.stop(bgm)
elseif key == 'p' then
love.audio.play(bgm)
else
love.audio.play("explosion.ogg") -- play explosion sound once
end
end
I also use automatic image caching (which could also be done with kikitos
memoize.lua):
Code: Select all
IMG = setmetatable({}, {__index = function(self, key)
local res = love.graphics.newImage("img/" .. key)
rawset(self, key, res)
return res
end})
Use it like this:
Code: Select all
function love.draw()
love.graphics.draw(IMG['hamster.png'], 400,300)
end
Last but not least, here's a case statement for Lua:
Code: Select all
function case(x)
return function (of)
local what = of[x] or of.default
if type(what) == "function" then
return what()
end
return what
end
end
Example usage:
Code: Select all
self.animation_offset = case(self.anim.position) {
[2] = vector(0,-1),
[3] = vector(1,-1),
[4] = vector(1,0),
default = vector(0,0),
}
local x = case (position) {
left = 0, -- same as ['left'] = 0
center = (love.graphics.getWidth() - self.width) / 2,
right = love.graphics.getWidth() - self.width,
default = 100
}
-- function evaluation
case (key) {
up = function() player.move(0,-1) end,
down = function() player.move(0,1) end,
left = function() player.move(-1,0) end,
right = function() player.move(1,0) end,
}
Re: Share your Utils
Posted: Wed Jun 22, 2011 10:59 pm
by BlackBulletIV
Now that is some cool stuff you've got there vrld! I might use some of those.
Re: Share your Utils
Posted: Thu Jun 23, 2011 4:07 pm
by Kadoba
There's some really awesome stuff in here.
I've made a simple event class that's been really helpful to me.
Code: Select all
---------------------------------------------------------------------------------------------------
-- Event.lua
---------------------------------------------------------------------------------------------------
-- A structure that stores callback functions and calls them when triggered
---------------------------------------------------------------------------------------------------
-- Setup
local Event = {}
local next = next
local weakkey= { __mode="k" }
-- Registers a callback function for this event
-- The first parameter is the function to be called and the second optional
-- parameter is the table it should be called on.
function Event:callback(callback, obj)
local reg = self._registry
if not reg[callback] then reg[callback] = setmetatable({}, weakkey) end
if obj then
reg[callback][obj] = true
else
reg[callback].standalone = true
end
end
-- Removes a callback from the event
function Event:removeCallback(callback, obj)
local reg = self._registry
if reg[callback] and obj then
reg[callback][obj] = nil
else
reg[callback] = nil
end
end
-- Triggers all callback functions
function Event:trigger(...)
local reg = self._registry
local arg = {...}
if next(reg) == nil then return end
for callback, t in pairs(reg) do
if next(t) then
for obj,_ in pairs(t) do
if type(obj) == "table" then
if self._condition(callback, obj) then
callback(obj, unpack(arg))
end
end
end
if t.standalone then
if self._condition(callback) then
callback(unpack(arg))
end
end
end
end
end
-- Clears all callbacks
function Event:clear()
self._registry = setmetatable({}, weakkey)
end
-- Sets a condition function to test the callbacks. The function is given
-- the callback function and object as parameters and must return
-- true or false specifying if the callback should be be called or not.
function Event:setCondition(funct)
self._condition = funct
end
-- The default condition. Always just returns true
local function defaultCondition() return true end
-- Unsets the condition
function Event:unsetCondition()
self._condition = defaultCondition
end
-- Creates and returns a new event
function Event:new()
tmp = {}
tmp._registry = setmetatable({}, weakkey)
tmp._condition = defaultCondition
for k,v in pairs(Event) do
tmp[k] = v
end
return tmp
end
-- Returns the event class
return Event
Example:
Code: Select all
Event = require "Event"
-- Create some events
updateEvent = Event:new()
drawEvent = Event:new()
-- Have the love callback functions trigger events
function love.update(dt) updateEvent:trigger(dt) end
function love.draw() drawEvent:trigger() end
-- Now you can give it whatever functions you want to call when triggered:
updateEvent:callback( updateSomething )
drawEvent:callback( drawSomething )
-- You can also give an object to call the function on.
-- These call object:update() and object:draw()
updateEvent:callback(object.update, object)
drawEvent:callback(object.draw, object)
-- Sets a condition where only objects with an x value greater than 50 will be drawn.
drawEvent:setCondition( function(funct, obj) return obj.x > 50 end)
Re: Share your Utils
Posted: Thu Jun 23, 2011 4:28 pm
by slime
Re: Share your Utils
Posted: Mon Jun 27, 2011 1:20 pm
by vrld
One more:
On demand resource loading and caching.
Resources are loaded on demand by specifying a loader function. The resource will only be loaded once.
Code: Select all
local function Proxy(loader)
return setmetatable({}, {__index = function(self, k)
local v = loader(k)
rawset(self, k, v)
return v
end})
end
"Why" you ask? Because this:
Code: Select all
-- set up a few caches
Image = Proxy(function(k) return love.graphics.newImage('img/' .. k .. '.png') end)
Font = Proxy(function(k) return love.graphics.newFont('font/game_over.ttf', k) end)
State = Proxy(function(k) return assert(love.filesystem.load('states/'..k..'.lua')) end)
Sound = Proxy(function(k) return love.sound.newSoundData('sound/' .. k .. '.ogg') end)
-- now you are able to do this without prior loading of resources
love.graphics.draw(Image.player, player.x, player.y, player.angle,1,1, Image.player:getWidth()/2, Image.player:getHeight()/2)
love.graphics.setFont(Font[30])
love.graphics.print("Hello, world!", 10,10)
Gamestate.switch(State.intro) -- loads states/intro.lua which returns a gamestate. file returns a Gamestate.
-- with the "audio manager" from a few posts ago
love.audio.play(Sound.explosion)
Re: Share your Utils
Posted: Tue Jun 28, 2011 12:19 pm
by Roland_Yonaba
A simple function for Image naive-resizing...
Have Just written on-the-job for my project...
Code: Select all
function resizeImage(filename,newX,newY)
local out = love.image.newImageData(newX,newY)
local source = love.image.newImageData(filename)
local w, h = source:getWidth(), source:getHeight()
for x = 1,newX-1 do
for y = 1, newY-1 do
local intX = math.floor(x*(w/newX))
local intY = math.floor(y*(h/newY))
local r,g,b,a = source:getPixel(intX,intY)
out:setPixel(x,y,r,g,b,a)
end
end
return love.graphics.newImage(out)
end
Re: Share your Utils
Posted: Tue Jun 28, 2011 12:25 pm
by vrld
Why not set the image filter to 'nearest' and use the scale parameters in love.draw()?
Re: Share your Utils
Posted: Tue Jun 28, 2011 1:26 pm
by Roland_Yonaba
Hmm...I see.. Something like...
Code: Select all
local im = love.graphics.newImage(filename)
im:setFilter("nearest","nearest")
function love.draw()
love.graphics.draw (im,x,y,r,newX/im:getWidth(),newY/im:getHeight(),ox,oy)
end
I didn't know it could work that way. Thanks so much for the tip, it works faster for me.
makeInaccessible
Posted: Fri Jul 29, 2011 5:55 am
by vpdp_pc
First, sorry for my English
When you wanna make a entity that you save be inaccessible and show up an error when you try to access to it, here the solution:
First arg is the entity (a table), second arg is the error message you want to show up
Code: Select all
local function makeInaccessible(tb, errorMsg)
--make it nil, so the metatable below will work perfectly
for k, v in pairs(tb) do
tb[k] = nil
end
local mt = {}
local err = function () error(errorMsg, 2) end --2 here to make the error description at right code line
mt.__index = err
mt.__newindex = err
setmetatable(tb, mt)
end
One more thing: the function error(msg, level) is rock with param
level. By default level = 1, but when level = 2 (like above), it will show the correct line of you code that you access the inaccessible entity. Try to use it