Using a string to call another file's function

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
geleiademocoto
Prole
Posts: 11
Joined: Sat Apr 26, 2014 11:25 pm

Using a string to call another file's function

Post by geleiademocoto »

Hey all,
I looked for other questions similar to this one by searching "call function from another file", but I didn't find any that had this particular problem. It's a Lua problem. Here's the thing:

I have a series of rooms that I'm storing in a table. Inside game.lua, I create the table containing strings with the names of every room (which are also the names of the lua files for each room). I also create a variable called current_room to store the particular string with the name of the room that's supposed to be loaded. Initially, that's "room_1", which is rooms[1].

Now I want to call room_1.load() right here in game.load(). I know that it works if I write room_1.load(), but later on I may want current_room to be another room. So I want to basically do current_room.load(). I can't, because it's a string, right? So I looked around and found a few functions like loadstring() and assert(loadstring()). They didn't work, though. How do I do this?

Here's some code for the tl;dr folk:

Code: Select all

  --this code is inside game.load(). there is a file called room_1.lua and it contains the function room_1.load()
  rooms = {"room_1", "room_2"}
  current_room = rooms[1]

  -- Load the current room
  assert(loadstring(current_room)).load()
Thanks!

EDIT: I think I found out what wasn't working. I created a variable

Code: Select all

load_current_room = current_room..".load()" 
and then called

Code: Select all

assert(loadstring(load_current_room))
seems to have worked! Is this the best way to do this?

EDIT 2: Nope, didn't work. LOVE stopped accusing an error, but the code I put in room_1.load() doesn't get executed. Back to square one.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Using a string to call another file's function

Post by Robin »

So what's wrong with:

Code: Select all

rooms = {room_1, room_2}
current_room = rooms[1]
current_room.load()
?

No loadstring needed.
Help us help you: attach a .love.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Using a string to call another file's function

Post by micha »

If you have the name as a string, you can also a access global variable like that:

Code: Select all

_G[name]
In your case this should work:

Code: Select all

_G.[current_room].load()
_G is the table of all global variables.

However, I think Robin's solution is better.
geleiademocoto
Prole
Posts: 11
Joined: Sat Apr 26, 2014 11:25 pm

Re: Using a string to call another file's function

Post by geleiademocoto »

So what's wrong with:
CODE: SELECT ALL
rooms = {room_1, room_2}
current_room = rooms[1]
current_room.load()

?

No loadstring needed.
I get the blue screen with this error:
game.lua:21:attempt to call field 'load'(a nil value)
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Using a string to call another file's function

Post by Robin »

It's hard to tell without a .love, but it looks like you don't have access to the rooms there. Are they required? And how?
Help us help you: attach a .love.
geleiademocoto
Prole
Posts: 11
Joined: Sat Apr 26, 2014 11:25 pm

Re: Using a string to call another file's function

Post by geleiademocoto »

EDIT: I forgot to actually attach it the file. Sorry, fixed now.

It's hard to tell without a .love, but it looks like you don't have access to the rooms there. Are they required? And how?
Er, I'm a little embarassed to attach this because of how messy it looks, both the code and the game itself. Actually the game doesn't even have actual graphics, I'm just using random pics to be able to test the stuff. But I suppose you'll just be looking at the code, so it doesn't matter.

I'm attaching the .love, and for those who don't feel like DLing anytihing, here's just game.lua. As you can see, I am requiring room_1. My requirement of player.lua seems to be working fine, though.

Code: Select all

game = {}

require('room_1')
require('player')

function game.load()
  game.clock = 0

  -- Player init
  player.load()


  --Init rooms
  rooms = {"room_1", "room_2"}
  current_room = rooms[1]
  load_current_room = current_room..".load()"
  --update_current_room = current_room..".update(dt)"

  -- Load the current room
  _G[current_room].load()
end



function game.draw()
  -- Call the room's draw function
  if current_room == rooms[1] then
    room_1.draw()
  end
  if current_room == rooms[2] then
    room_2.draw()
  end

  -- Draw player
  player.draw()
end

function game.update(dt)
  game.clock = game.clock + dt

  -- Update player
  player.update(dt)

  -- Update the rooms
  if current_room == rooms[1] then
    room_1.update(dt)
  end

end

function game.keypressed(key)
  -- Call the room's keypressed function
  if current_room == rooms[1] then
    room_1.keypressed(dt)
  end
  if current_room == rooms[2] then
    room_2.keypressed(dt)
  end

  -- Restart game
  if key == "q" then
    love.load()
  end

end

function game.keyreleased(key)
  -- Call the room's keyreleased function
  if current_room == rooms[1] then
    room_1.keyreleased(dt)
  end
  if current_room == rooms[2] then
    room_2.keyreleased(dt)
  end
end
Attachments
source.love
(625.63 KiB) Downloaded 97 times
Last edited by geleiademocoto on Sat May 17, 2014 10:55 pm, edited 1 time in total.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Using a string to call another file's function

Post by Robin »

It looks like something went wrong, because there's no .love here, and I particularly need to see the contents of room_1.lua.
Help us help you: attach a .love.
geleiademocoto
Prole
Posts: 11
Joined: Sat Apr 26, 2014 11:25 pm

Re: Using a string to call another file's function

Post by geleiademocoto »

Now that I've read your reply, I'm not sure how useful my .love file is going to be. I ended up deleting everything that was on room_1.lua except for the drawing of the background. The content of player.lua used to be inside of room_1, so the content of player.load() was what was in room_1.load(). So I'm afraid it won't be very useful, sorry.
User avatar
ejmr
Party member
Posts: 302
Joined: Fri Jun 01, 2012 7:45 am
Location: South Carolina, U.S.A.
Contact:

Re: Using a string to call another file's function

Post by ejmr »

If you use Robin’s suggestion, that is…

Code: Select all

function game.load()
  game.clock = 0
  player.load()

  -- Use the tables created as a result of require("room_1")
  -- instead of using their names.
  rooms = {room_1, room_2}
  current_room = rooms[1]
  current_room.load()
end
…then you can simplify a lot of the functions in game.lua, e.g.:

Code: Select all

function game.draw()
  -- Call the room's draw function
  if current_room == rooms[1] then
    room_1.draw()
  end
  if current_room == rooms[2] then
    room_2.draw()
  end

  -- Draw player
  player.draw()
end

-- If current_room equals the actual room_1 or room_2 tables then the
-- if-statements are not necessary and the function can be like this:

function game.draw()
    current_room.draw()
    player.draw()
end
ejmr :: Programming and Game-Dev Blog, GitHub
南無妙法蓮華經
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Using a string to call another file's function

Post by Robin »

geleiademocoto wrote:Now that I've read your reply, I'm not sure how useful my .love file is going to be. [...] So I'm afraid it won't be very useful, sorry.
You underestimate how much information we can glean from a .love. Most non-trivial non-general questions here only get resolved once the person seeking help uploads a .love.

If you upload the .love, I can see the file structure, I can see whether room_1.lua creates a global called room_1, if it returns anything, if the current_room is ever changed in another module, etc. The answers to those questions mean I know what other questions to ask, and so on, until I get to the answer. If I have a .love of your game, I can read the answers to all my questions in seconds, and get back to you with an answer within minutes. Now, we have to play a game where I ask you things like "what does file_a look like?" or "change a into b here, what is the result?" which can easily go on for days.

tl;dr: please upload a .love, always, even if you don't think it'll help.
Help us help you: attach a .love.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 3 guests