Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Quick questions about Gideros&Lua - Page 5 — Gideros Forum

Quick questions about Gideros&Lua

1235714

Comments

  • Apollo14Apollo14 Member
    edited March 2018
    Guys how to change color scheme of Zerobrane Studio?
    I've opened their file 'cfg/scheme-picker.lua', changed:
    styles = loadfile('cfg/tomorrow.lua')('TomorrowNightBlue')
    to:
    styles = loadfile('cfg/tomorrow.lua')('Monokai')
    But after restarting Zerobrane Studio color scheme stays the same, nothing changed.
    How to chage it?
    (ultimately I want it to be the same as in Gideros, did anybody tune a Zerobrane theme to be Gideros-like? :smile: )
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • antixantix Member
    Did you follow the instructions and modify cfg\user.lua?
  • Apollo14Apollo14 Member
    edited March 2018
    Did you follow the instructions and modify cfg\user.lua?
    uh, I didn't notice that new 'user.lua' has to be created, now it works well thx!

    Guys how to perform certain action after sound completed?
    it doesn't work for me:
    congratsSfx = Sound.new("sounds/congrats.wav")
    congratsSfx:play()
     
    congratsSfx:addEventListener(Event.COMPLETE, function()
    	print('sound completed!')
    end)
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • Apollo14Apollo14 Member
    edited March 2018
    Guys is it better (perfomance-wise) to always add event listeners or call functions directly from enterFrame?
    (I've seen somewhere that it's better to avoid event listeners whenever we can, is it true?)
    Or some other method is better?
    Variant #1 without dispatcher:
    clicksCounter=0
    isWindowShown=false
     
    function onMouseDownFunc(event)
    clicksCounter+=1
    --if clicksCounter ==10 then showAchievementWindow() --it could be here, but in more complex apps I'd need to watch the variable 'clicksCounter' every frame
    --and counter could be changed not only after MouseDown, but after other actions
    end
    stage:addEventListener(Event.MOUSE_DOWN, onMouseDownFunc)
     
    --achievement window function should be called only once:
    function showAchievementWindow()
    	if not isWindowShown then
    		print("now achievement window has to be shown!")
    		isWindowShown=true
    	end
    end
     
    function onEnterFrameFunc()
    	if clicksCounter == 10 then
    	showAchievementWindow()
    	end
    end
    stage:addEventListener(Event.ENTER_FRAME, onEnterFrameFunc)
    Variant #2 using event dispatcher:
    clicksCounter=0
    function onMouseDownFunc(event)
    clicksCounter+=1
    end
     
    stage:addEventListener(Event.MOUSE_DOWN, onMouseDownFunc)
     
    myDispatcher = EventDispatcher.new()
     
    function showAchievementWindow2()
    	print("now achievement window has to be shown!")
    	myDispatcher:removeEventListener("tenClicksDone", showAchievementWindow2)
    end
     
    myDispatcher:addEventListener("tenClicksDone", showAchievementWindow2)
     
    stage:addEventListener(Event.ENTER_FRAME, function()
    if clicksCounter == 10 then
    myDispatcher:dispatchEvent(Event.new("tenClicksDone"))
    end
    end)
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • The built-in event listeners are fine. This is the problem:
    myDispatcher = EventDispatcher.new()
    If used rarely it's fine, but if you use it every frame, or in loops, it can slow things down a lot. I made a callback system, CallbackBroadcaster, that works in the same way, but is much more efficient.

    Likes: Apollo14

    My Gideros games: www.totebo.com
    +1 -1 (+1 / -0 )Share on Facebook
  • I use the event listeners like an interrupt system in the old days - so for mouse, controller input, timers and vblank (enter frame) I use an event listener. I also use them to add the game overlay system so that the game can work independently of menus, high score tables, etc... That's all really.

    Likes: Apollo14

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited March 2018
    @SinisterSoft when do we need to include "64bits libs" in our apk? I don't get what is their purpose?
    Should we include 64bits libs to every app?


    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • hgy29hgy29 Maintainer
    @Apollo14, basically you should always do it for performance reasons, and also because it will soion become mandatory for play store. However it will double the size of gideros core (twice as much libraries), and there can still be a few thirs party libraries (ads providers, etc) not yet compatible, that's why it is still disabled by default.

    I strongly encourage everyone to have a try at 64bit before google enforces it, to be sure your apps actually work ok in 64 bit.
    +1 -1 (+4 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited March 2018
    Guys what is a good practice for changing background sprite in my app?
    I feel like my code is nowhere near to an optimal solution :D :D
    bigPack = TexturePack.new("pics/bigPack.txt", "pics/bigPack.png", true)
    bgArr = {}
    bgArr[1] = Bitmap.new(bigPack:getTextureRegion("bg1.jpg"))
    bgArr[2] = Bitmap.new(bigPack:getTextureRegion("bg2.jpg"))
    bgArr[3] = Bitmap.new(bigPack:getTextureRegion("bg3.jpg"))
     
    stage:addChild(bgArr[1])
    stage:addChild(bgArr[2])
    stage:addChild(bgArr[3])
    bgArr[1]:setVisible(true)
    bgArr[2]:setVisible(false)
    bgArr[3]:setVisible(false)
    currentBgIndex = 1
    To change background I'd have to do something like this:
    function setBg2()
    bgArr[currentBgIndex]:setVisible(false)
    currentBgIndex=2
    bgArr[currentBgIndex]:setVisible(true)
    end)
    Another solution may be to create MovieClip with 3 bg sprites, and just change frames, like here: http://giderosmobile.com/forum/discussion/comment/55399/#Comment_55399
    Is there something else better?

    First i thought it would work like that:
    bgArr[1] = Bitmap.new(bigPack:getTextureRegion("bg1.jpg"))
    bgArr[2] = Bitmap.new(bigPack:getTextureRegion("bg2.jpg"))
    bgArr[3] = Bitmap.new(bigPack:getTextureRegion("bg3.jpg"))
     
    currentBg = bgArr[1]
    stage:addChild(currentBg)
     
    function setBg2()
    currentBg = bgArr[2]
    end
    but once added to stage, currentBg doesn't update
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • SinisterSoftSinisterSoft Maintainer
    edited March 2018
    Something like this:
    bigPack = TexturePack.new("pics/bigPack.txt", "pics/bigPack.png", true)
    bgTex = {}
    for loop=1,3 do
      bgTex[loop] = bigPack:getTextureRegion("bg"..loop..".jpg")
    end
    bgArr=Bitmap.new(bgTex[1])
     
    stage:addChild(bgArr)
     
    function setBg(n)
      bgArr:setTextureRegion(bgTex[n])
    end
     
    setBg(3)
    (I just wrote this in the forum without using the editor, so there may be an error or two)

    Likes: Apollo14, MoKaLux

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+2 / -0 )Share on Facebook
  • Guys I'm testing admob ads, why it doesn't work on device player, what did I miss?
    in my main.lua I added Google's test key:
    require "ads"
    admob = Ads.new("admob")
    admob:setKey("ca-app-pub-3940256099942544/6300978111")
    admob:showAd("banner")
    admob:setAlignment("center", "top")
    Console errors:
    main.lua:6: module 'ads' not found:
    	no field package.preload['ads']
    	no file './ads.lua'
    	no file './ads/init.lua'
    	no file './_LuaPlugins_/ads.lua'
    	no file './_LuaPlugins_/ads/init.lua'
    	no file '/usr/local/share/lua/5.1/ads.lua'
    	no file '/usr/local/share/lua/5.1/ads/init.lua'
    	no file '/usr/local/lib/lua/5.1/ads.lua'
    	no file '/usr/local/lib/lua/5.1/ads/init.lua'
    	no file './ads.so'
    	no file '/usr/local/lib/lua/5.1/ads.so'
    	no file '/usr/local/lib/lua/5.1/loadall.so'
    stack traceback:
    	main.lua:6: in main chunk
    Ads plugin settings:
    image
    admobTest.png
    946 x 539 - 37K
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • antixantix Member
    You have to make a special player to test in the player. The website has instructions on how to make a player with the plugin included.

    Likes: SinisterSoft

    +1 -1 (+1 / -0 )Share on Facebook
  • Pick your plugins, then go to export, pick Android, then use the selector to pick player rather than full game.

    Likes: antix, Apollo14

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+2 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited March 2018
    Guys I wonder why it doesn't print keys&values of a table in logical order?
    varAr={}
    var1="someKey"
     
    for i=1,5 do
    varAr[var1..i] = "valueAssigned"
    end
     
    for k,v in pairs(varAr) do
    print(k,v)
    end
    This stuff is shown in the output panel:
    Uploading finished.
    someKey4	valueAssigned --why 4 is first?
    someKey1	valueAssigned
    someKey5	valueAssigned
    someKey3	valueAssigned
    someKey2	valueAssigned
    While I was expecting:
    Uploading finished.
    someKey1	valueAssigned
    someKey2	valueAssigned
    someKey3	valueAssigned
    someKey4	valueAssigned
    someKey5	valueAssigned
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • hgy29hgy29 Maintainer
    There is absolutely no notion of ordering in lua tables, it makes sense only for arrays where all values have numerical indices

    Likes: Apollo14

    +1 -1 (+1 / -0 )Share on Facebook
  • Without looking at the lua source code, I think lua converts the key name to a hash then searches for it, it could be that the hashes are sorted in some way and that the order of key pairs is revealed in order of the hashes ?

    Likes: Apollo14

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited March 2018
    Guys how does Core.yield(false) work?
    Can you provide a basic example? I just don't get it, in what situations it may be needed?
    Parameters 'true' and [number of seconds to wait] are pretty much self-explanatory :)
    function testFunc1()
    	for i=1,5 do
    	Core.yield(1)
    	print(i.." seconds passed")
    	end
    end
     
    Core.asyncCall(testFunc1)
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • hgy29hgy29 Maintainer
    The dafult behavior of 'fakethreads' is to autoyield, that is gideros will check periodically if there is some time left in the frame for the thread, and if not an automatic yield is performed.

    Calling Core.yield(true) disable autoyield, and makes sure the thread is further executed without interruption until it calls Core.yield(true/number) again.
    To go back to autoyielding mode, you need to call Core.yield(false)
    +1 -1 (+2 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited April 2018
    Guys I was going to create an Idle economic game.
    It seems there have to be LOTS of counters, multipliers, boosts, etc.
    And they have to be used extremely frequently, probably most of them every frame.
    Perfomance-wise what is better: to keep them all in one table, or in separate vars?
    --first variant:
    INCOME = {}
    INCOME.perSecond = 10
    INCOME.passiveMultiplier = 1
    INCOME.perTap = 1
    INCOME.perTapMultiplier = 1
    --INCOME.etc...
     
     
    --second variant:
    incomePerSecond = 10
    incomePassiveMultiplier = 1
    incomePerTap = 1
    --etc...
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • local variables

    Likes: Apollo14

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • But if you have loads then it might be easier to code in a table - you could have a table of incrementers that increments a table of variables - you could then iterate through them - even make new ones up live.

    Likes: Apollo14

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • antixantix Member
    store them in a table for ease of saving. When processing you can just make them local at that point.

    Likes: Apollo14

    +1 -1 (+1 / -0 )Share on Facebook
  • piepie Member
    I'd say the first variant:
    a single table, doesn't matter its size and nested tables, should count as a single variable and it's easy to save.
    Then you can go local to operate/process entries, and save the result back to the table.

    Likes: antix, Apollo14

    +1 -1 (+2 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited April 2018
    Guys why GTween onComplete doesn't work in my case? GTween animation runs normally, but it doesn't call onTweenComplete function
    update:uh, I had to add 'tween1.dispatchEvents=true'
    function onTweencomplete()
    	print("tween completed") -- it doesn't print
    end
    local tween1 = GTween.new(picsArr[1], 0.5, {x = -600}, {delay = 0, ease = easing.linear, onComplete=onTweencomplete})
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • jdbcjdbc Member
    edited April 2018
    Try to use
    local tween = GTween.new(picsArr[1], 0.5, {x = -600}, {ease = easing.linear,
    						onComplete = function()
    									  print("tween completed")
    								       end
    									})

    Likes: Apollo14

    +1 -1 (+1 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited April 2018
    Guys, what way is optimal to play random sound every 20-30 seconds?

    Is it a good practice to create infinite recursive functions or they should be avoided? (app is intened to be active for long periods of time, memory leaks are extremely undesired)
    function randRecursive()
    	local timerDelayed = Timer.delayedCall(math.random(20000,30000), function()
    		local randVoice = Sound.new("sounds/voice"..math.random(1,17)..".mp3")
    		randVoice:play()
    		randVoice=nil --should we make it nil for better garbage collection?
    		randRecursive() --lol:)
    	end)
    end
     
    randRecursive()
    Another variant:
    function atRandomPeriod()
    	for i=1,9000 do
    		Core.yield(math.random(20,30))
    		local randVoice = Sound.new("sounds/voice"..math.random(1,17)..".mp3")
    		randVoice:play()
    		randVoice=nil
    	end
    end
     
    Core.asyncCall(atRandomPeriod)
    Or something else maybe?
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • hgy29hgy29 Maintainer
    First variant should be ok since your callback doesn’t use up values from the calling function, so no memory issue here. It isn’t even recursive since it is called in an event handler. But second variant is easier to understand imho.

    Likes: Apollo14

    +1 -1 (+1 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited April 2018
    Guys how to properly break async loops?
    For some reason my trigger doesn't work:
    local allowPulse=true
     
    local function pulse(obj,trigger)
    	local i=0
    	while trigger==true do
    		obj:setAlpha((math.sin(i))^2)
    		i+=0.04
    		Core.yield(true)
    	end
    end
     
    Core.asyncCall(pulse,mySprite,allowPulse)
     
    --I'm trying to stop loop after 3000ms:
    local timerDelayed = Timer.delayedCall(3000, function() allowPulse=false end)
    --Trigger is switched to false, but loop doesn't stop!
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
  • i think it sends only the value and not a pointer to your var, so it is always true if it's true at the beginning. you could e.g. change "while trigger==true do"
    to "while allowPulse==true do" and it should work i think.
    otherwise, to send a pointer instead of the value, somebody else should be able to help.

    Likes: Apollo14

    +1 -1 (+1 / -0 )Share on Facebook
  • Apollo14Apollo14 Member
    edited April 2018
    Thx @keszegh !
    I've decided to create a table with triggers (though I'm not sure if it is an optimal way):
    local allowPulse={}
    allowPulse.trigger1=true
    allowPulse.trigger2=true
    allowPulse.trigger3=true
    allowPulse.trigger4=true
     
    local function pulse(obj,triggerName)
    	local i=0
    	while allowPulse[triggerName]==true do
    		obj:setAlpha((math.sin(i))^2)
    		i+=0.04
    		Core.yield(true)
    	end
    end
     
    Core.asyncCall(pulse,mySprite1,"trigger1")
    Core.asyncCall(pulse,mySprite2,"trigger2")
    --etc...
    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
Sign In or Register to comment.