Saving On/Off states of buttons and music

Hi folks. I have a settings screen in my app with just 2 buttons. Music On/Off and Sound On/Off. I can get the audio to turn off when I click them but when i leave the scene and come back the buttons reset to their “on” state and the music remains off. I need some way of saving these button states. Here’s my code…

[code]

module(…, package.seeall)

–====================================================================–
– SCENE: info.lua
–====================================================================–
new = function ()


– Imports

local ui = require ( “ui” )


– Groups

local localGroup = display.newGroup()


– Display Objects

local image = display.newImageRect( “images/titlescreenbg.png”, 480, 360 )
local frame = display.newImageRect( “images/infoScreenBg.png”, 480, 360 )
local backBg = display.newImageRect( “images/backBg.png”, 150, 67 )

local soundOn_btn = display.newImageRect(“images/sound_on.png”,162,35)
local soundOff_btn = display.newImageRect(“images/sound_off.png”,162,35)

local musicOn_btn = display.newImageRect(“images/music_on.png”,162,35)
local musicOff_btn = display.newImageRect(“images/music_off.png”,162,35)


– Functions

function toggleMusicButton(event)
if(event.phase == “ended”) then
if musicOn_btn.isVisible == true then
musicOff_btn.isVisible = true
musicOn_btn.isVisible = false;
print(“Music Off”)
audio.setVolume( 0, { channel=1 } )
else
musicOff_btn.isVisible = false
musicOn_btn.isVisible = true;
print(“Music On”)
audio.setVolume( 1, { channel=1 } )
end
end
end

function toggleSoundButton(event)
if(event.phase == “ended”) then
if soundOn_btn.isVisible == true then
soundOff_btn.isVisible = true
soundOn_btn.isVisible = false;
print(“Sound Off”)
audio.setVolume( 0, { channel=2 } )
else
soundOff_btn.isVisible = false
soundOn_btn.isVisible = true;
print(“Sound On”)
audio.setVolume( 1, { channel=2 } )
end
end
end

– BACK BUTTON FUNCTION

local function backBut(event)
if event.phase == “began” then
display.getCurrentStage():setFocus( event.target)
elseif event.phase == “ended” then
event.target:removeEventListener(“touch”, backBut)
display.getCurrentStage():setFocus(nil)
director:changeScene( “levelselect”, “moveFromBottom” )
end
end


– UI Objects

local backButton = ui.newButton{
defaultSrc = “images/backButton.png”,
defaultX = 90,
defaultY = 36,
overSrc = “images/backButton.png”,
overX = 100,
overY = 40,
onEvent = goBack,
id = “backButton”
}


– Variables

musicOff_btn.isVisible = false

soundOff_btn.isVisible = false

–====================================================================–
– INITIALIZE
–====================================================================–

local initVars = function ()


– Positions

image.x = display.contentWidth/2
image.y = display.contentHeight/2

backBg:setReferencePoint(display.TopRightReferencePoint);
backBg.x = display.contentWidth
backBg.y = display.screenOriginY

backButton:setReferencePoint(display.TopRightReferencePoint);
backButton.x = display.contentWidth - 10
backButton.y = display.screenOriginY + 3

frame.x = display.contentWidth /2
frame.y = display.contentHeight /2

musicOn_btn.x = 330
musicOn_btn.y = display.contentHeight / 2 -25

musicOff_btn.x = 330
musicOff_btn.y = display.contentHeight / 2 -25

soundOn_btn.x = 330
soundOn_btn.y = display.contentHeight / 2 +25

soundOff_btn.x = 330
soundOff_btn.y = display.contentHeight / 2 +25


– Inserts

localGroup:insert(image)
localGroup:insert(frame)
localGroup:insert(backBg)
localGroup:insert(backButton)
localGroup:insert(musicOff_btn)
localGroup:insert(musicOn_btn)
localGroup:insert(soundOff_btn)
localGroup:insert(soundOn_btn)


– Listeners

backButton:addEventListener(“touch”, backBut)
musicOn_btn:addEventListener(“touch”, toggleMusicButton)
musicOff_btn:addEventListener(“touch”, toggleMusicButton)
soundOn_btn:addEventListener(“touch”, toggleSoundButton)
soundOff_btn:addEventListener(“touch”, toggleSoundButton)

end


– Initiate variables

initVars()


– MUST return a display.newGroup()

return localGroup

end

[/code] [import]uid: 79620 topic_id: 23693 reply_id: 323693[/import]

For saving different values i would recomend ICE :wink: Its a super simple module created by Graham Ranson. just seach for ICE here on the forum and you should find it :wink: [import]uid: 119384 topic_id: 23693 reply_id: 95216[/import]

I tried using ICE but i got confused :frowning: [import]uid: 79620 topic_id: 23693 reply_id: 95242[/import]

@rebel what did you get confused with? Don’t give up, we can help you get it going [import]uid: 84637 topic_id: 23693 reply_id: 95267[/import]

I think he needs code to set button state when the screen loads. [import]uid: 10389 topic_id: 23693 reply_id: 95310[/import]

How can I save more than one file in the same path? [import]uid: 81091 topic_id: 23693 reply_id: 96902[/import]

I can help you with one button, because I don’t know how to save more than one variable in the same path.

[code]
local prevMusic
local MusicOn

–Loading Data
local path = system.pathForFile ( “data.txt”, system.DocumentsDirectory )
local file = io.open( path, “r” )
if file then
prevMusic = file:read ()
musicOn = prevMusic
io.close( file )
end

–Exceptions for First Time
if ( musicOn == nil ) then
musicOn = true
prevMusic = true
end

–Saving Data
local function write (e)
if ( e.type == “applicationExit” ) then
file = io.open( path, “w+” )
prevMusic = musicOn
file:write ( prevMusic )
io.close( file )
end
end
end
Runtime:addEventListener ( “system”, write )
[/code] [import]uid: 81091 topic_id: 23693 reply_id: 96903[/import]

Hi

Can anybody please help me, how this can be accomplished? I have tried something similar, with the code posted above. But I can’t get it to work properly. Is it smart to use ICE for this, only?

Thank you in advance. [import]uid: 122802 topic_id: 23693 reply_id: 105743[/import]

Is it really that much trouble to just save those states as globals, ie:

\_G.musicOn = false

ICE is presumably for saving those settings to a file so that if your app is closed and reopened you can fetch the information again. If you’re just worried about jumping scene to scene, you should either be using:

a. Globals, or…
b. use a seperate lua file that does effectively the same thing in smaller doses, eg:

[code]-- myVars.lua
local table = {}
table.musicOn = false

return table[/code]

^ That is basically a standalone lua file that you require into any other lua file where you need to read the variable. (eg:, it’s now “myVars.musicOn”)

Globals are perfectly fine to use, though, so long as you don’t go crazy with them. [import]uid: 41884 topic_id: 23693 reply_id: 105751[/import]

Hi richard9

Thank you for the help, I have decied to use globals, but I don’t know how I have to use them in this scenario? Can you help med with that?

Thank you in advance :slight_smile: [import]uid: 122802 topic_id: 23693 reply_id: 105921[/import]

Well, you said you want to check for whether the music and sound are on and off every time you enter the scene, right?

So what you should do is add these to main.lua:

--main.lua \_G.music = true

These are globals - variables you can access from any file in your project, without includes or anything. They are slower to access, but since you’re just using them for major game options that don’t change hundreds of times each second, the speed difference is unnoticeable.

From there what you should do every time you enter the scene is do a check for:
a) the variable state, and
b) whether it’s already on

I have no idea how to actually do that, but it sounds like you already have something in mind. But let’s say it’s audio.isChannelPlaying(1)?

--in the scene enter function if music and not audio.isChannelPlaying(1) then -- whatever command here you want to start playing the audio elseif not music and audio.isChannelPlaying(1) then -- in this case, "not music" means "music = false", so it's just saying if false, stop playing. Maybe this is unneeded for you end

You can then basically repeat the same mechanic for the other global.

The last remaining thing you would need to do is toggle the variable when you toggle music.

--wherever your music on/off function is -- if toggling off music = false -- if toggling on music = true

Does that help at all? [import]uid: 41884 topic_id: 23693 reply_id: 105924[/import]

Hi again

Thank you for the explanation and the code. But I can’t seem to get it to work properly :frowning:

this is my code:

[lua]_G.music = true

local function UnMutePressed ( event )
if event.phase == “release” and MusicOff.isActive then

if not music and not audio.isChannelPlaying(1) then
music = true

audio.setVolume( 0.75, { channel=1 } )
MusicOn.isVisible = true
MusicOff.isVisible = false
end
end

end

local function MutePressed ( event )
if event.phase == “release” and MusicOn.isActive then

if music and audio.isChannelPlaying(1) then
music = false

audio.setVolume( 0, { channel=1 } )

MusicOn.isVisible = false
MusicOff.isVisible = true
end

end

end

MusicOn = ui.newButton{
defaultSrc = IMAGE_DIR…“SM2.png”,
defaultX = 30,
defaultY = 30,
onEvent = MutePressed

}

MusicOn.x = 20; MusicOn.y = 20
MusicOn.isVisible = true

MusicOff = ui.newButton{
defaultSrc = IMAGE_DIR…“SM1.png”,
defaultX = 30,
defaultY = 30,
onEvent = UnMutePressed
}
MusicOff.x = 20; MusicOff.y = 20
MusicOff.isVisible = false[/lua]

Thank you in advance for the help :slight_smile:
[import]uid: 122802 topic_id: 23693 reply_id: 105941[/import]

Well, a few points:

  1. You need to be doing the “if not music” line check in [lua]function scene:enterScene( event )[/lua], not in your button code. It seems useless for your buttoncode anyway as you don’t seem to be pausing your audio, you’re just cutting the volume.

Correct me if I’m wrong, but I thought your problem was that upon switching to a new scene, the audio cuts out?

--myscene.lua function scene:enterScene(event) if music and audio.isChannelPlaying(1) then print("music switch is on but isn't playing! Fixing!") -- put your audio loading command here end -- ...

For your buttons, you need to check the variable in order to see which button to show.

--wherever your audio button code is, put this after the ui.newButtons are made if music then -- music == true MusicOn.isVisible = true MusicOff.isVisible = false MusicOff.isActive = false -- assuming this disables the listener? else -- music == false MusicOn.isVisible = false MusicOn.isActive = false -- assuming this disables the listener? MusicOff.isVisible = true end [import]uid: 41884 topic_id: 23693 reply_id: 105950[/import]

Hi richard9

Thank you for the help, but I am a little confused now. I don’t use storyboard, so I don’t know how I can check the music variable in enter scene with director.

I have this in my main.lua file

[lua] _G.music = true[/lua] - but do I need to write _G. in front of it, when it is in the main.lua.?If I delete the _G. will it still be global?

Thank you for the help :slight_smile: [import]uid: 122802 topic_id: 23693 reply_id: 106063[/import]

  1. Ah, I’m sorry, I somehow thought you were using storyboard. I can’t really help with director specifically since I don’t use it.

But the principles remain true. Run the check when you enter the scene (I guess in director this just means the beginning of the scene file?) as a seperate process from all of your button stuff.

  1. _G means “global”. But you only have to write it once.

\_G.music = true -- use \_G when you first make the variable. music = false -- afterwards you don't need the \_G

I recommend making it in main.lua because then it exists for all of your lua files everywhere from the beginning. You can declare from other files but you could run into timing issues if, say, you ‘require’ in a lua file that needs the global, before the global is created. (Since it’s a global you can edit or delete it from anywhere!)

Basically, there are three major variable layers:

local music = true -- local to where you are typing music = true -- a "regular" global that generally only "global" within that lua file \_G.music = true -- a "super" global that is seen everywhere.

Globals and superglobals kind of collide in some ways so I really just recommend using _G when possible.

[import]uid: 41884 topic_id: 23693 reply_id: 106069[/import]