Is it possible to have solarus functions in a module?

Started by zutokaza, September 29, 2016, 03:56:37 AM

Previous topic - Next topic
September 29, 2016, 03:56:37 AM Last Edit: September 29, 2016, 04:00:24 AM by zutokaza
I want to make my code shorter because I basically have 3 long scripts in one lua file and it is a bit crazy.

For example,

Code ( lua) Select


--mymodule.lua
local mymodule = {}
--variables

function mymodule.foo()

--solarus image function
blah blah
end

--solarus on_key_pressed function
blah blah
end

end

--map.lua

local mymodule = require "mymodule" -- Will it be out of scope if local?

--solarus on_key_pressed function
mymodule.foo()
end


return mymodule
Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

September 29, 2016, 06:38:29 AM #1 Last Edit: September 29, 2016, 06:47:46 AM by llamazing
Since your module has an on_key_pressed() function and image function (I'm assuming you mean on_draw()?), you probably want to use a menu. It works as just a simple table too if you don't need a menu.

Something like the following:
Code (lua) Select

--mymodule.lua
local mymodule = {}
--variables

--called on sol.menu.start()
function mymodule:on_started() --only needed if menu
end

--called on sol.menu.stop()
function mymodule:on_finished() --only needed if menu
end

function mymodule:on_draw(dst_surface)
--blah blah
end

function mymodule:on_key_pressed(key, modifiers)
--blah blah
end

function mymodule.myfunction()
--blah blah
end

return mymodule


--map.lua
local mymodule = require "mymodule" --mymodule is a table

function map:on_started()
sol.menu.start(self, mymodule) --only needed if menu
end

function map:on_finished()
sol.menu.stop(mymodule) --only needed if menu
end

mymodule.myfunction() --normal function call


If you want the menu to be run for all maps you can use a metatable:
Code (lua) Select

--you could put this code in mymodule.lua
local map_meta = sol.main.get_metatable"map"
function map_meta:on_started()
sol.menu.start(self, mymodule)
end

function map_meta:on_finished()
sol.menu.stop(mymodule)
end


If using the metatable method, having map:on_started() in an individual map overrides the metatable function.

Also see Christopho's require() tutorial:
https://www.youtube.com/watch?v=CUcfPYMlVs8


September 29, 2016, 02:45:10 PM #3 Last Edit: September 29, 2016, 02:49:36 PM by MetalZelda
It depends on how and where and in which context you want to use your menu

Let's assume that your script and menu will belong to map and you start it from map:on_started()
llamazing example is correct, but if you want to make something special in your map script, let's say something like

function map:on_started(destination)
  blablabla coding stuff
end

the menu will not start because the function is overwritten by your map script (correct me if I'm wrong)

The other solution will be to add this module and start it in game:on_map_changed(map), it does the same thing, you don't even need to stop it as a menu with "map" as context is automatically stopped when the map it belongs no longer exist

Another solution is to use the function defined in the multi_events.lua script that Christopho made a few weeks ago:
https://github.com/christopho/solarus-alttp-pack/blob/dev/data/scripts/multi_events.lua
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 29, 2016, 03:27:14 PM #5 Last Edit: September 29, 2016, 03:34:13 PM by llamazing
Quote from: Diarandor on September 29, 2016, 02:57:58 PM
Another solution is to use the function defined in the multi_events.lua script that Christopho made a few weeks ago:
https://github.com/christopho/solarus-alttp-pack/blob/dev/data/scripts/multi_events.lua
How does the multi_events.lua script work in regard to map:on_started()? Correct me if I'm wrong, but you wouldn't want to do the following in a map script...
Code (lua) Select

local map = ...

map:register_event("on_started", function()
--blah blah
end)


...because the map script gets executed every time the player enters the map, each time registering a new on_started function to the multi_events, and the on_started events registered from all the previous times the player entered the map would be undesirable.

September 29, 2016, 03:50:25 PM #6 Last Edit: September 29, 2016, 03:52:05 PM by Diarandor
When you leave a map, the engine destroys it (with all its code). So when you come back to the map, the code you have added before (with the register_event function) no longer exists and has to be added again. Only the code of the map metatable is kept when you leave a map.

The point is that you can avoid "overwriting" the event of your map script if you use that function, because the multi_events script just adds the new code at the end of the existing code of your event, without "overwriting" it.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

The "map" variable is a different one every time the players enters the map. It is true that the map script gets executed every time the player enters the map, but since the map variable is a new one, it will only have one on_started event. And the old map and its event will be garbage collected eventually (unless you keep references to them somewhere).

To sum up, if your project has the multi_events.lua script, then you have the choice between two approaches for all events:
Code (lua) Select

local map = ...

-- The traditional way still works:
function map:on_started()
  -- blah blah
end



Code (lua) Select

local map = ...

require("multi_events")

-- This approach allows to register several functions to the same event:
map:register_event("on_started", function()
        -- blah blah
end)


You can use the multi_events approach when you have the problem of several scripts that want to define the same event. For example, let's say that the dialog box script and the HUD scripts both want to do something in game:on_started().