Pausing?

Started by Zefk, August 31, 2016, 03:21:18 AM

Previous topic - Next topic
Hello,

I have a question. Does the pausing functions and script need to be in the game manager to work? Basically, I want to press the default pause button "D" and have dot_5 show.

Code ( lua) Select
function game:on_paused()
      dot_5 = true   
end
 
function game:on_unpaused()
      dot_5 = false 
end

Hi! Not necessarily, you can define it in other script if you want. But since that function is defined for the game entity, the recommended place to put that code is in the game manager just after the creation of your game entity (with other similar functions). An alternative is to define it in the game metatable, which needs to be done only once, because it will be immediately defined for all game instances you create (so the main script, or other script which is loaded only once, would be a good place in this case).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

August 31, 2016, 04:52:36 AM #2 Last Edit: August 31, 2016, 04:55:08 AM by Zefk
Moving my script to the game manger seems to work. I got an error for the map script when trying the pause functions there.

2150] Error: In maps/first_map: [string "maps/first_map.lua"]:47: attempt to index global 'game' (a nil value)

Edit:
I will probably have the game manager require scripts to keep it clean.

The error says that your variable "game" is not defined. Probably you forgot to define it in the map script with:
Code (Lua) Select
local game = map:get_game()
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

You are correct. I copied over it when transferring a script to my map script. I copied over "local map = ..." as well.

Code ( lua) Select
local map = ...
local game = map:get_game()


Is it possible to call a script from the scripts directory related to get_game()? For instance,

game_manager:
Code ( lua) Select
require ("scripts/volume_control")

It runs the script volume_control, but not the pause functions.

Code ( lua) Select
function game:on_paused()
      dot_5 = true   
end
 
function game:on_unpaused()
      dot_5 = false 
end

-I do not understand what you mean by "a script related to get_game()". Note that "get_game()" is a function defined for some entities that returns the game entity in which they exist.
-Also, I do not know in which script are your pause functions defined; are they in the volume_control script or in the game manager script?

Could you explain all of this a bit better?
Or even better, put a copy of these scripts: the game manager and the script where your pause functions are defined. That will be faster.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 01, 2016, 03:50:44 AM #6 Last Edit: September 03, 2016, 10:28:28 AM by Zefk
Here is the script. It is a volume control menu for the Solarus book project. It covers some basics. I will have to clean up the comments a bit later. It works perfectly, but I want to call is from scripts/volume_control.lua. The pause functions do not work when calling scripts/volume_control. It works in the game_manager for global purposes, so it will not have to be put in every game map.

Script completed: Here
volume_control.lua
Code ( lua) Select
--[[
Main script Author: Zane Kukta (Zefk)

Directory Script Author: Diarandor

Solarus ARPG Engine creator: Christopho

Script Completion Date: 8 - 31 - 16 (August, 31st - Happy birthday dad.)

License: Free under GPLv3 by default. It uses Solarus functions and Solarus is under GPLv3. Credit the three (3) people involved in script and link to their websites.

Websites:
http://zelzec-entertainment.weebly.com/
http://www.solarus-games.org/
https://github.com/Diarandor

Forum Script Link:
http://forum.solarus-games.org/index.php/topic,737.msg3880.html#msg3880

Bugs fixed:
-Browse sound active with the up and down keys when walking.
-Dot does not vanishing when closing the menu.
-Dot not being on the percentage when opening the menu again.
--]]

--Makes it so game related functions work. For instance, the pause function at the bottom.
local game = ...


--set boolean(true or false) to false
local background = false
local dot_1 = false
local dot_2 = false
local dot_3 = false
local dot_4 = false
local dot_5 = false
local browse_sound = false

--Have browse start a volume 100% (5)
--0% = 1
--25% = 2
--50% = 3
--75% = 4
--100% = 5
local  browse = 5

--set boolean to image, so you can show it with true and make it vanish with false. Add "_img" after it because it is an image. Put it in the sprite folder.
local background_img = sol.surface.create("Background.png")
local dot_1_img = sol.surface.create("1_orange_dot.png")
local dot_2_img = sol.surface.create("2_orange_dot.png")
local dot_3_img = sol.surface.create("3_orange_dot.png")
local dot_4_img = sol.surface.create("4_orange_dot.png")
local dot_5_img = sol.surface.create("5_orange_dot.png")

--The draw function. You need it to draw on the screen in Solarus.
function sol.main:on_draw(screen)

--Basic conditional statements. If you walk, then you burn calories.
  if background then
    --Draw image on screen and coordinates
    --background_img:draw(screen, 20, 10)
    background_img:draw(screen)
  end

  if dot_1 then
    dot_1_img:draw(screen)
  end

  if dot_2 then
    dot_2_img:draw(screen)
  end

  if dot_3 then
    dot_3_img:draw(screen)
  end

  if dot_4 then
    dot_4_img:draw(screen)
  end

  if dot_5 then
    dot_5_img:draw(screen)
  end
end

--Function for allowing keys to be pressed for scripts
function sol.main:on_key_pressed(key)

--Browse down or turn the volume down
  if key == "down" and browse_sound == true
  then
       sol.audio.play_sound("bomb")
       if browse >= 1
       then
            browse = browse - 1
       end
  end

--Browse up or turn the volume up
if key == "up" and browse_sound == true
  then
       sol.audio.play_sound("bomb")
       if browse <= 5
       then
            browse = browse + 1
       end
  end

--Makes the orange volume dot vanish and appear when changing the volume.
if background == true
then
     sol.audio.play_sound("cursor")
     if browse == 1
     then
          dot_1 = true
          dot_2 = false
          sol.audio.set_sound_volume(0)
          sol.audio.set_music_volume(0)
     end
     if browse == 2
     then
          dot_2 = true
          dot_1 = false
          dot_3 = false
          sol.audio.set_sound_volume(25)
          sol.audio.set_music_volume(25)
     end
     if browse == 3
     then
          dot_3 = true
          dot_2 = false
          dot_4 = false
          sol.audio.set_sound_volume(50)
          sol.audio.set_music_volume(50)
     end
     if browse == 4
     then
          dot_4 = true
          dot_3 = false
          dot_5 = false
          sol.audio.set_sound_volume(75)
          sol.audio.set_music_volume(75)
     end
     if browse == 5
     then
          dot_5 = true
          dot_4 = false
          sol.audio.set_sound_volume(100)
          sol.audio.set_music_volume(100)
     end
  end
end

--Game functions that allow the game to be paused, when the default pause button "D" is pressed
function game:on_paused()
      sol.audio.play_sound("cat")
--Activates the background and menu script.
      background = true
--Turns on the browsing sound
      browse_sound = true
--Checks for the dot location when launching the menu. You want the dot to show on the percentage it is at. Is it on 100%?


      if browse == 1
     then
          dot_1 = true
          dot_2 = false
     end
     if browse == 2
     then
          dot_2 = true
          dot_1 = false
          dot_3 = false
     end
     if browse == 3
     then
          dot_3 = true
          dot_2 = false
          dot_4 = false
     end
     if browse == 4
     then
          dot_4 = true
          dot_3 = false
          dot_5 = false
     end
     if browse == 5
     then
          dot_5 = true
          dot_4 = false
     end
end
--The unpause function. Press "D" again to unpause the game. The menu is turned to false and that turns off the background menu and all the dots are turned off because no one likes orange dots left on the screen.
function game:on_unpaused()
      background = false 
      dot_1 = false
      dot_2 = false
      dot_3 = false
      dot_4 = false
      dot_5 = false
--shuts off the browsing sound when walking
      browse_sound = false

end

Hi, it is very strange that your script works, because your on_paused/unpaused functions are defined in a game entity that seems not defined, which should produce an error unless you have some global variable "game". (It is not usually a good idea to use global variables.) You should initialize the game variable in the script giving it from some other script, maybe with the loading syntax:
Code (Lua) Select
sol.main.load_file("scripts/volume_control.lua")(game)
and then start your volume_control script with local game = ... so that the game variable is stored. (There is another way to get the game variable to be defined in other script: using some function that initializes it, but for this purpose you need the script to return some table with the initializer function.)

QuoteThe pause functions do not work when calling scripts/volume_control.
-Are you sure that you don't have defined these functions twice? (Maybe in the game maganer you have other definition.) If so, the second definition would override the first one. Check farefully your other scripts to make sure that this is not happening.
-Do you get some error?
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Worked perfectly. Thank you a bunch for the help! I will make sure to credit you for the scripting help.  :D

;D
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

sol.main.load_file() is not recommended in new code, require() is better and faster.

Quote from: Christopho on September 01, 2016, 08:37:28 AM
sol.main.load_file() is not recommended in new code, require() is better and faster.

I noticed that in the documentation. Does sol.main.load_file() do things that require() cannot? I know require() does not parse the file again every time you call it and that makes it faster, but sol.main.load_file() loads this script instantly. Does it require more ram or memory to use sol.main.load_file()? I will be noting both in the book project.

Tests:
I get an error when using require()
2140] Error: In on_finished: [string "scripts/volume_control.lua"]:125: attempt to index local 'game' (a string value)


Code ( lua) Select
require("scripts/volume_control.lua")(game)

Same for:
Code ( lua) Select
require("scripts/volume_control.lua")

Note: I tried it without the .lua extension as well.

September 01, 2016, 10:36:52 AM #12 Last Edit: September 01, 2016, 10:50:24 AM by Diarandor
Christopho has explained me now how to use it, I think it's like this (I have not checked it yet):
Code (Lua) Select
local foo = require("script"); foo:f(game)
I have to clean my code with this. It seems that load_file is important for other purposes, but as a non-programmer that is out of my knowledge... and for our purposes we should avoid it.

EDIT: I updated the function, I had posted something wrong. But I guess you will need an initializer function.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

With:
Code ( lua) Select
  local foo = require("scripts/volume_control"); foo:f(game)


I get:
2140] Error: In on_finished: [string "scripts/volume_control.lua"]:125: attempt to index local 'game' (a string value)

September 01, 2016, 11:16:04 AM #14 Last Edit: September 01, 2016, 11:18:35 AM by Christopho
TL;DR: use require(), sol.main.load_file() is too low-level for most purposes.

The loadfile() vs require() choice is a pure Lua matter, there is nothing special in Solarus. (The sol.main.load_file() of Solarus is completely identical to loadfile() except that it loads relative to the data directory of archive.)

Here is how to properly call some code from another script, for example with a game parameter:

The other script (let's call it my_feature.lua):
Code (lua) Select

local my_feature = {}

function my_feature:my_function(game)
  -- Do stuff
end

return my_feature


The calling code (wherever you have your game object, typically in the game_manager script):
Code (lua) Select

local my_feature = require("my_feature")

.........
-- Later:
local game = ............
.........
my_feature:my_function(game)


sol.main.load_file() / loadfile() is a very low-level function that opens a script, parses it and returns it as a function value. require() is much more powerful. require() is the recommended way because it does not load again and does not parses again the script, it only does that the first time. Subsequent calls to require() just return whatever the script returned the first time. In this example, the my_feature table.

It is the convention in Lua to return a table from required scripts. Lua programmers are used to this. But if you prefer, you can directly return a function instead of a table containing functions. This way you will have something similar to sol.main.load_file(). It would work like this:

The required script:
Code (lua) Select

local function my_function(game)
  -- Do stuff
end

return my_function

Or even
Code (lua) Select

return function(game)
  -- Do stuff
end


The calling code:
Code (lua) Select

local my_function = require("my_function")

.........
-- Later:
local game = ............
.........
my_function(game)

Pros:
- The code is shorter.
Cons:
- It is less conventional to return a function from required scripts.
- Returning a table instead allows to put several functions in the table.

You can read this for more information about require() vs loadfile(): http://stackoverflow.com/questions/34235540/whats-the-difference-between-loadfile-require-and-import