Share your Utils

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Share your Utils

Post 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"?).
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Share your Utils

Post 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,
}
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Share your Utils

Post by BlackBulletIV »

Now that is some cool stuff you've got there vrld! I might use some of those.
User avatar
Kadoba
Party member
Posts: 399
Joined: Mon Jan 10, 2011 8:25 am
Location: Oklahoma

Re: Share your Utils

Post 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)
User avatar
slime
Solid Snayke
Posts: 3144
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Share your Utils

Post by slime »

Here's my event library.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Share your Utils

Post 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)
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Share your Utils

Post 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
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Share your Utils

Post by vrld »

Why not set the image filter to 'nearest' and use the scale parameters in love.draw()?
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Share your Utils

Post 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.
vpdp_pc
Prole
Posts: 15
Joined: Fri Jul 29, 2011 5:39 am

makeInaccessible

Post 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 :awesome:
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 1 guest