Difference between revisions of "Ftf libs"
From GiderosMobile
Line 167: | Line 167: | ||
end) | end) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | == KEY REMAPPING WITH SAVE DATA == | ||
+ | In this ''Settings'' scene we can remap any predefined keys. You can navigate using the arrows on your keyboard and press '''ENTER''' to remap a key. | ||
+ | |||
+ | Once you have remapped the keys, the new settings are save to a file which will be read everytime you restart the game. | ||
+ | |||
+ | '''Code using [[ButtonMonster class|ButtonMonster]]''' | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | -- *** SAVING AND LOADING DATA IN JSON FORMAT *** | ||
+ | require "json" -- don't forget to add the JSON plugin in your project | ||
+ | |||
+ | function saveData(filepath, value) | ||
+ | local contents = json.encode(value) | ||
+ | local file = io.open(filepath, "w") -- create file | ||
+ | file:write(contents) -- save json string in file | ||
+ | io.close(file) | ||
+ | end | ||
+ | |||
+ | function getData(filepath) | ||
+ | local value | ||
+ | local file = io.open(filepath, "r") | ||
+ | if file then | ||
+ | local contents = file:read("*a") -- read contents | ||
+ | value = json.decode(contents) -- decode json | ||
+ | io.close(file) | ||
+ | end | ||
+ | return value | ||
+ | end | ||
+ | |||
+ | -- *** LOADING AND SAVING USER PREFS DATA *** | ||
+ | -- global prefs functions | ||
+ | function myLoadPrefs(xconfigfilepath) | ||
+ | local mydata = getData(xconfigfilepath) -- try to read information from file | ||
+ | if not mydata then -- if no prefs file, create it | ||
+ | mydata = {} | ||
+ | -- set prefs | ||
+ | mydata.g_language = g_language | ||
+ | -- controls | ||
+ | mydata.g_keyleft = g_keyleft | ||
+ | mydata.g_keyright = g_keyright | ||
+ | mydata.g_keyup = g_keyup | ||
+ | mydata.g_keydown = g_keydown | ||
+ | mydata.g_keyaction1 = g_keyaction1 | ||
+ | mydata.g_keyaction2 = g_keyaction2 | ||
+ | mydata.g_keyaction3 = g_keyaction3 | ||
+ | -- save prefs | ||
+ | saveData(xconfigfilepath, mydata) -- create file and save data | ||
+ | else -- prefs file exists, use it! | ||
+ | -- set prefs | ||
+ | g_language = mydata.g_language | ||
+ | -- controls | ||
+ | g_keyleft = mydata.g_keyleft | ||
+ | g_keyright = mydata.g_keyright | ||
+ | g_keyup = mydata.g_keyup | ||
+ | g_keydown = mydata.g_keydown | ||
+ | g_keyaction1 = mydata.g_keyaction1 | ||
+ | g_keyaction2 = mydata.g_keyaction2 | ||
+ | g_keyaction3 = mydata.g_keyaction3 | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function mySavePrefs(xconfigfilepath) | ||
+ | local mydata = {} -- clear the table | ||
+ | -- set prefs | ||
+ | mydata.g_language = g_language | ||
+ | -- controls | ||
+ | mydata.g_keyleft = g_keyleft | ||
+ | mydata.g_keyright = g_keyright | ||
+ | mydata.g_keyup = g_keyup | ||
+ | mydata.g_keydown = g_keydown | ||
+ | mydata.g_keyaction1 = g_keyaction1 | ||
+ | mydata.g_keyaction2 = g_keyaction2 | ||
+ | mydata.g_keyaction3 = g_keyaction3 | ||
+ | -- save prefs | ||
+ | saveData(xconfigfilepath, mydata) -- save new data | ||
+ | end | ||
+ | |||
+ | -- initial default global prefs values | ||
+ | g_configfilepath = "|D|configfile.txt" -- data are saved in this file (in the Document app folder) | ||
+ | g_language = application:getLanguage() | ||
+ | g_keyleft = KeyCode.LEFT | ||
+ | g_keyright = KeyCode.RIGHT | ||
+ | g_keyup = KeyCode.UP | ||
+ | g_keydown = KeyCode.DOWN | ||
+ | g_keyaction1 = KeyCode.D -- punch1 | ||
+ | g_keyaction2 = KeyCode.S -- punch1 | ||
+ | g_keyaction3 = KeyCode.Q -- jump/jump punch1 | ||
+ | |||
+ | -- load saved prefs from file (|D|configfile.txt) | ||
+ | myLoadPrefs(g_configfilepath) -- override default values by saved values if any | ||
+ | |||
+ | -- *** GLOBAL FONT AND UI THEME FOR BUTTONS *** | ||
+ | myttf = TTFont.new("fonts/Cabin-Regular-TTF.ttf", 2.8*8) -- UI | ||
+ | g_ui_theme = {} | ||
+ | g_ui_theme.pixelcolorup = 0x8d595d | ||
+ | g_ui_theme.pixelcolordown = 0xc09c98 | ||
+ | g_ui_theme.textcolorup = 0xd9d2cb | ||
+ | g_ui_theme.textcolordown = 0xd9d2cb | ||
+ | g_ui_theme._textcolordisabled = 0xd9d2cb | ||
+ | g_ui_theme.tooltiptextcolor = 0x3a1d20 | ||
+ | g_ui_theme.tooltipoffsetx = -7*8 | ||
+ | g_ui_theme.tooltipoffsety = 1*4 | ||
+ | |||
+ | -- *** THE OPTIONS SCENE (Class) *** | ||
+ | Options = Core.class(Sprite) | ||
+ | |||
+ | local keyNames = { -- display a friendly key name | ||
+ | [KeyCode.LEFT] = "LEFT", | ||
+ | [KeyCode.RIGHT] = "RIGHT", | ||
+ | [KeyCode.UP] = "UP", | ||
+ | [KeyCode.DOWN] = "DOWN", | ||
+ | [KeyCode.NUM0] = "NUMPAD 0", | ||
+ | [KeyCode.NUM1] = "NUMPAD 1", | ||
+ | [KeyCode.NUM2] = "NUMPAD 2", | ||
+ | [KeyCode.NUM3] = "NUMPAD 3", | ||
+ | [KeyCode.NUM4] = "NUMPAD 4", | ||
+ | [KeyCode.NUM5] = "NUMPAD 5", | ||
+ | [KeyCode.NUM6] = "NUMPAD 6", | ||
+ | [KeyCode.NUM7] = "NUMPAD 7", | ||
+ | [KeyCode.NUM8] = "NUMPAD 8", | ||
+ | [KeyCode.NUM9] = "NUMPAD 9", | ||
+ | [KeyCode.SPACE] = "SPACE", | ||
+ | [KeyCode.SHIFT] = "SHIFT", | ||
+ | [KeyCode.CTRL] = "CONTROL", | ||
+ | [KeyCode.ALT] = "ALT", | ||
+ | [KeyCode.TAB] = "TAB", | ||
+ | } | ||
+ | |||
+ | function Options:init() | ||
+ | -- bg | ||
+ | application:setBackgroundColor(0x232a35) | ||
+ | -- tooltip layer | ||
+ | local tooltiplayer = Sprite.new() | ||
+ | -- buttons | ||
+ | local key | ||
+ | -- movement | ||
+ | if (keyNames[g_keyleft] or 0) == 0 then key = utf8.char(g_keyleft) | ||
+ | else key = keyNames[g_keyleft] | ||
+ | end -- display a friendly key name | ||
+ | self.btnLEFT = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="left", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 2, tooltiplayer) | ||
+ | if (keyNames[g_keyright] or 0) == 0 then key = utf8.char(g_keyright) | ||
+ | else key = keyNames[g_keyright] | ||
+ | end -- display a friendly key name | ||
+ | self.btnRIGHT = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="right", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 3, tooltiplayer) | ||
+ | if (keyNames[g_keyup] or 0) == 0 then key = utf8.char(g_keyup) | ||
+ | else key = keyNames[g_keyup] | ||
+ | end -- display a friendly key name | ||
+ | self.btnUP = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="up", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 1, tooltiplayer) | ||
+ | if (keyNames[g_keydown] or 0) == 0 then key = utf8.char(g_keydown) | ||
+ | else key = keyNames[g_keydown] | ||
+ | end -- display a friendly key name | ||
+ | self.btnDOWN = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="down", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 4, tooltiplayer) | ||
+ | -- actions | ||
+ | if (keyNames[g_keyaction1] or 0) == 0 then key = utf8.char(g_keyaction1) | ||
+ | else key = keyNames[g_keyaction1] | ||
+ | end -- display a friendly key name | ||
+ | self.btnACTION1 = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="punch1", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 5, tooltiplayer) | ||
+ | if (keyNames[g_keyaction2] or 0) == 0 then key = utf8.char(g_keyaction2) | ||
+ | else key = keyNames[g_keyaction2] | ||
+ | end -- display a friendly key name | ||
+ | self.btnACTION2 = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="punch2", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 6, tooltiplayer) | ||
+ | if (keyNames[g_keyaction3] or 0) == 0 then key = utf8.char(g_keyaction3) | ||
+ | else key = keyNames[g_keyaction3] | ||
+ | end -- display a friendly key name | ||
+ | self.btnACTION3 = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=17*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown, | ||
+ | tooltiptext="jump punch", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 7, tooltiplayer) | ||
+ | -- btn menu | ||
+ | self.btnMENU = ButtonMonster.new({ | ||
+ | autoscale=false, pixelwidth=12*8, pixelheight=6*8, | ||
+ | pixelscalexup=0.8, pixelscalexdown=0.9, | ||
+ | pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown, | ||
+ | text="MENU", ttf=myttf, textcolorup=0x0009B3, textcolordown=0x45d1ff, | ||
+ | tooltiptext="Enter", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor, | ||
+ | tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety, | ||
+ | }, 8, tooltiplayer) | ||
+ | -- btns table | ||
+ | self.btns = {} | ||
+ | self.btns[#self.btns + 1] = self.btnUP -- 1 | ||
+ | self.btns[#self.btns + 1] = self.btnLEFT -- 2 | ||
+ | self.btns[#self.btns + 1] = self.btnRIGHT -- 3 | ||
+ | self.btns[#self.btns + 1] = self.btnDOWN -- 4 | ||
+ | self.btns[#self.btns + 1] = self.btnACTION1 -- 5 | ||
+ | self.btns[#self.btns + 1] = self.btnACTION2 -- 6 | ||
+ | self.btns[#self.btns + 1] = self.btnACTION3 -- 7 | ||
+ | self.btns[#self.btns + 1] = self.btnMENU -- 8 | ||
+ | self.selector = 1 -- starting button | ||
+ | -- position | ||
+ | self.btnLEFT:setPosition(1.5*myappwidth/10, 6*8+6*myappheight/10) -- 2 | ||
+ | self.btnRIGHT:setPosition(3.5*myappwidth/10, 6*8+6*myappheight/10) -- 3 | ||
+ | self.btnUP:setPosition(2.5*myappwidth/10, 6*8+4.6*myappheight/10) -- 1 | ||
+ | self.btnDOWN:setPosition(2.5*myappwidth/10, 6*8+7.4*myappheight/10) -- 4 | ||
+ | for i = 5, 7 do -- action buttons | ||
+ | self.btns[i]:setPosition(5.6*myappwidth/10, (i-5)*6*8+6*myappheight/10) | ||
+ | end | ||
+ | self.btnMENU:setPosition(myappwidth - self.btnMENU:getWidth()/2, myappheight - self.btnMENU:getHeight()/2) | ||
+ | -- order | ||
+ | for k, v in ipairs(self.btns) do self:addChild(v) end | ||
+ | self:addChild(tooltiplayer) | ||
+ | -- buttons listeners | ||
+ | for k, v in ipairs(self.btns) do | ||
+ | -- v:addEventListener("pressed", function() self.selector = k self:goto() end) | ||
+ | v:addEventListener("clicked", function() self.selector = k self:goto() end) | ||
+ | v:addEventListener("hovered", function(e) self.selector = e.currselector end) | ||
+ | v.btns = self.btns -- FOR KEYBOARD NAVIGATION! | ||
+ | end | ||
+ | -- let's go! | ||
+ | self.isremapping = false | ||
+ | self:myKeysPressed() | ||
+ | self:updateButton() | ||
+ | end | ||
+ | |||
+ | -- key remapping | ||
+ | function Options:remapKey(xbool) | ||
+ | local btn = self.btns[self.selector] | ||
+ | if xbool then | ||
+ | self.isremapping = true | ||
+ | btn:setColorTransform(255/255, 255/255, 0/255, 255/255) | ||
+ | else | ||
+ | btn:setColorTransform(255/255, 255/255, 255/255, 255/255) | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- update button state | ||
+ | function Options:updateButton() | ||
+ | for k, v in ipairs(self.btns) do | ||
+ | v.currselector = self.selector | ||
+ | v:updateVisualState() | ||
+ | if k == self.selector then v:selectionSfx() end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- KEYS HANDLER | ||
+ | function Options:myKeysPressed() | ||
+ | self:addEventListener(Event.KEY_DOWN, function(e) | ||
+ | if self.isremapping then -- KEY REMAPPING | ||
+ | if e.keyCode == KeyCode.ESC then | ||
+ | self.isremapping = false | ||
+ | self:remapKey(self.isremapping) | ||
+ | self:updateButton() | ||
+ | return | ||
+ | end | ||
+ | local keycode = e.keyCode | ||
+ | local key = keyNames[keycode] | ||
+ | if (keyNames[keycode] or 0) == 0 then key = utf8.char(keycode) end | ||
+ | self.btns[self.selector]:changeText(key) | ||
+ | if self.selector == 1 then g_keyup = keycode -- follows self.btns order | ||
+ | elseif self.selector == 2 then g_keyleft = keycode -- follows self.btns order | ||
+ | elseif self.selector == 3 then g_keyright = keycode -- follows self.btns order | ||
+ | elseif self.selector == 4 then g_keydown = keycode -- follows self.btns order | ||
+ | elseif self.selector == 5 then g_keyaction1 = keycode -- follows self.btns order | ||
+ | elseif self.selector == 6 then g_keyaction2 = keycode -- follows self.btns order | ||
+ | elseif self.selector == 7 then g_keyaction3 = keycode -- follows self.btns order | ||
+ | end | ||
+ | self.isremapping = false | ||
+ | self:remapKey(self.isremapping) | ||
+ | self:updateButton() | ||
+ | mySavePrefs(g_configfilepath) | ||
+ | else -- NOT KEY REMAPPING | ||
+ | if e.keyCode == KeyCode.ESC then self:back() end | ||
+ | -- keyboard | ||
+ | if e.keyCode == KeyCode.UP or e.keyCode == g_keyup or e.keyCode == KeyCode.LEFT or e.keyCode == g_keyleft then | ||
+ | self.selector -= 1 if self.selector < 1 then self.selector = #self.btns end | ||
+ | self:updateButton() | ||
+ | elseif e.keyCode == KeyCode.DOWN or e.keyCode == g_keydown or e.keyCode == KeyCode.RIGHT or e.keyCode == g_keyright then | ||
+ | self.selector += 1 if self.selector > #self.btns then self.selector = 1 end | ||
+ | self:updateButton() | ||
+ | end | ||
+ | -- modifier | ||
+ | local modifier = application:getKeyboardModifiers() | ||
+ | local alt = (modifier & KeyCode.MODIFIER_ALT) > 0 | ||
+ | if not alt and (e.keyCode == KeyCode.ENTER or e.keyCode == KeyCode.SPACE or e.keyCode == g_keyaction1) then -- validate | ||
+ | self:goto() | ||
+ | end | ||
+ | end | ||
+ | end) | ||
+ | end | ||
+ | |||
+ | -- scenes navigation | ||
+ | function Options:goto() | ||
+ | for k, v in ipairs(self.btns) do | ||
+ | if k == self.selector then | ||
+ | if v.isdisabled then print("btn disabled!", k) | ||
+ | elseif k >= 1 and k <= #self.btns-1 then self:remapKey(true) -- player1 controls/actions | ||
+ | elseif k == #self.btns then self:back() -- last button is go back to menu scene | ||
+ | else print("nothing here!", k) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | function Options:back() | ||
+ | print("SWITCH TO MENU SCENE") | ||
+ | -- scenemanager:changeScene("menu", 1, transitions[1], easings[3]) | ||
+ | end | ||
+ | |||
+ | -- *** START THE SCENE *** | ||
+ | stage:addChild(Options.new()) | ||
+ | </syntaxhighlight> | ||
+ | |||
Revision as of 13:16, 23 October 2024
Here are some longer code (classes) from the Gideros forum and some other places :-)
All samples are ready to use. Enjoy!
GFX
Hex to Number / Number to Hex
--[[
Lua Hex v0.4
-------------------
Hex conversion lib for Lua.
How to use:
lhex.to_hex(n) -- convert a number to a hex string
lhex.to_dec(hex) -- convert a hex "string" (prefix with "0x..." or "0X...") to number
Part of LuaBit(http://luaforge.net/projects/bit/).
Under the MIT license.
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
--]]
local function to_bits(n)
-- checking not float
if(n - (n//1) > 0) then error("trying to apply bitwise operation on non-integer!") end
if(n < 0) then return to_bits(~(n//1) + 1) end -- negative
-- to bits table
local tbl = {}
local cnt = 1
while (n > 0) do
local last = n%2
if(last == 1) then tbl[cnt] = 1
else tbl[cnt] = 0
end
n = (n-last)/2
cnt += 1
end
return tbl
end
local function tbl_to_number(tbl)
local n = #tbl
local rslt = 0
local power = 1
for i = 1, n do
rslt += tbl[i]*power
power *= 2
end
return rslt
end
local function to_hex(n)
if(type(n) ~= "number") then error("non-number type passed in.") end
-- checking not float
if(n - (n//1) > 0) then error("trying to apply bitwise operation on non-integer!") end
if(n < 0) then -- negative
n = to_bits(~(-n<>n) + 1)
n = tbl_to_number(n)
end
local hex_tbl = { "A", "B", "C", "D", "E", "F" }
local hex_str = ""
while(n ~= 0) do
local last = n%16
if(last < 10) then hex_str = tostring(last) .. hex_str
else hex_str = hex_tbl[last-10+1] .. hex_str
end
n = (n/16)//1 -- floor
end
if(hex_str == "") then hex_str = "0" end
return "0x"..hex_str
end
local function to_dec(hexstring)
if(type(hexstring) ~= "string") then error("non-string type passed in.") end
local head = string.sub(hexstring, 1, 2)
if(head ~= "0x" and head ~= "0X") then error("wrong hex format, should lead by 0x or 0X.") end
return tonumber(hexstring:sub(3), 16) -- base 16
end
--------------------
-- lua hex lib interface
lhex = {
to_hex=to_hex,
to_dec=to_dec,
}
--------------------
-- examples
local dec = 4341688
local hex = lhex.to_hex(dec) -- number to hex
print(hex) -- 0x423FB8
local revdec = lhex.to_dec(hex) -- hex string (prefix with "0x" or "0X") to number
print(revdec) -- 4341688
print(lhex.to_dec("0x0")) -- 0, hex string (prefix with "0x" or "0X") to number
print(lhex.to_dec("0x00ff00")) -- 65280, hex string (prefix with "0x" or "0X") to number
print(lhex.to_hex(16777215)) -- 0xFFFFFF, number to hex
local pix = Pixel.new(lhex.to_hex(56816), 1, 32, 32)
stage:addChild(pix)
print("hex is", hex)
FILES
Get Files in Folder @xxx
note: requires the Lfs plugin
Gets all the files in a folder matching a file extension and store them in a list.
local myos = application:getDeviceInfo()
local iswin32 = if myos == "win32" then true else false
--print(iswin32)
function getFilesInFolder(xpath, xlist)
local lfs = require "lfs"
for file in lfs.dir(xpath) do
if file ~= "." and file ~= ".." then
if file:match(".png$") then -- choose your file extension here
if iswin32 then
local f = xpath.."\\"..file
-- print(f)
xlist[#xlist + 1] = f:gsub("/", "\\")
else
local f = xpath.."/"..file
-- print(f)
xlist[#xlist + 1] = f:gsub("\\", "/")
end
end
end
end
lfs = nil
end
Demo code using ButtonMonster
local myos = application:getDeviceInfo()
local iswin32 = if myos == "win32" then true else false
--print(iswin32)
local folderimages = {} -- list all images in user selected folder
local images = {} -- list all images with valid extension
local btnimagefolder = ButtonMonster.new({
pixelcolorup=0xffaa00, text="import images", textcolorup=0xaa0000, textscalex=3,
isautoscale=true,
})
btnimagefolder:setPosition(16, 16)
stage:addChild(btnimagefolder)
btnimagefolder:addEventListener("clicked", function()
local path
if iswin32 then path = application:get("openDirectoryDialog", "Select Folder", "C:\\tmp\\")
else path = application:get("openDirectoryDialog", "Select Folder", "C:/tmp/")
end -- print(path)
if path then getFilesInFolder(path, folderimages) end
if folderimages and #folderimages > 0 then
for i = 1, #folderimages do
images[i] = Bitmap.new(Texture.new(folderimages[i]), true)
images[i]:setAnchorPoint(0.5, 1)
images[i]:setPosition(8, 8)
-- ...
end
end
end)
KEY REMAPPING WITH SAVE DATA
In this Settings scene we can remap any predefined keys. You can navigate using the arrows on your keyboard and press ENTER to remap a key.
Once you have remapped the keys, the new settings are save to a file which will be read everytime you restart the game.
Code using ButtonMonster
-- *** SAVING AND LOADING DATA IN JSON FORMAT ***
require "json" -- don't forget to add the JSON plugin in your project
function saveData(filepath, value)
local contents = json.encode(value)
local file = io.open(filepath, "w") -- create file
file:write(contents) -- save json string in file
io.close(file)
end
function getData(filepath)
local value
local file = io.open(filepath, "r")
if file then
local contents = file:read("*a") -- read contents
value = json.decode(contents) -- decode json
io.close(file)
end
return value
end
-- *** LOADING AND SAVING USER PREFS DATA ***
-- global prefs functions
function myLoadPrefs(xconfigfilepath)
local mydata = getData(xconfigfilepath) -- try to read information from file
if not mydata then -- if no prefs file, create it
mydata = {}
-- set prefs
mydata.g_language = g_language
-- controls
mydata.g_keyleft = g_keyleft
mydata.g_keyright = g_keyright
mydata.g_keyup = g_keyup
mydata.g_keydown = g_keydown
mydata.g_keyaction1 = g_keyaction1
mydata.g_keyaction2 = g_keyaction2
mydata.g_keyaction3 = g_keyaction3
-- save prefs
saveData(xconfigfilepath, mydata) -- create file and save data
else -- prefs file exists, use it!
-- set prefs
g_language = mydata.g_language
-- controls
g_keyleft = mydata.g_keyleft
g_keyright = mydata.g_keyright
g_keyup = mydata.g_keyup
g_keydown = mydata.g_keydown
g_keyaction1 = mydata.g_keyaction1
g_keyaction2 = mydata.g_keyaction2
g_keyaction3 = mydata.g_keyaction3
end
end
function mySavePrefs(xconfigfilepath)
local mydata = {} -- clear the table
-- set prefs
mydata.g_language = g_language
-- controls
mydata.g_keyleft = g_keyleft
mydata.g_keyright = g_keyright
mydata.g_keyup = g_keyup
mydata.g_keydown = g_keydown
mydata.g_keyaction1 = g_keyaction1
mydata.g_keyaction2 = g_keyaction2
mydata.g_keyaction3 = g_keyaction3
-- save prefs
saveData(xconfigfilepath, mydata) -- save new data
end
-- initial default global prefs values
g_configfilepath = "|D|configfile.txt" -- data are saved in this file (in the Document app folder)
g_language = application:getLanguage()
g_keyleft = KeyCode.LEFT
g_keyright = KeyCode.RIGHT
g_keyup = KeyCode.UP
g_keydown = KeyCode.DOWN
g_keyaction1 = KeyCode.D -- punch1
g_keyaction2 = KeyCode.S -- punch1
g_keyaction3 = KeyCode.Q -- jump/jump punch1
-- load saved prefs from file (|D|configfile.txt)
myLoadPrefs(g_configfilepath) -- override default values by saved values if any
-- *** GLOBAL FONT AND UI THEME FOR BUTTONS ***
myttf = TTFont.new("fonts/Cabin-Regular-TTF.ttf", 2.8*8) -- UI
g_ui_theme = {}
g_ui_theme.pixelcolorup = 0x8d595d
g_ui_theme.pixelcolordown = 0xc09c98
g_ui_theme.textcolorup = 0xd9d2cb
g_ui_theme.textcolordown = 0xd9d2cb
g_ui_theme._textcolordisabled = 0xd9d2cb
g_ui_theme.tooltiptextcolor = 0x3a1d20
g_ui_theme.tooltipoffsetx = -7*8
g_ui_theme.tooltipoffsety = 1*4
-- *** THE OPTIONS SCENE (Class) ***
Options = Core.class(Sprite)
local keyNames = { -- display a friendly key name
[KeyCode.LEFT] = "LEFT",
[KeyCode.RIGHT] = "RIGHT",
[KeyCode.UP] = "UP",
[KeyCode.DOWN] = "DOWN",
[KeyCode.NUM0] = "NUMPAD 0",
[KeyCode.NUM1] = "NUMPAD 1",
[KeyCode.NUM2] = "NUMPAD 2",
[KeyCode.NUM3] = "NUMPAD 3",
[KeyCode.NUM4] = "NUMPAD 4",
[KeyCode.NUM5] = "NUMPAD 5",
[KeyCode.NUM6] = "NUMPAD 6",
[KeyCode.NUM7] = "NUMPAD 7",
[KeyCode.NUM8] = "NUMPAD 8",
[KeyCode.NUM9] = "NUMPAD 9",
[KeyCode.SPACE] = "SPACE",
[KeyCode.SHIFT] = "SHIFT",
[KeyCode.CTRL] = "CONTROL",
[KeyCode.ALT] = "ALT",
[KeyCode.TAB] = "TAB",
}
function Options:init()
-- bg
application:setBackgroundColor(0x232a35)
-- tooltip layer
local tooltiplayer = Sprite.new()
-- buttons
local key
-- movement
if (keyNames[g_keyleft] or 0) == 0 then key = utf8.char(g_keyleft)
else key = keyNames[g_keyleft]
end -- display a friendly key name
self.btnLEFT = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="left", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 2, tooltiplayer)
if (keyNames[g_keyright] or 0) == 0 then key = utf8.char(g_keyright)
else key = keyNames[g_keyright]
end -- display a friendly key name
self.btnRIGHT = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="right", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 3, tooltiplayer)
if (keyNames[g_keyup] or 0) == 0 then key = utf8.char(g_keyup)
else key = keyNames[g_keyup]
end -- display a friendly key name
self.btnUP = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="up", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 1, tooltiplayer)
if (keyNames[g_keydown] or 0) == 0 then key = utf8.char(g_keydown)
else key = keyNames[g_keydown]
end -- display a friendly key name
self.btnDOWN = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="down", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 4, tooltiplayer)
-- actions
if (keyNames[g_keyaction1] or 0) == 0 then key = utf8.char(g_keyaction1)
else key = keyNames[g_keyaction1]
end -- display a friendly key name
self.btnACTION1 = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="punch1", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 5, tooltiplayer)
if (keyNames[g_keyaction2] or 0) == 0 then key = utf8.char(g_keyaction2)
else key = keyNames[g_keyaction2]
end -- display a friendly key name
self.btnACTION2 = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="punch2", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 6, tooltiplayer)
if (keyNames[g_keyaction3] or 0) == 0 then key = utf8.char(g_keyaction3)
else key = keyNames[g_keyaction3]
end -- display a friendly key name
self.btnACTION3 = ButtonMonster.new({
autoscale=false, pixelwidth=17*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text=key, ttf=myttf, textcolorup=g_ui_theme.textcolorup, textcolordown=g_ui_theme.textcolordown,
tooltiptext="jump punch", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 7, tooltiplayer)
-- btn menu
self.btnMENU = ButtonMonster.new({
autoscale=false, pixelwidth=12*8, pixelheight=6*8,
pixelscalexup=0.8, pixelscalexdown=0.9,
pixelcolorup=g_ui_theme.pixelcolorup, pixelcolordown=g_ui_theme.pixelcolordown,
text="MENU", ttf=myttf, textcolorup=0x0009B3, textcolordown=0x45d1ff,
tooltiptext="Enter", tooltipttf=myttf, tooltiptextcolor=g_ui_theme.tooltiptextcolor,
tooltipoffsetx=g_ui_theme.tooltipoffsetx, tooltipoffsety=g_ui_theme.tooltipoffsety,
}, 8, tooltiplayer)
-- btns table
self.btns = {}
self.btns[#self.btns + 1] = self.btnUP -- 1
self.btns[#self.btns + 1] = self.btnLEFT -- 2
self.btns[#self.btns + 1] = self.btnRIGHT -- 3
self.btns[#self.btns + 1] = self.btnDOWN -- 4
self.btns[#self.btns + 1] = self.btnACTION1 -- 5
self.btns[#self.btns + 1] = self.btnACTION2 -- 6
self.btns[#self.btns + 1] = self.btnACTION3 -- 7
self.btns[#self.btns + 1] = self.btnMENU -- 8
self.selector = 1 -- starting button
-- position
self.btnLEFT:setPosition(1.5*myappwidth/10, 6*8+6*myappheight/10) -- 2
self.btnRIGHT:setPosition(3.5*myappwidth/10, 6*8+6*myappheight/10) -- 3
self.btnUP:setPosition(2.5*myappwidth/10, 6*8+4.6*myappheight/10) -- 1
self.btnDOWN:setPosition(2.5*myappwidth/10, 6*8+7.4*myappheight/10) -- 4
for i = 5, 7 do -- action buttons
self.btns[i]:setPosition(5.6*myappwidth/10, (i-5)*6*8+6*myappheight/10)
end
self.btnMENU:setPosition(myappwidth - self.btnMENU:getWidth()/2, myappheight - self.btnMENU:getHeight()/2)
-- order
for k, v in ipairs(self.btns) do self:addChild(v) end
self:addChild(tooltiplayer)
-- buttons listeners
for k, v in ipairs(self.btns) do
-- v:addEventListener("pressed", function() self.selector = k self:goto() end)
v:addEventListener("clicked", function() self.selector = k self:goto() end)
v:addEventListener("hovered", function(e) self.selector = e.currselector end)
v.btns = self.btns -- FOR KEYBOARD NAVIGATION!
end
-- let's go!
self.isremapping = false
self:myKeysPressed()
self:updateButton()
end
-- key remapping
function Options:remapKey(xbool)
local btn = self.btns[self.selector]
if xbool then
self.isremapping = true
btn:setColorTransform(255/255, 255/255, 0/255, 255/255)
else
btn:setColorTransform(255/255, 255/255, 255/255, 255/255)
end
end
-- update button state
function Options:updateButton()
for k, v in ipairs(self.btns) do
v.currselector = self.selector
v:updateVisualState()
if k == self.selector then v:selectionSfx() end
end
end
-- KEYS HANDLER
function Options:myKeysPressed()
self:addEventListener(Event.KEY_DOWN, function(e)
if self.isremapping then -- KEY REMAPPING
if e.keyCode == KeyCode.ESC then
self.isremapping = false
self:remapKey(self.isremapping)
self:updateButton()
return
end
local keycode = e.keyCode
local key = keyNames[keycode]
if (keyNames[keycode] or 0) == 0 then key = utf8.char(keycode) end
self.btns[self.selector]:changeText(key)
if self.selector == 1 then g_keyup = keycode -- follows self.btns order
elseif self.selector == 2 then g_keyleft = keycode -- follows self.btns order
elseif self.selector == 3 then g_keyright = keycode -- follows self.btns order
elseif self.selector == 4 then g_keydown = keycode -- follows self.btns order
elseif self.selector == 5 then g_keyaction1 = keycode -- follows self.btns order
elseif self.selector == 6 then g_keyaction2 = keycode -- follows self.btns order
elseif self.selector == 7 then g_keyaction3 = keycode -- follows self.btns order
end
self.isremapping = false
self:remapKey(self.isremapping)
self:updateButton()
mySavePrefs(g_configfilepath)
else -- NOT KEY REMAPPING
if e.keyCode == KeyCode.ESC then self:back() end
-- keyboard
if e.keyCode == KeyCode.UP or e.keyCode == g_keyup or e.keyCode == KeyCode.LEFT or e.keyCode == g_keyleft then
self.selector -= 1 if self.selector < 1 then self.selector = #self.btns end
self:updateButton()
elseif e.keyCode == KeyCode.DOWN or e.keyCode == g_keydown or e.keyCode == KeyCode.RIGHT or e.keyCode == g_keyright then
self.selector += 1 if self.selector > #self.btns then self.selector = 1 end
self:updateButton()
end
-- modifier
local modifier = application:getKeyboardModifiers()
local alt = (modifier & KeyCode.MODIFIER_ALT) > 0
if not alt and (e.keyCode == KeyCode.ENTER or e.keyCode == KeyCode.SPACE or e.keyCode == g_keyaction1) then -- validate
self:goto()
end
end
end)
end
-- scenes navigation
function Options:goto()
for k, v in ipairs(self.btns) do
if k == self.selector then
if v.isdisabled then print("btn disabled!", k)
elseif k >= 1 and k <= #self.btns-1 then self:remapKey(true) -- player1 controls/actions
elseif k == #self.btns then self:back() -- last button is go back to menu scene
else print("nothing here!", k)
end
end
end
end
function Options:back()
print("SWITCH TO MENU SCENE")
-- scenemanager:changeScene("menu", 1, transitions[1], easings[3])
end
-- *** START THE SCENE ***
stage:addChild(Options.new())
More to come God's willing...