ObscureWorlds Libraries

StoneCrow
Party member
Posts: 199
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks
Contact:

ObscureWorlds Libraries

Rather than cling onto them for my personal projects, would the community here be interested in the varied libraries I use for different projects accompanied with information on their use and creation?

I have libraries (if thats the right word) for: And a program framework that can load other games into itself like a hub viewable here, useful for project packs.
Everything would be released under zlib license.
Last edited by StoneCrow on Fri Apr 19, 2013 3:13 pm, edited 3 times in total.
Dull but sincere filler.

markgo
Party member
Posts: 189
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Re: ObscureWorlds Libraries

Hell yea! I love free stuff.

StoneCrow
Party member
Posts: 199
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks
Contact:

Mouse Control

Okay first library is my mouse control library, titled ow_control.

Code: Select all

--[[
LICENCE DETAILS: ZLIB LICENCE

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source
distribution.
]]

-- HOLDS ALL GAME CONTROLS AND SOME FUNCTIONS RELATING TO THEM

-- interaction tables used by the menu system example
-- this is how i would use it myself
--[[
startuptable = { -- table key/name, for distinction, but tables without names can be fed straight into currenttable
{x=100,y=70,w=600,h=80,action={"pre","rwrinfo"},},  -- position and size, with action telling what peice of code to use with it, action here has 2 entries the section and the actual action, this just lets me distinguish sections in the mouseAction function, but it can be coded to distinguish on table name/key instead
}
]]

-- currenttable to draw menu style interactions from
-- place in main.lua
-- more tables can be added to this but the detection functions return the last detection they make, allowing overlay menus to work without tinkery provided they are last in the currenttable list.
--currenttable = {startuptable}

-- click area detection functions for menu code
return nearestestui(x,y,currenttable)
end

function nearestestui(x,y,table)
local id = null

for i = 1,#table do
for i,v in ipairs(table[i]) do
if checkCollision(x,y,1,1,v.x,v.y,v.w,v.h) == true then
id = {i,j,v.action}
end
end
end
return id
end

--input library for mousepresses
-- bashes the information straight through to the mouseAction below, but exceptions can be added so that it doesn't in some circumstances
function love.mousepressed(x,y,button)
mouseAction(x,y,button)
end

function love.mousereleased(x,y,button)
if button == "m" then
mouseAction(x,y,5)
end
end

-- HUD DETECTION CODE

--SUPERFUNCTION
--controls all of the mouse actions within the editor
--a bit cryptic but not to hard to understand
function mouseAction(x,y,act)
-- this just gets what your currently clicking on from the tables your testing at the moment

--NULL INPUT
--stops it from crashing if theres nothing at click
if n ~= null then
if n[3][1] == "pre" then -- test one used as a distinction
if n[3][2] == "rwrinfo" then -- test two used to work out the command
-- STUFF TO DO HERE
end
end
end
end
Above is the version that uses two entries in action to distinguish which part of mouseAction to go to, though it could use the key of the tables easily with minor modifications to mouseAction and nearestestui, I've just found that making sections independent from table saves alot of repeat code.
Would love any critique on this as I'm always expanding and simplifying its style, I'm aware that it is a very dry system that requires setting up for each project and page but I find this makes it more powerful just slower to enable and set up, though outside dependancies and a creator for the actual menutables could easily be written in.

This was developed over about 5 or 6 failed projects which required large and varied ability menus, huds and ui's. The original version was infact incredibly huge and about double the size of this due to no simplification or anything, I personally love this system and combined with a debug function shared below can be added and modified very very easily and rapidly.

The debug system just added to the bottom of love.graphics.draw(), you have to set the value "debug" as debug = true and create a font of size 11 called font11 to make it work, but it can be switched off by just setting debug to false.

Code: Select all

if debug then
-- currenttable highlights
love.graphics.setColor(255,255,255,100)
love.graphics.setFont(font11)

for i=1,#currenttable do
for i,v in ipairs(currenttable[i]) do
love.graphics.rectangle("fill",v.x,v.y,v.w,v.h)
end
end

-- infopanel
local temp = "FPS: "..love.timer.getFPS()..". x:"..mx..". y:"..my.."."
if (mx+font11:getWidth(temp)) < love.graphics.getWidth() then
love.graphics.setColor(0,30,100,150)
love.graphics.rectangle("fill",mx+10,my-0,font11:getWidth(temp),11)
love.graphics.setColor(200,255,255,255)
love.graphics.rectangle("line",mx+10,my+0,font11:getWidth(temp),11)
love.graphics.print(temp,mx+10,my+0)
else
love.graphics.setColor(0,30,100,150)
love.graphics.rectangle("fill",mx-(font11:getWidth(temp)+10),my-0,font11:getWidth(temp),11)
love.graphics.setColor(200,255,255,255)
love.graphics.rectangle("line",mx-(font11:getWidth(temp)+10),my+0,font11:getWidth(temp),11)
love.graphics.print(temp,mx-(font11:getWidth(temp)+10),my+0)
end
temp = nil
end
Finally here is an image of a menu created recently with this version of the system and with the debug module turned on.
ow_controlsystem.png (235.03 KiB) Viewed 4556 times
It can also be viewed by pressing f1 in audiotree or f1/f2 in most of my programs.

If this is useful or interesting to anyone I will soon release the next block of code.
Last edited by StoneCrow on Fri Apr 19, 2013 3:14 pm, edited 1 time in total.
Dull but sincere filler.

StoneCrow
Party member
Posts: 199
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks
Contact:

Okay this one is alot more like a library.
OW_rope, it reads strings and burns them.

Code: Select all

--[[
LICENCE DETAILS: ZLIB LICENCE

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source
distribution.
]]

---- EXAMPLE OF HOW TO USE THIS TABLE
----
---- require "ow_rope.lua"
----
---- and saving works like this
---- love.filesystem.write(savefilename,"name of table="..rope.burn(name of table))
---- although this seems basic, the rope.burn function can save almost every table without errors to lua or other txt formats,
----
---- rope.load sets up your directory and loads a settings file. It can also be changed in much the same way mouseAction
---- is meant to be changed for each  project, easily allowing you to add code calls based on the settings.
---- although only supporting saving in lua natively may leave programs open to the lua code security holes with downloaded save files,
---- its designed in such a way where the file should always be made on your computer and any downloaded savefiles are at the users risk

rope = {}

math.randomseed(os.time())

love.filesystem.setIdentity(directory)
-- >>>
if love.filesystem.exists(savefile) then
elseif not love.filesystem.exists(savefile) then
-- place what you want the default settings for this file here
love.filesystem.mkdir("sandbox")
love.filesystem.mkdir("challenge")

settings = {
fullscreen=false,
colour = {{255,255,255},{0,0,0}},
currentres = {800,600,1},
canvases = true,
volume = 0.3,
subsettings = {
showbranchpos = false
}
}
--use this bit to save in other ways
love.filesystem.write(savefile,"settings="..rope.burn(settings))
end

-- <<<
-- if you need to set up actions after save/settings load do them here, eg, if settings.fullscreen then love.graphics.toggleFullscreen() end

end

-- tables must be compatible with rope.burn

function rope.burn(t)
local data = {}
if type(t) == "number" then
return t
elseif type(t) == "boolean" then
if t then
return "true"
elseif not t then
return "false"
end
elseif type(t) == "string" then
return t
elseif type(t) == "table" then
local data = {}
table.insert(data,"{\n")
for k,v in pairs(t) do
if type(k) ~= "number" and type(v) ~= "function" then
local k_info = rope.burn(k)
local v_info = rope.burn(v)
if type(v) == "string" then
v_info = '"'..v_info..'"'
end
table.insert(data,k_info)
table.insert(data,"=")
table.insert(data,v_info)
table.insert(data,",\n")
k_info,v_info = nil,nil
elseif type(k) == "number" and type(v) == "table" then
local v_info = rope.burn(v)
table.insert(data,v_info)
table.insert(data,",\n")
v_info = nil
elseif type(k) == "number" and type(v) == "number" then
local v_info = rope.burn(v)
table.insert(data,v_info)
table.insert(data,",\n")
v_info = nil
elseif type(k) == "number" and type(v) == "boolean" then
local v_info = rope.burn(v)
table.insert(data,v_info)
table.insert(data,",\n")
v_info = nil
elseif type(k) == "number" and type(v) == "string" then
local v_info = rope.burn(v)
table.insert(data,'"'..v_info..'"')
table.insert(data,",\n")
v_info = nil
end
end
table.insert(data,"\n}")
return table.concat(data)
end
end

end

end
The code is designed to save in lua and read in lua and hasn't been tested for other formats though I imagine it could save tables to most formats but reading them would need a custom reader using rope.readandreturn.

This was developed the first time I needed a persistent setting file for a program, so the rope.load is designed purposely for that.
Though I've used rope.burn for lots of things after that. The ability to save strings and keys was added in later.

To check if the savefile saves correctly just go to the save directory and load it into a text editor, if saved correctly it should be easily readable and if saved in lua should load in and out of your program without issue.
A successful save setup should look like this:

Code: Select all

settings={
fullscreen=false,
currentres={
800,
600,
4,
},
canvases=true,
subsettings={
showbranchpos=true,
},
volume=0.5,
colour={
{
60,
10,
10,
},
{
255,
90,
15,
},
},
}
I'm gonna wait till I get some feedback to post the next library
Last edited by StoneCrow on Fri Apr 19, 2013 3:15 pm, edited 2 times in total.
Dull but sincere filler.

StoneCrow
Party member
Posts: 199
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks
Contact:

Camera and useful functions

Okay still no feedback.
Well here's the camera code

Code: Select all

--[[
LICENCE DETAILS: ZLIB LICENCE

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source
distribution.
]]

-- just load the table and keep the use of the name camera free
-- also uses mx and my as the mouse positions just add something that names them as the camera positions like mx = love.mouse.getX() in update

camera = {}

camera.mode = {"edges"}

camera.pos = {
x = 0, --xpos
y = 0, --ypos
s = 1, --scale
}

-- just add this to love.update(dt)
function camera.update(dt)
for i,v in ipairs(camera.mode) do
if v == "edge" then
if mx <= 10 and camera.pos.x > 0 then
camera.pos.x = camera.pos.x - (100*dt)
elseif mx >= settings.currentres[1]-10 then
camera.pos.x = camera.pos.x + (100*dt)
end
end
end
end
This is a really simple section of code. I figured would just be more useful as an example to anyone of how to create and manage a camera function set, because writing it was something that threw me a year or two ago when I first wrote this kind of thing.

to enable it just follow the instructions in the code above and add the code below to love.draw()

Code: Select all

love.graphics.push()
love.graphics.translate(-camera.pos.x,-camera.pos.y)
love.graphics.scale(camera.pos.s,camera.pos.s)

-- graphics code affected by the translations

love.graphics.pop()

-- ui stuff or things that aren't affected
Finally I'll just post my functions collection file, this is just a few functions I find myself using over and over again in different projects. No license on this one so feel free to steal, some of it I've scavenged from all over the place myself.

Code: Select all

-- Enumerates the contents of a folder into a table, printf-able if you add the filetree variable

function recursiveEnumerate(folder, fileTree)
local fileTree = fileTree or null
local lfs = love.filesystem
local filesTable = lfs.enumerate(folder)
if fileTree == null then
return filesTable
else
for i,v in ipairs(filesTable) do
local file = folder.."/"..v
if lfs.isFile(file) then
fileTree = fileTree.."\n"..file
elseif lfs.isDirectory(file) then
fileTree = fileTree.."\n"..file.." (DIR)"
fileTree = recursiveEnumerate(file, fileTree)
end
end
return filetree
end
end

-- SPLITS STRINGS INTO LETTERS OR WITH AN ITERATOR

function stringsplit(input,iterator)
iterator = iterator or "."
local output = {}
for word in input:gmatch(iterator) do
table.insert(output, word)
end
return output
end

-- Y ORDERING

function ysort (a,b)
return a.y>b.y
end

-- INVERT NUMBER
function math.invert(item,maxvalue) --item is the number and maxvalue is the top point of its range to invert it around
return maxvalue - item
end

-- REVERSE NUMBER

function math.reverse(item)
return -item
end

-- ROUNDING TO NEAREST

function roundtointeger(item)
local integer, fraction = math.modf(item)
if fraction >= 5 then
integer = integer + 1
end
return integer
end

-- finds matching variables accross a table and puts their positions into a table
function findvar(data,pos,var)
local output = {}
for i,v in ipairs(data) do
if v.pos == var then
table.insert(output,i)
end
end
return output
end

-- BOX COLLISIONS

-- this is from the love2d wiki
-- Collision detection function.
-- Checks if box1 and box2 overlap.
-- w and h mean width and height.
function checkCollision(box1x, box1y, box1w, box1h, box2x, box2y, box2w, box2h)
if box1x > box2x + box2w - 1 or -- Is box1 on the right side of box2?
box1y > box2y + box2h - 1 or -- Is box1 under box2?
box2x > box1x + box1w - 1 or -- Is box2 on the right side of box1?
box2y > box1y + box1h - 1    -- Is b2 under b1?
then
return false                -- No collision. Yay!
else
return true                 -- Yes collision. Ouch!
end
end

-- SLIDER FUNCTION

-- moves 1 towards 2 over time
-- 3 is the speed
-- to use add the slider function to the update area
-- and define sliderinfo = {}
-- I.E sliderinfo = {{start,destination,speed}}

function slider(dt)
if #sliderinfo > 0 then
for i,v in ipairs(sliderinfo) do
if v[1] ~= v[2] then
if v[1] > v[2] then
v[1] = v[1] - (v[3]*dt)
if v[1] < v[2] then
v[1] = v[2]
end
elseif v[1] < v[2] then
v[1] = v[1] + (v[3]*dt)
if v[1] > v[2] then
v[1] = v[2]
end
end
end
end
end
end

-- TEST IF SOMETHING IS ALREADY IN A TABLE
-- used to see if something should be added or not

function isintable(item,table,posi)
local posi = posi or false
local output = false
if posi == false then
for i,v in ipairs(table) do
if v == item then
output = true
end
end
else
for i,v in ipairs(table) do
if v[posi] == item then
output = true
end
end
end
posi = nil
return output
end

-- same as above but returns its position

function whereintable(item,table)
local output = null
for i,v in ipairs(table) do
if v == item then
output = i
end
end
return output
end
Thanks everyone who has had a look at this code !
Would love to hear about any of it, though the last file of functions is a bit outdated in places.
Dull but sincere filler.

DarthGrover
Prole
Posts: 16
Joined: Wed Feb 05, 2014 11:31 pm
Location: Ohio USA

Re: ObscureWorlds Libraries

Thanks for the isintable library. Gregg

StoneCrow
Party member
Posts: 199
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks
Contact:

Re: ObscureWorlds Libraries

Would anyone be interested in a breakdown of how my scenes/states library works?

I feel like I actually have a really comfortable and easy to use system here for loading different what I'm referring internally to as "states". If you have ever used Corona for mobiles you may recognise the use of this, as this is kind of my dream of how I wished that had worked.

In short each state has its own attached functions that correlate to love functions like update, draw or mouse, physically separating themselves and allowing different bits of your game to be easily loaded and dropped (think menu's, backgrounds, levels).

They also support:
rapid removal of themselves (not completely ironed out, full support but would be easy enough to do),

automatic fading of the entire state with minimum extra legwork within the state,

This is all possible by calling a "name" you gave the state when you loaded it (names cannot be the same for different states),

Setting their position in the draw order of states easily,
The main negative for some people might of course be the slight performance issue associated with the additional functions, but for the kind of games I write I haven't had a single performance issue yet and it's been the best thing I've designed for my work speed since I started programming.
Dull but sincere filler.

Snuux
Prole
Posts: 49
Joined: Sun Dec 15, 2013 10:43 am
Location: Russia, Moskow
Contact:

Re: ObscureWorlds Libraries

My library for easy saving Slib! Try this! Now you can encrypt your save!
- Drop of light LD#30
- OUTRANGE LD#31
(Sorry for my english. I learn it myself, and I don't have enough experience)

StoneCrow
Party member
Posts: 199
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks
Contact:

Re: ObscureWorlds Libraries

Yeah I do, if I got to a point where a project was complex and slow enough I would begin to optimize. So far it hasn't been a problem for me on LÖVE.
Dull but sincere filler.

Jasoco
Inner party member
Posts: 3650
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: ObscureWorlds Libraries

You just have to realize what table.insert and table.remove are doing. Using them a lot can become a bottleneck because they're essentially reordering entire tables every time you use them. Say you have a table with 1000 items and you remove number 5. What happens is the function now takes everything from 6 to 1000 and moves them all forward by 1 one at a time. And if you try to insert something back in at say slot 3, you are now moving 3-999 up 1 position in order to make room. It might not be a speed problem for small tables and small games but used a lot all that time can add up.

Removing or adding to the end will be faster than removing or adding to the beginning, but still.

Who is online

Users browsing this forum: Bing [Bot] and 19 guests