Difference between revisions of "Examples"
(→GFX: added VFX) |
m (Text replacement - "</source>" to "</syntaxhighlight>") |
||
(42 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
'''Here are some examples from the Gideros forum and some other places :-)'''<br/> | '''Here are some examples from the Gideros forum and some other places :-)'''<br/> | ||
'''All samples are ready to use. Enjoy!'''<br/> | '''All samples are ready to use. Enjoy!'''<br/> | ||
+ | |||
+ | |||
+ | == LUA == | ||
+ | |||
+ | === TERNARY OPERATOR '''@hgy29''' === | ||
+ | |||
+ | '''New Luau implementation here: [[Ternary_Operator]].''' | ||
+ | |||
+ | |||
+ | '''Example 1''': assume you have a variable called '''c''', and you want to assign it a value only if '''a''' variable is above 10, with a ternary operator you would do this: '''c = a > 10 ? a : b''' | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | -- in lua you do | ||
+ | c = a > 10 and a or b | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Example 2''': assume you have a boolean called ''b'' and you want to set its default value to false | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | -- in lua you do | ||
+ | -- b = b and true or false -- that doesn't work :-/ | ||
+ | b = b and (b ~= nil) -- that works :-) | ||
+ | b = b and not (b == nil) -- that also works ;-) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Example 3''': assume you have a boolean called ''b'' and you want to set its default value to true | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | -- in lua you do | ||
+ | -- b = b and false or true -- that doesn't work :-/ | ||
+ | b = b or (b == nil) -- that works :-) | ||
+ | </syntaxhighlight> | ||
== STRING == | == STRING == | ||
=== A COLORED STRING '''@hgy29''' === | === A COLORED STRING '''@hgy29''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local text = TextField.new(nil, "This is a \e[color=#f005]semi transparent red\e[color] text") | local text = TextField.new(nil, "This is a \e[color=#f005]semi transparent red\e[color] text") | ||
text:setPosition(32, 64) | text:setPosition(32, 64) | ||
stage:addChild(text) | stage:addChild(text) | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === A COLORED STRING 2 '''@mokalux''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | -- beautifying a tf | ||
+ | local tf = TextField.new(nil, "") | ||
+ | local mystr = "Gideros, what a beauty!" | ||
+ | local strsplit = mystr:split(",") | ||
+ | --local mystr2 = strsplit[1] -- gets the first index of the table split (=Gideros) | ||
+ | --local mystr3 = "\e[color=#e5e]"..mystr2.."\e[color]" -- beautifies Gideros | ||
+ | --mystr = mystr:gsub(mystr2, mystr3) -- replaces mystr2 by mystr3 | ||
+ | mystr = mystr:gsub(strsplit[1], "\e[color=#e5e]"..strsplit[1].."\e[color]") -- less code! | ||
+ | -- final display | ||
+ | tf:setText(mystr) | ||
+ | tf:setScale(3) | ||
+ | tf:setPosition(128, 128) | ||
+ | stage:addChild(tf) | ||
+ | </syntaxhighlight> | ||
=== DATE & TIME '''@mokalux''' === | === DATE & TIME '''@mokalux''' === | ||
Gets system date and time (YYYYMMDD_HHMMSS) | Gets system date and time (YYYYMMDD_HHMMSS) | ||
− | < | + | <syntaxhighlight lang="lua"> |
-- CURRENT DATE AND TIME | -- CURRENT DATE AND TIME | ||
local myyear = os.date("*t").year | local myyear = os.date("*t").year | ||
Line 25: | Line 71: | ||
local mytime = myyear..mymonth..myday.."_"..myhour..mymin..mysec | local mytime = myyear..mymonth..myday.."_"..myhour..mymin..mysec | ||
print(mytime) -- 20200309_143048 | print(mytime) -- 20200309_143048 | ||
− | </ | + | </syntaxhighlight> |
=== FINDING A NUMBER IN A STRING '''@xxx''' === | === FINDING A NUMBER IN A STRING '''@xxx''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local mystring = "Doe is 26 years old." | local mystring = "Doe is 26 years old." | ||
local age = tonumber(string.match(mystring, "%d+")) | local age = tonumber(string.match(mystring, "%d+")) | ||
print(age) -- outputs 26 | print(age) -- outputs 26 | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === FINDING ANY INDEXED NUMBERS IN A STRING '''@mokalux''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local mystr = "x64y250s8" | ||
+ | local x, y, speed -- numbers (eg. coordinates) | ||
+ | local index | ||
+ | -- | ||
+ | index = mystr:find("s") -- "s" index represents speed | ||
+ | speed = tonumber(mystr:sub(index):match("%d+")) -- find sNNN | ||
+ | index = mystr:find("x") -- index x | ||
+ | x = tonumber(mystr:sub(index):match("%d+")) -- find xNNN | ||
+ | index = mystr:find("y") -- index y | ||
+ | y = tonumber(mystr:sub(index):match("%d+")) -- find yNNNN | ||
+ | </syntaxhighlight> | ||
=== CHECK IF STRING X STARTS OR ENDS WITH STRING Y '''@lua-users wiki''' === | === CHECK IF STRING X STARTS OR ENDS WITH STRING Y '''@lua-users wiki''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local function starts_with(str, start) | local function starts_with(str, start) | ||
return str:sub(1, #start) == start | return str:sub(1, #start) == start | ||
Line 43: | Line 103: | ||
return ending == "" or str:sub(-#ending) == ending | return ending == "" or str:sub(-#ending) == ending | ||
end | end | ||
− | </ | + | </syntaxhighlight> |
=== FINDING THE LAST POSITION OF CHARACTER X IN A STRING '''@mokalux''' === | === FINDING THE LAST POSITION OF CHARACTER X IN A STRING '''@mokalux''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
mystr = "This is a sample string containing many stars *. Here is another one *. And a last one *." | mystr = "This is a sample string containing many stars *. Here is another one *. And a last one *." | ||
for i = 1, string.len(mystr) do | for i = 1, string.len(mystr) do | ||
Line 55: | Line 115: | ||
end | end | ||
print(counti, countl) | print(counti, countl) | ||
− | </ | + | </syntaxhighlight> |
=== GET PATH '''@xxx''' === | === GET PATH '''@xxx''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
function getPath(str) | function getPath(str) | ||
return str:match("(.*[/\\])") | return str:match("(.*[/\\])") | ||
Line 67: | Line 127: | ||
print(getPath(x)) -- prints: /home/user/.local/share/app/ | print(getPath(x)) -- prints: /home/user/.local/share/app/ | ||
print(getPath(y)) -- prints: C:\Program Files\app\ | print(getPath(y)) -- prints: C:\Program Files\app\ | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === GET PATH AND FILENAME '''@mokalux''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function getPathAndFileName(xpath) | ||
+ | local xpathlength = xpath:len() | ||
+ | local tmpfolder = xpath:match("(.*[/\\])") | ||
+ | local tmpfolderlength = tmpfolder:len() | ||
+ | local finalfolder = tmpfolder:sub(1, tmpfolderlength-1) | ||
+ | local finalfile = xpath:sub(-(xpathlength-tmpfolderlength)) | ||
+ | return finalfolder, finalfile | ||
+ | end | ||
+ | |||
+ | x = "/home/user/.local/share/app/some_file.png" | ||
+ | local folder, file = getPathAndFileName(x) | ||
+ | print(folder, file) -- prints: "/home/user/.local/share/app/", "some_file.png" | ||
+ | </syntaxhighlight> | ||
=== FORMAT 0xRRGGBB COLOR TO STRING '''@Rrraptor, @keszegh''' === | === FORMAT 0xRRGGBB COLOR TO STRING '''@Rrraptor, @keszegh''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local mycolor = 0x0000ff -- your color | local mycolor = 0x0000ff -- your color | ||
Line 84: | Line 160: | ||
-- Rrraptor | -- Rrraptor | ||
local mycolorstring2 = ("%x"):format(mycolor) --> "ff" | local mycolorstring2 = ("%x"):format(mycolor) --> "ff" | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === SPLIT A STRING EVERY N CHARACTERS '''@https://stackoverflow.com/questions/76194310/how-would-i-split-a-string-once-every-n-characters''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local mystr = "Hello, World!" | ||
+ | local splitevery = 2 | ||
+ | for c in mystr:gmatch(('.'):rep(splitevery)) do | ||
+ | print(c) | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Note''': a remaining less than n characters will be silently ignored. Could be fixed by using a numeric for loop or .? instead | ||
== GFX == | == GFX == | ||
+ | |||
+ | === DRAWING A CIRCLE (PARTICLE) '''@hgy29''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local mkr=Particles.new() | ||
+ | mkr:addParticles{ | ||
+ | {x=0,y=0,size=100,color=0xFFFFFF}, -- outter circle | ||
+ | {x=0,y=0,size=70,color=0x4071B5}, -- inner circle | ||
+ | } | ||
+ | stage:addChild(mkr) | ||
+ | mkr:setPosition(120,120) | ||
+ | </syntaxhighlight> | ||
=== DRAWING A CIRCLE '''@xxx''' === | === DRAWING A CIRCLE '''@xxx''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
xCircle = Core.class(Sprite) | xCircle = Core.class(Sprite) | ||
Line 109: | Line 207: | ||
--- usage | --- usage | ||
--xCircle(10, 5, 0xFF0000) | --xCircle(10, 5, 0xFF0000) | ||
− | </ | + | </syntaxhighlight> |
=== DRAWING ANOTHER CIRCLE (stars, circles, flowers) '''@gemboy100''' === | === DRAWING ANOTHER CIRCLE (stars, circles, flowers) '''@gemboy100''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
Circle = Core.class(Mesh) | Circle = Core.class(Mesh) | ||
Line 216: | Line 314: | ||
c4:setPosition(3 * 64, 3 * 64) | c4:setPosition(3 * 64, 3 * 64) | ||
stage:addChild(c4) | stage:addChild(c4) | ||
− | </ | + | </syntaxhighlight> |
=== DRAWING AN ARC '''@hgvyas123''' === | === DRAWING AN ARC '''@hgvyas123''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
function drawArc(xc,yc,xradius,yradius,startAngle,endAngle,isFill) | function drawArc(xc,yc,xradius,yradius,startAngle,endAngle,isFill) | ||
if yradius == nil then | if yradius == nil then | ||
Line 261: | Line 359: | ||
local myarc = drawArc(128, 128, 64, 64, 0, 5 * 45, false) | local myarc = drawArc(128, 128, 64, 64, 0, 5 * 45, false) | ||
stage:addChild(myarc) | stage:addChild(myarc) | ||
− | </ | + | </syntaxhighlight> |
=== CIRCULAR PROGRESS '''@hgy29''' === | === CIRCULAR PROGRESS '''@hgy29''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
CircularProgress = Core.class(Sprite) | CircularProgress = Core.class(Sprite) | ||
Line 308: | Line 406: | ||
--- usage | --- usage | ||
-- meter = CircularProgress.new(40, 5, 0x770000, nil, 2) | -- meter = CircularProgress.new(40, 5, 0x770000, nil, 2) | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === HEX TO RGB '''@rrraptor''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function hex2rgb(hex) | ||
+ | local r = (hex >> 16 & 0xff) / 255 | ||
+ | local g = (hex >> 8 & 0xff) / 255 | ||
+ | local b = (hex & 0xff) / 255 | ||
+ | return r,g,b | ||
+ | end | ||
+ | |||
+ | --- usage | ||
+ | --local r, g, b = hex2rgb(0xFF0000) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === HEX TO RGB table '''@rrraptor''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function hex2rgb(hex) | ||
+ | local rgbtable = {} -- new 211115 XXX | ||
+ | rgbtable.r, rgbtable.g, rgbtable.b = | ||
+ | (hex >> 16 & 0xff) / 255, (hex >> 8 & 0xff) / 255, (hex & 0xff) / 255 | ||
+ | return rgbtable | ||
+ | end | ||
+ | |||
+ | --- usage | ||
+ | --local rgbtable = hex2rgb(0xFF0000) -- rgbtable.r, rgbtable.g, rgbtable.b | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === PICKING A RANDOM COLOR '''@rrraptor''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function randomColor() return "0x"..(math.random() * (1 << 24) | 0) end | ||
+ | |||
+ | --- usage | ||
+ | --local pixel = Pixel.new(randomColor(), 1, 32, 64) | ||
+ | --stage:addChild(pixel) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === HEX TO RGB '''@rrraptor''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function hex2rgb(hex) | ||
+ | local r = (hex >> 16 & 0xff) / 255 | ||
+ | local g = (hex >> 8 & 0xff) / 255 | ||
+ | local b = (hex & 0xff) / 255 | ||
+ | return r,g,b | ||
+ | end | ||
+ | |||
+ | --- usage | ||
+ | --local r, g, b = hex2rgb(0xFF0000) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === HEX TO RGB2 '''@https://gist.github.com/jasonbradley/4357406''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function hex2rgb2(hex) | ||
+ | hex = hex:gsub("#","") | ||
+ | return tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6)) | ||
+ | end | ||
+ | --- usage | ||
+ | --local r, g, b = hex2rgb2(0xFF0000) | ||
+ | </syntaxhighlight> | ||
=== SAVING IMAGE TO FILE '''@mokalux''' === | === SAVING IMAGE TO FILE '''@mokalux''' === | ||
Saving an image or part of an image to disk. | Saving an image or part of an image to disk. | ||
− | < | + | <syntaxhighlight lang="lua"> |
function xsaveJPGtoDoc(xoriginalimgfile, xposx, xposy, xsizew, xsizeh, xdestimgname) | function xsaveJPGtoDoc(xoriginalimgfile, xposx, xposy, xsizew, xsizeh, xdestimgname) | ||
local mytexture = Texture.new(xoriginalimgfile) | local mytexture = Texture.new(xoriginalimgfile) | ||
Line 325: | Line 481: | ||
--- usage | --- usage | ||
--local xsavedjpg = xsaveJPGtoDoc("gfx/bg/dark.jpg", 0, 0, 64, 64, "dark") | --local xsavedjpg = xsaveJPGtoDoc("gfx/bg/dark.jpg", 0, 0, 64, 64, "dark") | ||
− | </ | + | </syntaxhighlight> |
=== PREVENT FROM DRAGGING A SHAPE OVER OTHER SHAPE '''@hgvyas123''' === | === PREVENT FROM DRAGGING A SHAPE OVER OTHER SHAPE '''@hgvyas123''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
--[[ | --[[ | ||
Drag the shapes around with your mouse or fingers | Drag the shapes around with your mouse or fingers | ||
Line 409: | Line 565: | ||
info:setPosition(23, 50) | info:setPosition(23, 50) | ||
stage:addChild(info) | stage:addChild(info) | ||
− | </ | + | </syntaxhighlight> |
=== CHECK POINT IS IN POLYGON '''@atilim''' === | === CHECK POINT IS IN POLYGON '''@atilim''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
function pointInPolygon(vertices, x, y) | function pointInPolygon(vertices, x, y) | ||
local intersectionCount = 0 | local intersectionCount = 0 | ||
Line 470: | Line 626: | ||
end | end | ||
end) | end) | ||
− | </ | + | </syntaxhighlight> |
=== STENCIL OPERATION '''@hgy29''' === | === STENCIL OPERATION '''@hgy29''' === | ||
[[File:Stencil_operation_ex01.png]] | [[File:Stencil_operation_ex01.png]] | ||
− | < | + | <syntaxhighlight lang="lua"> |
local star = Bitmap.new(Texture.new("gfx/star.png", true)) | local star = Bitmap.new(Texture.new("gfx/star.png", true)) | ||
stage:addChild(star) | stage:addChild(star) | ||
Line 516: | Line 672: | ||
-- Restore our initial bitmap blending mode, to show it on screen as usual | -- Restore our initial bitmap blending mode, to show it on screen as usual | ||
star:setBlendMode(Sprite.ALPHA) | star:setBlendMode(Sprite.ALPHA) | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === ZOOM SPRITE TO MOUSE POSITION '''@hgy29, @keszegh''' === | ||
+ | '''This one is just awesome!''' | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | application:setBackgroundColor(0x333333) | ||
+ | |||
+ | -- sprites | ||
+ | local canvaslayer = Sprite.new() | ||
+ | local pixel = Bitmap.new(Texture.new("gfx/pot/1K-triangle_buble-diffuse.jpg")) | ||
+ | -- order | ||
+ | canvaslayer:addChild(pixel) | ||
+ | canvaslayer:setAnchorPoint(0.5, 0.5) | ||
+ | stage:addChild(canvaslayer) | ||
+ | -- position | ||
+ | canvaslayer:setPosition(application:getContentWidth()/2, application:getContentHeight()/2) | ||
+ | |||
+ | -- current zoom | ||
+ | local currzoom = 0.5 | ||
+ | local zoomstart = currzoom | ||
+ | canvaslayer:setScale(currzoom) | ||
+ | -- thank you very much hgy29 & keszegh :-) | ||
+ | local pointerstartx, pointerstarty = 0, 0 | ||
+ | local canvasposx, canvasposy = 0, 0 | ||
+ | local offsetx, offsety = 0, 0 | ||
+ | |||
+ | stage:addEventListener(Event.MOUSE_DOWN, function(e) | ||
+ | pointerstartx, pointerstarty = stage:globalToLocal(e.rx, e.ry) | ||
+ | e:stopPropagation() | ||
+ | end) | ||
+ | stage:addEventListener(Event.MOUSE_MOVE, function(e) | ||
+ | canvasposx, canvasposy = canvaslayer:getPosition() | ||
+ | offsetx = e.rx - pointerstartx | ||
+ | offsety = e.ry - pointerstarty | ||
+ | canvasposx += offsetx | ||
+ | canvasposy += offsety | ||
+ | canvaslayer:setPosition(canvasposx, canvasposy) | ||
+ | pointerstartx, pointerstarty = stage:globalToLocal(e.rx, e.ry) | ||
+ | e:stopPropagation() | ||
+ | end) | ||
+ | stage:addEventListener(Event.MOUSE_WHEEL, function(e) -- e.wheel = +- 120 | ||
+ | zoomstart = currzoom | ||
+ | pointerstartx, pointerstarty = stage:globalToLocal(e.rx, e.ry) | ||
+ | canvasposx, canvasposy = canvaslayer:getPosition() | ||
+ | -- local viewportZoom=math.clamp(self.zoomStart*2^((self.panStart.ry-newY)/100),_MIN_ZOOM,_MAX_ZOOM) | ||
+ | currzoom = zoomstart + e.wheel/120/4 | ||
+ | if currzoom <= 0.2 then currzoom = 0.2 end | ||
+ | if currzoom >= 2 then currzoom = 2 end | ||
+ | canvaslayer:setScale(currzoom) | ||
+ | local viewportx = canvasposx + (pointerstartx - canvasposx) * (1 - currzoom/zoomstart) | ||
+ | local viewporty = canvasposy + (pointerstarty - canvasposy) * (1 - currzoom/zoomstart) | ||
+ | canvaslayer:setPosition(viewportx, viewporty) | ||
+ | e:stopPropagation() | ||
+ | end) | ||
+ | </syntaxhighlight> | ||
== VFX == | == VFX == | ||
=== PARTICLES EFFECT 1 '''@hgy29''' === | === PARTICLES EFFECT 1 '''@hgy29''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
function EffectExplode(s, scale, x, y, r, speed, texture) | function EffectExplode(s, scale, x, y, r, speed, texture) | ||
local p = Particles.new() | local p = Particles.new() | ||
Line 557: | Line 767: | ||
Core.asyncCall(EffectExplode, stage, | Core.asyncCall(EffectExplode, stage, | ||
1, e.x, e.y, 100, 2, | 1, e.x, e.y, 100, 2, | ||
− | Texture.new("gfx/ | + | Texture.new("gfx/smoke.png", true) |
) | ) | ||
end) | end) | ||
− | </ | + | </syntaxhighlight> |
== ANIMATION == | == ANIMATION == | ||
=== FPS '''@atilim''' === | === FPS '''@atilim''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local fps = TextField.new(nil, "") | local fps = TextField.new(nil, "") | ||
fps:setScale(2) | fps:setScale(2) | ||
Line 589: | Line 799: | ||
-- Add FPS Counter to stage | -- Add FPS Counter to stage | ||
stage:addEventListener(Event.ENTER_FRAME, displayFps) | stage:addEventListener(Event.ENTER_FRAME, displayFps) | ||
− | </ | + | </syntaxhighlight> |
=== MOVING A SPRITE IN AN ARC PATH '''@Disciple''' === | === MOVING A SPRITE IN AN ARC PATH '''@Disciple''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local bone = Sprite.new() | local bone = Sprite.new() | ||
--local boneImg = Bitmap.new(Texture.new("gfx/enemy01.png")) -- add your gfx! | --local boneImg = Bitmap.new(Texture.new("gfx/enemy01.png")) -- add your gfx! | ||
Line 618: | Line 828: | ||
stage:addEventListener(Event.ENTER_FRAME, enterFrame) | stage:addEventListener(Event.ENTER_FRAME, enterFrame) | ||
− | </ | + | </syntaxhighlight> |
=== MOVING A SPRITE IN AN HORIZONTAL SINE WAVE '''@Harrison''' === | === MOVING A SPRITE IN AN HORIZONTAL SINE WAVE '''@Harrison''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local blimp1 = Pixel.new(0x0000ff, 0.5, 32, 64) | local blimp1 = Pixel.new(0x0000ff, 0.5, 32, 64) | ||
blimp1:setAnchorPoint(0.5, 0.5) | blimp1:setAnchorPoint(0.5, 0.5) | ||
Line 640: | Line 850: | ||
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame) | stage:addEventListener(Event.ENTER_FRAME, onEnterFrame) | ||
− | </ | + | </syntaxhighlight> |
=== MOVING A SPRITE IN A VERTICAL COS WAVE '''@Harrison''' === | === MOVING A SPRITE IN A VERTICAL COS WAVE '''@Harrison''' === | ||
− | < | + | <syntaxhighlight lang="lua"> |
local blimp2 = Pixel.new(0x00ff00, 0.5, 64, 32) | local blimp2 = Pixel.new(0x00ff00, 0.5, 64, 32) | ||
blimp2:setAnchorPoint(0.5, 0.5) | blimp2:setAnchorPoint(0.5, 0.5) | ||
Line 662: | Line 872: | ||
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame) | stage:addEventListener(Event.ENTER_FRAME, onEnterFrame) | ||
− | </ | + | </syntaxhighlight> |
Line 669: | Line 879: | ||
=== CSV '''@hgy29''' === | === CSV '''@hgy29''' === | ||
Load a CSV file. | Load a CSV file. | ||
− | < | + | <syntaxhighlight lang="lua"> |
function loadCSV(file) | function loadCSV(file) | ||
local function csvsplit(line) | local function csvsplit(line) | ||
Line 699: | Line 909: | ||
--print(csv:getField(4,"Value")) | --print(csv:getField(4,"Value")) | ||
--print(csv:getField(7,"Time") | --print(csv:getField(7,"Time") | ||
− | </ | + | </syntaxhighlight> |
=== JSON '''@xxx''' === | === JSON '''@xxx''' === | ||
Loading and saving preferences. | Loading and saving preferences. | ||
− | < | + | <syntaxhighlight lang="lua"> |
require "json" -- you must add JSON plugin to your app | require "json" -- you must add JSON plugin to your app | ||
Line 759: | Line 969: | ||
--print(g_language) | --print(g_language) | ||
--print(g_theme) | --print(g_theme) | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === JSON V2 '''@mokalux''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | require "json" -- you must add JSON plugin to your app | ||
+ | |||
+ | 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 result, value | ||
+ | local file = io.open(filepath, "r") | ||
+ | if file then | ||
+ | local contents = file:read("*a") -- read contents | ||
+ | -- value = json.decode(contents) -- decode json | ||
+ | result, value = pcall(json.decode, contents) -- try to decode json | ||
+ | io.close(file) | ||
+ | end | ||
+ | return result, value | ||
+ | end | ||
+ | |||
+ | --[[ | ||
+ | -- usage | ||
+ | -- init.lua | ||
+ | g_configfilepath = "|D|myconfigfile.txt" -- C:\Users\xxx\AppData\Roaming\myappname on Windows | ||
+ | -- ... | ||
+ | |||
+ | -- main.lua | ||
+ | function myLoadPrefs() | ||
+ | local _result, mydata = getData(g_configfilepath) -- try to read information from file | ||
+ | if not mydata then -- if no prefs file, create it | ||
+ | print("* creating prefs data file") | ||
+ | mydata = {} | ||
+ | -- your data | ||
+ | mydata.g_language = g_language | ||
+ | mydata.g_bgcolor = g_bgcolor | ||
+ | -- ... | ||
+ | -- create file and save datas | ||
+ | saveData(g_configfilepath, mydata) | ||
+ | myLoadPrefs() -- reload! | ||
+ | else -- data exist, use them! | ||
+ | g_language = mydata.g_language -- global variable | ||
+ | g_bgcolor = mydata.g_bgcolor or 0x333333 -- global variable | ||
+ | -- ... | ||
+ | end | ||
+ | end | ||
+ | function mySavePrefs() | ||
+ | local mydata = {} -- clear the table | ||
+ | -- prefs | ||
+ | mydata.g_language = g_language | ||
+ | mydata.g_bgcolor = g_bgcolor or 0x333333 | ||
+ | -- save new data | ||
+ | saveData(g_configfilepath, mydata) | ||
+ | end | ||
+ | |||
+ | -- main.lua or elsewhere | ||
+ | myLoadPrefs() -- load initial prefs | ||
+ | |||
+ | -- use the data | ||
+ | application:setBackgroundColor(g_bgcolor) | ||
+ | -- ... | ||
+ | ]] | ||
+ | </syntaxhighlight> | ||
== MATH == | == MATH == | ||
Line 766: | Line 1,042: | ||
=== CLAMP '''@rrraptor''' === | === CLAMP '''@rrraptor''' === | ||
Limits the value to the specified range. | Limits the value to the specified range. | ||
− | < | + | <syntaxhighlight lang="lua"> |
-- v - value to limit | -- v - value to limit | ||
-- min, max - range | -- min, max - range | ||
Line 777: | Line 1,053: | ||
--clamp(-20, 0, 100) --> 0 | --clamp(-20, 0, 100) --> 0 | ||
--clamp(120, 0, 100) --> 100 | --clamp(120, 0, 100) --> 100 | ||
− | </ | + | </syntaxhighlight> |
=== LERP '''@xxx''' === | === LERP '''@xxx''' === | ||
Lerps between 2 values. | Lerps between 2 values. | ||
− | < | + | <syntaxhighlight lang="lua"> |
local function lerp(a, b, t) | local function lerp(a, b, t) | ||
return a + (b-a) * t | return a + (b-a) * t | ||
end | end | ||
− | </ | + | </syntaxhighlight> |
=== MAP '''@rrraptor''' === | === MAP '''@rrraptor''' === | ||
Transforms one range to another. | Transforms one range to another. | ||
− | < | + | <syntaxhighlight lang="lua"> |
-- v - value to map | -- v - value to map | ||
-- minSrc - lower bound of the value's current range | -- minSrc - lower bound of the value's current range | ||
Line 805: | Line 1,081: | ||
--map(10, 0, 10, 0, 200) -> 200 | --map(10, 0, 10, 0, 200) -> 200 | ||
--map(0, -1, 1, 0, 1) -> 0.5 | --map(0, -1, 1, 0, 1) -> 0.5 | ||
− | </ | + | </syntaxhighlight> |
− | === ROUND '''@ | + | === ROUND '''@http://lua-users.org/wiki/FormattingNumbers''' === |
Rounds a number to the nearest decimal. | Rounds a number to the nearest decimal. | ||
− | < | + | <syntaxhighlight lang="lua"> |
--[[ | --[[ | ||
− | round(val, n) - Rounds a number to the nearest decimal places. | + | round(val, n) - Rounds a number to the nearest decimal places. |
val - The value to round. | val - The value to round. | ||
n - Number of decimal places to round to. | n - Number of decimal places to round to. | ||
Line 824: | Line 1,100: | ||
end | end | ||
end | end | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | === ROUND2 '''@https://stackoverflow.com/a/58411671/870125''' === | ||
+ | Rounds a number to the nearest decimal. | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local function round(num) | ||
+ | return num + (2^52 + 2^51) - (2^52 + 2^51) | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === ROUND3 '''@http://lua-users.org/wiki/SimpleRound''' === | ||
+ | Rounds a number to the nearest decimal. Seems to be fast. | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function round(n, mult) | ||
+ | mult = mult or 1 | ||
+ | return math.floor((n+mult/2)/mult) * mult | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Move Towards '''@https://devforum.roblox.com/t/new-lua-functions-mathsign-and-mathclamp/37309/14''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local function moveTowards(current, target, maxDelta) | ||
+ | if current < target then return math.min(target, current + maxDelta) | ||
+ | elseif current > target then return math.max(target, current - maxDelta) | ||
+ | else return target | ||
+ | end | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Shoot Towards '''@mokalux''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | function shoot() | ||
+ | local projectiletex = "gfx/projectiles/bullet1.png" | ||
+ | local projectilespeed = 8*1 | ||
+ | -- a turret targeting a player | ||
+ | local angle = math.atan2(player.y - turret.y, player.x - turret.x) | ||
+ | -- projectile direction | ||
+ | local vx, vy = projectilespeed * math.cos(angle), projectilespeed * math.sin(angle) | ||
+ | -- ... | ||
+ | -- projectile implementation example | ||
+ | local g = Projectile.new( | ||
+ | texture=projectiletex, | ||
+ | x=turret.x + 8*4, y=turret.y + 0, -- your projectile start location | ||
+ | speedx=vx, speedy=vy, | ||
+ | }) | ||
+ | g = nil -- cleanup | ||
+ | -- ... | ||
+ | end | ||
+ | </syntaxhighlight> | ||
== TABLE == | == TABLE == | ||
− | === | + | === SELF VALUE TABLE TRICK '''@mokalux''' === |
+ | <syntaxhighlight lang="lua"> | ||
+ | local myvalue == "myvalue" | ||
+ | self[myvalue] -- this is equivalent to self.myvalue | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === HIGHEST / LOWEST NUMBER IN A TABLE '''@https://stackoverflow.com/questions/5178087/how-do-i-get-the-highest-integer-in-a-table-in-lua''' === | ||
+ | Gets the highest or the lowest number in a table. | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | print(math.max(unpack{4, 5, 62, -5, 12, 9})) -- 62 | ||
+ | print(math.min(unpack{4, 5, 62, -5, 12, 9})) -- -5 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === MERGING 2 TABLES '''@xxx''' === | ||
'''method 1:''' | '''method 1:''' | ||
− | < | + | <syntaxhighlight lang="lua"> |
z = {} | z = {} | ||
n = 0 | n = 0 | ||
for _,v in ipairs(x) do n=n+1; z[n]=v end | for _,v in ipairs(x) do n=n+1; z[n]=v end | ||
for _,v in ipairs(y) do n=n+1; z[n]=v end | for _,v in ipairs(y) do n=n+1; z[n]=v end | ||
− | </ | + | </syntaxhighlight> |
'''method 2:''' | '''method 2:''' | ||
− | < | + | <syntaxhighlight lang="lua"> |
levelsetup = {color=0x5E3C3A, isshape=true, restitution=0, friction=1} | levelsetup = {color=0x5E3C3A, isshape=true, restitution=0, friction=1} | ||
tablebase = { x = 64, y = 200, w = 400, h = 250, rotation = 0} | tablebase = { x = 64, y = 200, w = 400, h = 250, rotation = 0} | ||
Line 844: | Line 1,181: | ||
tablebase[k] = v | tablebase[k] = v | ||
end | end | ||
− | </ | + | </syntaxhighlight> |
+ | |||
+ | == DEBUGGING == | ||
+ | |||
+ | === TEXTURE MEMORY USAGE '''@SinisterSoft''' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local temp, oldusage | ||
+ | temp=(application:getTextureMemoryUsage()/1024) | ||
+ | if temp~=oldusage then | ||
+ | oldusage=temp | ||
+ | print("* 1 Texture usage: "..temp.." MB") | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
'''More to come God's willing...''' | '''More to come God's willing...''' | ||
− | |||
− |
Latest revision as of 15:27, 13 July 2023
Here are some examples from the Gideros forum and some other places :-)
All samples are ready to use. Enjoy!
LUA
TERNARY OPERATOR @hgy29
New Luau implementation here: Ternary_Operator.
Example 1: assume you have a variable called c, and you want to assign it a value only if a variable is above 10, with a ternary operator you would do this: c = a > 10 ? a : b
-- in lua you do
c = a > 10 and a or b
Example 2: assume you have a boolean called b and you want to set its default value to false
-- in lua you do
-- b = b and true or false -- that doesn't work :-/
b = b and (b ~= nil) -- that works :-)
b = b and not (b == nil) -- that also works ;-)
Example 3: assume you have a boolean called b and you want to set its default value to true
-- in lua you do
-- b = b and false or true -- that doesn't work :-/
b = b or (b == nil) -- that works :-)
STRING
A COLORED STRING @hgy29
local text = TextField.new(nil, "This is a \e[color=#f005]semi transparent red\e[color] text")
text:setPosition(32, 64)
stage:addChild(text)
A COLORED STRING 2 @mokalux
-- beautifying a tf
local tf = TextField.new(nil, "")
local mystr = "Gideros, what a beauty!"
local strsplit = mystr:split(",")
--local mystr2 = strsplit[1] -- gets the first index of the table split (=Gideros)
--local mystr3 = "\e[color=#e5e]"..mystr2.."\e[color]" -- beautifies Gideros
--mystr = mystr:gsub(mystr2, mystr3) -- replaces mystr2 by mystr3
mystr = mystr:gsub(strsplit[1], "\e[color=#e5e]"..strsplit[1].."\e[color]") -- less code!
-- final display
tf:setText(mystr)
tf:setScale(3)
tf:setPosition(128, 128)
stage:addChild(tf)
DATE & TIME @mokalux
Gets system date and time (YYYYMMDD_HHMMSS)
-- CURRENT DATE AND TIME
local myyear = os.date("*t").year
local mymonth = os.date("*t").month; if mymonth < 10 then mymonth = "0"..mymonth end
local myday = os.date("*t").day; if myday < 10 then myday = "0"..myday end
local myhour = os.date("*t").hour; if myhour < 10 then myhour = "0"..myhour end
local mymin = os.date("*t").min; if mymin < 10 then mymin = "0"..mymin end
local mysec = os.date("*t").sec; if mysec < 10 then mysec = "0"..mysec end
local mytime = myyear..mymonth..myday.."_"..myhour..mymin..mysec
print(mytime) -- 20200309_143048
FINDING A NUMBER IN A STRING @xxx
local mystring = "Doe is 26 years old."
local age = tonumber(string.match(mystring, "%d+"))
print(age) -- outputs 26
FINDING ANY INDEXED NUMBERS IN A STRING @mokalux
local mystr = "x64y250s8"
local x, y, speed -- numbers (eg. coordinates)
local index
--
index = mystr:find("s") -- "s" index represents speed
speed = tonumber(mystr:sub(index):match("%d+")) -- find sNNN
index = mystr:find("x") -- index x
x = tonumber(mystr:sub(index):match("%d+")) -- find xNNN
index = mystr:find("y") -- index y
y = tonumber(mystr:sub(index):match("%d+")) -- find yNNNN
CHECK IF STRING X STARTS OR ENDS WITH STRING Y @lua-users wiki
local function starts_with(str, start)
return str:sub(1, #start) == start
end
local function ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
FINDING THE LAST POSITION OF CHARACTER X IN A STRING @mokalux
mystr = "This is a sample string containing many stars *. Here is another one *. And a last one *."
for i = 1, string.len(mystr) do
if string.sub(mystr, i, i) == "*" then
counti += 1 -- number of stars *
countl = i -- index of the last star * in the string
end
end
print(counti, countl)
GET PATH @xxx
function getPath(str)
return str:match("(.*[/\\])")
end
x = "/home/user/.local/share/app/some_file"
y = "C:\\Program Files\\app\\some_file"
print(getPath(x)) -- prints: /home/user/.local/share/app/
print(getPath(y)) -- prints: C:\Program Files\app\
GET PATH AND FILENAME @mokalux
function getPathAndFileName(xpath)
local xpathlength = xpath:len()
local tmpfolder = xpath:match("(.*[/\\])")
local tmpfolderlength = tmpfolder:len()
local finalfolder = tmpfolder:sub(1, tmpfolderlength-1)
local finalfile = xpath:sub(-(xpathlength-tmpfolderlength))
return finalfolder, finalfile
end
x = "/home/user/.local/share/app/some_file.png"
local folder, file = getPathAndFileName(x)
print(folder, file) -- prints: "/home/user/.local/share/app/", "some_file.png"
FORMAT 0xRRGGBB COLOR TO STRING @Rrraptor, @keszegh
local mycolor = 0x0000ff -- your color
-- prints "0x" as regular string, then add converted hex number with 6 leading zeros
-- keszegh
local mycolorstring = string.format("0x%06x",mycolor) --> "0x0000ff"
-- Rrraptor
local mycolorstring = ("0x%06x"):format(mycolor) --> "0x0000ff"
-- converts to hex number only
-- keszegh
local mycolorstring2 = string.format("%x",mycolor) --> "ff"
-- Rrraptor
local mycolorstring2 = ("%x"):format(mycolor) --> "ff"
SPLIT A STRING EVERY N CHARACTERS @https://stackoverflow.com/questions/76194310/how-would-i-split-a-string-once-every-n-characters
local mystr = "Hello, World!"
local splitevery = 2
for c in mystr:gmatch(('.'):rep(splitevery)) do
print(c)
end
Note: a remaining less than n characters will be silently ignored. Could be fixed by using a numeric for loop or .? instead
GFX
DRAWING A CIRCLE (PARTICLE) @hgy29
local mkr=Particles.new()
mkr:addParticles{
{x=0,y=0,size=100,color=0xFFFFFF}, -- outter circle
{x=0,y=0,size=70,color=0x4071B5}, -- inner circle
}
stage:addChild(mkr)
mkr:setPosition(120,120)
DRAWING A CIRCLE @xxx
xCircle = Core.class(Sprite)
function xCircle:init(r, steps, color)
color = color or 0xff0000
local sin, cos, d2r = math.sin, math.cos, math.pi / 180
local c = Shape.new()
c:setFillStyle(Shape.SOLID, color)
c:setLineStyle(0)
c:beginPath()
c:moveTo(r * sin(0 * d2r), r * cos(0 * d2r))
for i = 0, 360, 360 / steps do
c:lineTo(r * sin(i * d2r), r * cos(i * d2r))
end
c:endPath()
self:addChild(c)
end
--- usage
--xCircle(10, 5, 0xFF0000)
DRAWING ANOTHER CIRCLE (stars, circles, flowers) @gemboy100
Circle = Core.class(Mesh)
function Circle:init(__, r, COLOR, STEPS, PULL, CUT)
local r1 = r -- h radius
local r2 = r -- v radius
local STEPS = STEPS or math.floor((math.pi / 4) * r)
local COLOR = COLOR or 0
local PULL = PULL or 0
local CUT = CUT or 2
if STEPS < 3 then STEPS = 3 end
if PULL > r then PULL = 0
elseif PULL > 0 then
if CUT then
while STEPS % CUT ~= 0 do
STEPS += 1
end
elseif STEPS % 2 ~= 0 then STEPS +=1 end
end
self.c = {}
local v = {}
local ind = {}
local _i = 0
local _l = 0
local ou = 2
local step = math.pi / (STEPS / 2)
local pull = 0
v[#v + 1] = 0; v[#v + 1] = 0
self.c[#self.c + 1] = COLOR; self.c[#self.c + 1] = 1
--for i=step,PI*2, step do -- buggy cuz of infinite PI
for i = 1, STEPS do
_l += 1
if _l % CUT == 0 then pull = PULL else pull = 0 end
v[#v + 1] = (r1 - pull) * math.cos(i * step)
v[#v + 1] = (r2 - pull) * math.sin(i * step)
v[#v + 1] = (r1 - pull + ou) * math.cos(i * step)
v[#v + 1] = (r2 - pull + ou) * math.sin(i * step)
--
self.c[#self.c + 1] = COLOR
self.c[#self.c + 1] = 1
self.c[#self.c + 1] = COLOR
self.c[#self.c + 1] = 0.0
--
ind[#ind + 1] = _i + 3
ind[#ind + 1] = _i + 5
ind[#ind + 1] = _i + 4
ind[#ind + 1] = _i + 4
ind[#ind + 1] = _i + 3
ind[#ind + 1] = _i + 2
ind[#ind + 1] = _i + 4
ind[#ind + 1] = _i + 2
ind[#ind + 1] = 1
_i = _i + 2
end
ind[#ind - 7] = 2
ind[#ind - 6] = 3
ind[#ind - 5] = 2
ind[#ind - 2] = 2
self:setVertexArray(v)
self:setIndexArray(ind)
self:setColorArray(self.c)
end
function Circle:setColor(c, a)
local a = a or 1
self.c[1] = c
self.c[2] = a
for i = 3, #self.c, 4 do
self.c[i + 0] = c
self.c[i + 1] = a
end
self:setColorArray(self.c)
end
-- usage
--star
local c1 = Circle.new(false, 80, 0xffaa55, 9, 50)
c1:setColor(0xff0000, 0.75)
c1:setPosition(1 * 64, 1 * 64)
stage:addChild(c1)
--circle
local c2 = Circle.new(false, 32, 0xffaa55)
c2:setPosition(3 * 64, 1 * 64)
stage:addChild(c2)
--flowers
local c3 = Circle.new(false, 32, 0xffaa55, 80, 10, 8)
c3:setPosition(1 * 64, 3 * 64)
stage:addChild(c3)
local c4 = Circle.new(false, 64, 0xffaa55, 100, 5)
c4:setPosition(3 * 64, 3 * 64)
stage:addChild(c4)
DRAWING AN ARC @hgvyas123
function drawArc(xc,yc,xradius,yradius,startAngle,endAngle,isFill)
if yradius == nil then
yradius = xradius
end
if startAngle == nil then
startAngle = 0
end
if endAngle == nil then
endAngle = 360
end
if isFill == nil then
isFill = true
end
local shape = Shape.new()
if isFill then
shape:setFillStyle(Shape.SOLID, 0xff0000, 0.5)
else
shape:setLineStyle(3, 0x000000)
end
shape:beginPath()
for i=startAngle,endAngle do
if i == 1 then
shape:moveTo(math.sin(math.rad(i)) * xradius, math.cos(math.rad(i)) * yradius)
else
shape:lineTo(math.sin(math.rad(i)) * xradius, math.cos(math.rad(i)) * yradius)
end
end
if isFill then
shape:closePath()
end
shape:endPath()
shape:setPosition(xc, yc)
return shape
end
--- usage
--function drawArc(xc,yc,xradius,yradius,startAngle,endAngle,isFill)
local myarc = drawArc(128, 128, 64, 64, 0, 5 * 45, false)
stage:addChild(myarc)
CIRCULAR PROGRESS @hgy29
CircularProgress = Core.class(Sprite)
function CircularProgress:init(radius, width, color, font, fontscale)
self.radiusMin, self.radiusMax = radius - width / 2, radius + width / 2
self.color = color
self.font = font
self:addChild(Path2D.new())
local text = TextField.new(font, "-")
text:setTextColor(color)
text:setScale(fontscale or 1)
self:addChild(text)
-- self:setValue(0.4)
end
function CircularProgress:setValue(val, xcolor, xalpha)
local angs, ange = 0, math.pi * val * 1.999
local rl, rh = self.radiusMin, self.radiusMax
local ta = self:getChildAt(1)
local ra = math.floor(val * 2)
-- ta:setLineColor(self.color, xalpha)
-- ta:setFillColor(self.color, xalpha)
ta:setLineColor(xcolor, xalpha)
ta:setFillColor(xcolor, xalpha)
ta:setPath("MALAZ",
math.sin(angs) * rl, -math.cos(angs) * rl,
rl, rl, 0, ra, 1,
math.sin(ange) * rl, -math.cos(ange) * rl,
math.sin(ange) * rh, -math.cos(ange) * rh,
rh, rh, 0, ra, 0,
math.sin(angs) * rh, -math.cos(angs) * rh
)
ta:setLineThickness(4, 0.5)
ta = self:getChildAt(2)
ta:setText(("%d%%"):format(math.floor(val * 100)))
ta:setTextColor(xcolor)
ta:setAlpha(xalpha)
local tax, tay, taw, tah = ta:getBounds(ta)
ta:setAnchorPosition(tax + taw / 2, tay + tah / 2)
return ta
end
--- usage
-- meter = CircularProgress.new(40, 5, 0x770000, nil, 2)
HEX TO RGB @rrraptor
function hex2rgb(hex)
local r = (hex >> 16 & 0xff) / 255
local g = (hex >> 8 & 0xff) / 255
local b = (hex & 0xff) / 255
return r,g,b
end
--- usage
--local r, g, b = hex2rgb(0xFF0000)
HEX TO RGB table @rrraptor
function hex2rgb(hex)
local rgbtable = {} -- new 211115 XXX
rgbtable.r, rgbtable.g, rgbtable.b =
(hex >> 16 & 0xff) / 255, (hex >> 8 & 0xff) / 255, (hex & 0xff) / 255
return rgbtable
end
--- usage
--local rgbtable = hex2rgb(0xFF0000) -- rgbtable.r, rgbtable.g, rgbtable.b
PICKING A RANDOM COLOR @rrraptor
function randomColor() return "0x"..(math.random() * (1 << 24) | 0) end
--- usage
--local pixel = Pixel.new(randomColor(), 1, 32, 64)
--stage:addChild(pixel)
HEX TO RGB @rrraptor
function hex2rgb(hex)
local r = (hex >> 16 & 0xff) / 255
local g = (hex >> 8 & 0xff) / 255
local b = (hex & 0xff) / 255
return r,g,b
end
--- usage
--local r, g, b = hex2rgb(0xFF0000)
HEX TO RGB2 @https://gist.github.com/jasonbradley/4357406
function hex2rgb2(hex)
hex = hex:gsub("#","")
return tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6))
end
--- usage
--local r, g, b = hex2rgb2(0xFF0000)
SAVING IMAGE TO FILE @mokalux
Saving an image or part of an image to disk.
function xsaveJPGtoDoc(xoriginalimgfile, xposx, xposy, xsizew, xsizeh, xdestimgname)
local mytexture = Texture.new(xoriginalimgfile)
local mybmp = Bitmap.new(mytexture)
local rt = RenderTarget.new(mybmp:getWidth(), mybmp:getHeight())
rt:draw(mybmp)
rt:save("|D|tex_"..xdestimgname..".jpg", xposx, xposy, xsizew, xsizeh)
return "|D|tex_"..xdestimgname..".jpg"
end
--- usage
--local xsavedjpg = xsaveJPGtoDoc("gfx/bg/dark.jpg", 0, 0, 64, 64, "dark")
PREVENT FROM DRAGGING A SHAPE OVER OTHER SHAPE @hgvyas123
--[[
Drag the shapes around with your mouse or fingers
This code is MIT licensed, see <a href="http://www.opensource.org/licenses/mit-license.php" target="_blank" rel="nofollow">http://www.opensource.org/licenses/mit-license.php</a>
(C) 2010 - 2011 Gideros Mobile
]]
local myShapes = {}
function Sprite:collidesWith(sprite2)
local x,y,w,h = self:getBounds(stage)
local x2,y2,w2,h2 = sprite2:getBounds(stage)
return not ((y+h < y2) or (y > y2+h2) or (x > x2+w2) or (x+w < x2))
end
local function onMouseDown(self, event)
if self:hitTestPoint(event.x, event.y) then
self.isFocus = true
self.x0 = event.x
self.y0 = event.y
event:stopPropagation()
end
end
local function onMouseMove(self, event)
if self.isFocus then
self.lastX,self.lastY = self:getPosition()
local dx = event.x - self.x0
local dy = event.y - self.y0
self:setX(self:getX() + dx)
self:setY(self:getY() + dy)
self.x0 = event.x
self.y0 = event.y
for i=1,#myShapes do
if myShapes[i] ~= self then
if self:collidesWith(myShapes[i]) then
self:setPosition(self.lastX,self.lastY)
end
end
end
event:stopPropagation()
end
end
local function onMouseUp(self, event)
if self.isFocus then
self.isFocus = false
event:stopPropagation()
end
end
for i=1,5 do
local shape = Shape.new()
shape:setLineStyle(3, 0x000000)
shape:setFillStyle(Shape.SOLID, 0xff0000, 0.5)
shape:beginPath()
shape:moveTo(0, 0)
shape:lineTo(100, 0)
shape:lineTo(100, 50)
shape:lineTo(0, 50)
shape:closePath()
shape:endPath()
shape:setX(math.random(0, 320 - 100))
shape:setY(math.random(0, 480 - 50))
shape.isFocus = false
shape:addEventListener(Event.MOUSE_DOWN, onMouseDown, shape)
shape:addEventListener(Event.MOUSE_MOVE, onMouseMove, shape)
shape:addEventListener(Event.MOUSE_UP, onMouseUp, shape)
stage:addChild(shape)
table.insert(myShapes, shape)
end
local info = TextField.new(nil, "drag the shapes around with your mouse or fingers")
info:setPosition(23, 50)
stage:addChild(info)
CHECK POINT IS IN POLYGON @atilim
function pointInPolygon(vertices, x, y)
local intersectionCount = 0
local x0 = vertices[#vertices].x - x
local y0 = vertices[#vertices].y - y
for i= 1, #vertices do
local x1 = vertices[i].x - x
local y1 = vertices[i].y - y
if y0 > 0 and y1 <= 0 and x1 * y0 > y1 * x0 then
intersectionCount = intersectionCount + 1
end
if y1 > 0 and y0 <= 0 and x0 * y1 > y0 * x1 then
intersectionCount = intersectionCount + 1
end
x0 = x1
y0 = y1
end
return (intersectionCount % 2) == 1
end
local vertices = {
{x = 0, y = 0},
{x = 0, y = 100},
{x = 100, y = 100},
{x = 0, y = 0},
}
local shape = Shape.new()
shape:setFillStyle(Shape.SOLID, 0xff0000)
shape:setLineStyle(5, 0x0000ff, 1)
shape:beginPath()
shape:moveTo(vertices[1].x,vertices[1].y)
shape:lineTo(vertices[2].x,vertices[2].y)
shape:lineTo(vertices[3].x,vertices[3].y)
shape:lineTo(vertices[4].x,vertices[4].y)
shape:endPath()
shape:setPosition(64, 64)
stage:addChild(shape)
local vertices_shape = {}
for i = 1, #vertices do
vertices_shape[i] = {x = vertices[i].x + shape:getX(), y = vertices[i].y + shape:getY()}
end
shape:addEventListener(Event.MOUSE_HOVER, function(e)
if pointInPolygon(vertices_shape, e.x, e.y) then
print("hovering the shape")
else
print("not hovering the shape")
end
end)
STENCIL OPERATION @hgy29
local star = Bitmap.new(Texture.new("gfx/star.png", true))
stage:addChild(star)
local bluestar_tex = RenderTarget.new(star:getWidth(), star:getHeight())
local bluestar = Bitmap.new(bluestar_tex)
stage:addChild(bluestar) bluestar:setPosition(0, 128)
-- Here is the magic!
-- Clear our render target to all alpha
bluestar_tex:clear(0x000000, 0)
--[[Gideros don't draw pixels with alpha value of 0,
they are discarded at early stage. Use the stencil to get a
footprint of visible pixels of source image]]
star:setStencilOperation {
stencilClear = true,
stencilWriteMask = 1,
stencilFunc = Sprite.STENCIL_ALWAYS,
depthPass = Sprite.STENCIL_INCR
}
bluestar_tex:draw(star)
-- Render the footprint in the color we want
local mask = Pixel.new(0x00FFFF, 1, star:getWidth(), star:getHeight())
mask:setStencilOperation {
stencilClear = false,
stencilMask = 1,
stencilWriteMask = 1,
stencilRef = 0,
stencilFunc = Sprite.STENCIL_NOTEQUAL,
depthPass = Sprite.STENCIL_KEEP,
stencilFail = Sprite.STENCIL_KEEP
}
bluestar_tex:draw(mask)
--[[ The result is possibly enough here, but we lost the smoothed edges of
the original texture in the process. We can restore them with a smart alpha
blending trick:]]
star:setBlendMode(Sprite.ZERO, Sprite.SRC_ALPHA)
bluestar_tex:draw(star)
-- Restore our initial bitmap blending mode, to show it on screen as usual
star:setBlendMode(Sprite.ALPHA)
ZOOM SPRITE TO MOUSE POSITION @hgy29, @keszegh
This one is just awesome!
application:setBackgroundColor(0x333333)
-- sprites
local canvaslayer = Sprite.new()
local pixel = Bitmap.new(Texture.new("gfx/pot/1K-triangle_buble-diffuse.jpg"))
-- order
canvaslayer:addChild(pixel)
canvaslayer:setAnchorPoint(0.5, 0.5)
stage:addChild(canvaslayer)
-- position
canvaslayer:setPosition(application:getContentWidth()/2, application:getContentHeight()/2)
-- current zoom
local currzoom = 0.5
local zoomstart = currzoom
canvaslayer:setScale(currzoom)
-- thank you very much hgy29 & keszegh :-)
local pointerstartx, pointerstarty = 0, 0
local canvasposx, canvasposy = 0, 0
local offsetx, offsety = 0, 0
stage:addEventListener(Event.MOUSE_DOWN, function(e)
pointerstartx, pointerstarty = stage:globalToLocal(e.rx, e.ry)
e:stopPropagation()
end)
stage:addEventListener(Event.MOUSE_MOVE, function(e)
canvasposx, canvasposy = canvaslayer:getPosition()
offsetx = e.rx - pointerstartx
offsety = e.ry - pointerstarty
canvasposx += offsetx
canvasposy += offsety
canvaslayer:setPosition(canvasposx, canvasposy)
pointerstartx, pointerstarty = stage:globalToLocal(e.rx, e.ry)
e:stopPropagation()
end)
stage:addEventListener(Event.MOUSE_WHEEL, function(e) -- e.wheel = +- 120
zoomstart = currzoom
pointerstartx, pointerstarty = stage:globalToLocal(e.rx, e.ry)
canvasposx, canvasposy = canvaslayer:getPosition()
-- local viewportZoom=math.clamp(self.zoomStart*2^((self.panStart.ry-newY)/100),_MIN_ZOOM,_MAX_ZOOM)
currzoom = zoomstart + e.wheel/120/4
if currzoom <= 0.2 then currzoom = 0.2 end
if currzoom >= 2 then currzoom = 2 end
canvaslayer:setScale(currzoom)
local viewportx = canvasposx + (pointerstartx - canvasposx) * (1 - currzoom/zoomstart)
local viewporty = canvasposy + (pointerstarty - canvasposy) * (1 - currzoom/zoomstart)
canvaslayer:setPosition(viewportx, viewporty)
e:stopPropagation()
end)
VFX
PARTICLES EFFECT 1 @hgy29
function EffectExplode(s, scale, x, y, r, speed, texture)
local p = Particles.new()
p:setPosition(x, y)
p:setTexture(texture)
p:setScale(scale)
s:addChild(p)
local parts = {}
for i = 1, 50 do
local a = math.random() * 6.3
local dx, dy = math.sin(a), math.cos(a)
local sr = math.random() * r
local px, py = dx * sr, dy * sr
local ss = (speed or 1) * (1 + math.random())
table.insert(parts,
{
x = px, y = py,
speedX = dx * ss,
speedY = dy * ss,
speedAngular = math.random() * 4 - 2,
decayAlpha = 0.95 + math.random() *0.04,
ttl = 1000,
size = 10 + math.random() * 20
}
)
end
p:addParticles(parts)
Core.yield(2)
p:removeFromParent()
end
-- usage
stage:addEventListener(Event.MOUSE_DOWN,function (e)
Core.asyncCall(EffectExplode, stage,
1, e.x, e.y, 100, 2,
Texture.new("gfx/smoke.png", true)
)
end)
ANIMATION
FPS @atilim
local fps = TextField.new(nil, "")
fps:setScale(2)
fps:setPosition(16, 16)
fps:setTextColor(0xff0000)
stage:addChild(fps)
local frame = 0
local timer = os.timer()
local qFloor = math.floor
local function displayFps(event)
frame = frame + 1
if frame == 60 then
local currentTimer = os.timer()
fps:setText(qFloor(60 / (currentTimer - timer)))
frame = 0
timer = currentTimer
-- optional
--print ("memory used: "..qFloor(collectgarbage("count")/1000),"Mb")
end
end
-- Add FPS Counter to stage
stage:addEventListener(Event.ENTER_FRAME, displayFps)
MOVING A SPRITE IN AN ARC PATH @Disciple
local bone = Sprite.new()
--local boneImg = Bitmap.new(Texture.new("gfx/enemy01.png")) -- add your gfx!
-- or use this one (Pixel)
local boneImg = Pixel.new(0x0000ff, 0.75, 32, 48)
stage:addChild(bone)
bone:addChild(boneImg)
boneImg:setAnchorPoint(0.5, 0.5)
local grav = -15 / 2
local velx = -3 / 2
local rotvel = -3 / 2
local x = 300 / 2
local y = 400 / 2
local rotation = 0
function enterFrame ()
grav = grav + 0.3
x = x + velx
y = y + grav
rotation = rotation + rotvel
bone:setRotation(rotation)
bone:setPosition(x, y)
end
stage:addEventListener(Event.ENTER_FRAME, enterFrame)
MOVING A SPRITE IN AN HORIZONTAL SINE WAVE @Harrison
local blimp1 = Pixel.new(0x0000ff, 0.5, 32, 64)
blimp1:setAnchorPoint(0.5, 0.5)
blimp1:setPosition(0, 128)
blimp1.speedx = 1.2
stage:addChild(blimp1)
function onEnterFrame(event)
local posx = blimp1:getX() + blimp1.speedx
local posy = blimp1:getY() + (1.5 * math.sin(0.075 * posx))
if blimp1:getX() > application:getContentWidth() + blimp1:getWidth() / 2 then
blimp1:setPosition(-blimp1:getWidth() / 2, 128)
posx = blimp1:getX()
posy = blimp1:getY()
end
blimp1:setPosition(posx, posy)
end
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
MOVING A SPRITE IN A VERTICAL COS WAVE @Harrison
local blimp2 = Pixel.new(0x00ff00, 0.5, 64, 32)
blimp2:setAnchorPoint(0.5, 0.5)
blimp2:setPosition(128, 0)
blimp2.speedy = 1.3
stage:addChild(blimp2)
function onEnterFrame(event)
local posy = blimp2:getY() + blimp2.speedy -- posy first
local posx = blimp2:getX() + 2.5 * math.cos(0.1 * posy) -- posy first
if blimp2:getY() > application:getContentHeight() + blimp2:getHeight() then
blimp2:setPosition(128, -blimp2:getHeight())
posx = blimp2:getX()
posy = blimp2:getY()
end
blimp2:setPosition(posx, posy)
end
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
FILES
CSV @hgy29
Load a CSV file.
function loadCSV(file)
local function csvsplit(line)
local t, w, l2 = {}, nil, nil
while #line > 0 do
w, l2 = line:match("\"([^\"]*)\"[,\r\n]?(.*)") -- Check for quoted string
if not w then w, line = line:match("([^,]*)[,\r\n]?(.*)") -- Non quoted
else line = l2 end
if not w then break end --Nothing or issue, break
t[#t + 1] = w
end
return t
end
local headers, csv = nil, {}
for line in io.lines(file) do
f = csvsplit(line)
if not headers then -- Assume first line is headers
headers = {} for n, v in ipairs(f) do headers[v] = n end
else
csv[#csv + 1] = f
end
end
csv.getField = function(self, row, field) return self[row][headers[field]] end
return csv
end
--- usage
--csv=loadCSV("135-bis-bt.csv")
--print(csv:getField(4,"Value"))
--print(csv:getField(7,"Time")
JSON @xxx
Loading and saving preferences.
require "json" -- you must add JSON plugin to your app
function saveData(filepath, value)
local contents = json.encode(value)
local file = io.open("|D|"..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("|D|"..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
-- globals
g_configfilepath = "myplayground.txt"
g_language = application:getLanguage()
g_theme = "dark"
g_isaudio = true
g_level = 1
-- init prefs
local mydata = getData(g_configfilepath) -- try to read information from file
-- if no prefs file, create it
if not mydata then
mydata = {g_language, g_theme, g_isaudio, g_level}
saveData(g_configfilepath, mydata) -- create file and save datas
else
g_language = mydata[1]
g_theme = mydata[2]
g_isaudio = mydata[3]
g_level = mydata[4]
end
-- save prefs
function mySavePrefs(xlanguage, xtheme, xisaudio, xlevel)
local mydata = {xlanguage or g_language, xtheme or g_theme, xisaudio or g_isaudio, xlevel or g_level}
saveData(g_configfilepath, mydata) -- save new datas
g_language = mydata[1]
g_theme = mydata[2]
g_isaudio = mydata[3]
g_level = mydata[4]
end
--- usage
--mySavePrefs("en", "dark", true, 1)
--print(g_language)
--print(g_theme)
JSON V2 @mokalux
require "json" -- you must add JSON plugin to your app
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 result, value
local file = io.open(filepath, "r")
if file then
local contents = file:read("*a") -- read contents
-- value = json.decode(contents) -- decode json
result, value = pcall(json.decode, contents) -- try to decode json
io.close(file)
end
return result, value
end
--[[
-- usage
-- init.lua
g_configfilepath = "|D|myconfigfile.txt" -- C:\Users\xxx\AppData\Roaming\myappname on Windows
-- ...
-- main.lua
function myLoadPrefs()
local _result, mydata = getData(g_configfilepath) -- try to read information from file
if not mydata then -- if no prefs file, create it
print("* creating prefs data file")
mydata = {}
-- your data
mydata.g_language = g_language
mydata.g_bgcolor = g_bgcolor
-- ...
-- create file and save datas
saveData(g_configfilepath, mydata)
myLoadPrefs() -- reload!
else -- data exist, use them!
g_language = mydata.g_language -- global variable
g_bgcolor = mydata.g_bgcolor or 0x333333 -- global variable
-- ...
end
end
function mySavePrefs()
local mydata = {} -- clear the table
-- prefs
mydata.g_language = g_language
mydata.g_bgcolor = g_bgcolor or 0x333333
-- save new data
saveData(g_configfilepath, mydata)
end
-- main.lua or elsewhere
myLoadPrefs() -- load initial prefs
-- use the data
application:setBackgroundColor(g_bgcolor)
-- ...
]]
MATH
CLAMP @rrraptor
Limits the value to the specified range.
-- v - value to limit
-- min, max - range
function clamp(v, min, max)
return (v <> min) >< max
end
--- usage
--clamp(20, 0, 100) --> 20
--clamp(-20, 0, 100) --> 0
--clamp(120, 0, 100) --> 100
LERP @xxx
Lerps between 2 values.
local function lerp(a, b, t)
return a + (b-a) * t
end
MAP @rrraptor
Transforms one range to another.
-- v - value to map
-- minSrc - lower bound of the value's current range
-- maxSrc - upper bound of the value's current range
-- minDst - lower bound of the value's target range
-- maxDst - upper bound of the value's target range
-- clampValue - constrain the value to the newly mapped range
function map(v, minSrc, maxSrc, minDst, maxDst, clampValue)
local newV = (v - minSrc) / (maxSrc - minSrc) * (maxDst - minDst) + minDst
return not clampValue and newV or clamp(newV, minDst >< maxDst, minDst <> maxDst)
end
--- usage
--map(0.5, 0, 1, 0, 200) -> 100
--map(10, 0, 10, 0, 200) -> 200
--map(0, -1, 1, 0, 1) -> 0.5
ROUND @http://lua-users.org/wiki/FormattingNumbers
Rounds a number to the nearest decimal.
--[[
round(val, n) - Rounds a number to the nearest decimal places.
val - The value to round.
n - Number of decimal places to round to.
-- usage
--print( round( 1.5678 ) ) -- prints: 1.57
]]
function xround(val, n)
if (n) then
return math.floor( (val * 10^n)+0.5 ) / (10^n)
else
return math.floor(val+0.5)
end
end
ROUND2 @https://stackoverflow.com/a/58411671/870125
Rounds a number to the nearest decimal.
local function round(num)
return num + (2^52 + 2^51) - (2^52 + 2^51)
end
ROUND3 @http://lua-users.org/wiki/SimpleRound
Rounds a number to the nearest decimal. Seems to be fast.
function round(n, mult)
mult = mult or 1
return math.floor((n+mult/2)/mult) * mult
end
Move Towards @https://devforum.roblox.com/t/new-lua-functions-mathsign-and-mathclamp/37309/14
local function moveTowards(current, target, maxDelta)
if current < target then return math.min(target, current + maxDelta)
elseif current > target then return math.max(target, current - maxDelta)
else return target
end
end
Shoot Towards @mokalux
function shoot()
local projectiletex = "gfx/projectiles/bullet1.png"
local projectilespeed = 8*1
-- a turret targeting a player
local angle = math.atan2(player.y - turret.y, player.x - turret.x)
-- projectile direction
local vx, vy = projectilespeed * math.cos(angle), projectilespeed * math.sin(angle)
-- ...
-- projectile implementation example
local g = Projectile.new(
texture=projectiletex,
x=turret.x + 8*4, y=turret.y + 0, -- your projectile start location
speedx=vx, speedy=vy,
})
g = nil -- cleanup
-- ...
end
TABLE
SELF VALUE TABLE TRICK @mokalux
local myvalue == "myvalue"
self[myvalue] -- this is equivalent to self.myvalue
HIGHEST / LOWEST NUMBER IN A TABLE @https://stackoverflow.com/questions/5178087/how-do-i-get-the-highest-integer-in-a-table-in-lua
Gets the highest or the lowest number in a table.
print(math.max(unpack{4, 5, 62, -5, 12, 9})) -- 62
print(math.min(unpack{4, 5, 62, -5, 12, 9})) -- -5
MERGING 2 TABLES @xxx
method 1:
z = {}
n = 0
for _,v in ipairs(x) do n=n+1; z[n]=v end
for _,v in ipairs(y) do n=n+1; z[n]=v end
method 2:
levelsetup = {color=0x5E3C3A, isshape=true, restitution=0, friction=1}
tablebase = { x = 64, y = 200, w = 400, h = 250, rotation = 0}
for k, v in pairs(levelsetup) do
tablebase[k] = v
end
DEBUGGING
TEXTURE MEMORY USAGE @SinisterSoft
local temp, oldusage
temp=(application:getTextureMemoryUsage()/1024)
if temp~=oldusage then
oldusage=temp
print("* 1 Texture usage: "..temp.." MB")
end
More to come God's willing...