ObscureWorlds Libraries

Showcase your games and demos, and discuss ongoing projects.

ObscureWorlds Libraries

Postby StoneCrow on Tue Apr 16, 2013 1:05 pm

Image
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.
User avatar
StoneCrow
Party member
 
Posts: 198
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks

Re: ObscureWorlds Libraries

Postby markgo on Tue Apr 16, 2013 1:38 pm

Hell yea! I love free stuff.
User avatar
markgo
Party member
 
Posts: 166
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Mouse Control

Postby StoneCrow on Tue Apr 16, 2013 1:47 pm

Okay first library is my mouse control library, titled ow_control.
Code: Select all
--[[
LICENCE DETAILS: ZLIB LICENCE

Copyright (c) <2012> <Lewis Pearce>

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
function nearestmenu(x,y)
   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
   local n = nearestmenu(x,y)
   
   --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
ow_controlsystem.png (235.03 KiB) Viewed 1331 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.
User avatar
StoneCrow
Party member
 
Posts: 198
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks

Saving and loading

Postby StoneCrow on Wed Apr 17, 2013 11:45 am

Okay this one is alot more like a library.
OW_rope, it reads strings and burns them.
Code: Select all
--[[
LICENCE DETAILS: ZLIB LICENCE

Copyright (c) <2011> <Lewis Pearce>

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"
---- ropeLoad("exampledirectory","examplesavefile")
----
---- 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,
---- though they need a custom loader to load and run.
----
---- 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 = {}

function rope.load(directory,savefile)
   math.randomseed(os.time())   
   
   -- you can put all the libraries your game loads here
   
   love.filesystem.setIdentity(directory)
   -- >>>
   if love.filesystem.exists(savefile) then
      rope.read(savefile)
   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,
         premenu = true,
         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

-- just the functions for loading the lua savefiles

function rope.read(item)
   love.filesystem.load(item)()
end

function rope.readandreturn(item)
   return love.filesystem.load(item)()
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,
premenu=true,
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.
User avatar
StoneCrow
Party member
 
Posts: 198
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks

Camera and useful functions

Postby StoneCrow on Fri Apr 19, 2013 3:12 pm

Okay still no feedback.
Well here's the camera code
Code: Select all
--[[
LICENCE DETAILS: ZLIB LICENCE

Copyright (c) <2012> <Lewis Pearce>

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 :ultrahappy: !
Would love to hear about any of it, though the last file of functions is a bit outdated in places.
Dull but sincere filler.
User avatar
StoneCrow
Party member
 
Posts: 198
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks

Re: ObscureWorlds Libraries

Postby DarthGrover on Wed Feb 05, 2014 11:56 pm

Thanks for the isintable library. Gregg
DarthGrover
Prole
 
Posts: 9
Joined: Wed Feb 05, 2014 11:31 pm
Location: Ohio USA

Re: ObscureWorlds Libraries

Postby StoneCrow on Mon Mar 31, 2014 9:07 pm

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.
User avatar
StoneCrow
Party member
 
Posts: 198
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks

Re: ObscureWorlds Libraries

Postby Snuux on Tue Apr 01, 2014 8:50 am

You use "table.insert" very often. And it's don't good. Read this, about lua optimizations: link
My library for easy saving Slib! Try this! Now you can encrypt your save!
Snuux
Prole
 
Posts: 24
Joined: Sun Dec 15, 2013 10:43 am
Location: Russiaa, Moskow

Re: ObscureWorlds Libraries

Postby StoneCrow on Tue Apr 01, 2014 9:20 am

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.
User avatar
StoneCrow
Party member
 
Posts: 198
Joined: Sat Apr 17, 2010 9:31 am
Location: Wales the land of leeks and leaks

Re: ObscureWorlds Libraries

Postby Jasoco on Tue Apr 01, 2014 4:59 pm

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.
Love.filesystem.enumerate is a very serious problem in our lives, we need to understand the problem about Love.filesystem.enumerate. We can discuss how to make it work, to avoid the inconvenience of our lives. -- Some Spambot
User avatar
Jasoco
Inner party member
 
Posts: 2723
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA

Next

Return to Projects and Demos

Who is online

Users browsing this forum: Rabbitturds575 and 5 guests