[SOLVED] How to create a queue of spawning game objects after one another and stopping based on a countdown timer

No no, back up. Read the error message more carefully.

attempt to index

Attempting to index something means you’re trying to use it as a table and access a value inside it using a key.

attempt to index global

This means that the error is happening when your script attempts to access a global variable.

attempt to index global 'self'

The global variable that you’re trying to use is named: ‘self’.

'self' (a nil value)

The value of the global variable that you were trying to use is nil.
Since you were trying to get a value from the variable using a key, the variable was expected to be a table. Instead of a table, it was nil, hence the error.

[Edit]: Looking for a global variable means that no local variable was found with that name, in the current scope.

1 Like

I see. Oh I see, I’m reading your previous post on Explanation of the “self” argument for dummies and I think I’m somewhat understanding it. I originally used self to make it so the variable be different for every instance so I think I’m doing it right.So line 7 is self.book_code = "". So I’m debugging it again, reaching to the original error, clicking the triangle to forward it and jumping to here.

image

So if self is a table, and I’m indexing a global self from my book.script, then does that mean I was trying to access the self table inside of insert-book-code.script or vice versa?
Sorry, I’m just having a hard time grasping this.

I guess another question would be, what is the key in this case.

Wait, so I’m using the factory to create an instance of a game object, and I’m using self to make sure each variable of each instance of it is unique and not shared, but then inside of that game object, I have a script that’s also attempting to use self to make sure each instance of it has unique variable values. :thinking:

Wait a minute, if I’m already making a new instance of book.go inside of insert-book-code.script, why would I need self.book_code inside of book.script.

1 Like

Line 7 from the error is:

self.book_code = ""

So the key in this case is: "book_code", since

self.book_code

is just shorthand for:

self["book_code"]

The one and only problem is: no local variable named ‘self’ exists in the context where you expected it to. Just take a look at these few lines:

function init(self)
	generate_book_appearance()
	generate_book_code()
end

local function generate_book_code()
	self.book_code = ""

Where’s self?

2 Likes

OK, I’ll stop being annoying and just explain it :stuck_out_tongue: : ‘self’ is always given as a function argument. In other words, a local variable inside a function. The problem is, you are not passing ‘self’ on to the “generate_book_code()” function, so ‘self’ doesn’t exist inside that function when it runs. You want to do this:

function init(self)
	generate_book_appearance(self)
	generate_book_code(self)
end

local function generate_book_code(self)
	self.book_code = ""
1 Like

HOLY CRAP, I FEEL DUMB. Also I was having dinner and that popped into my head, I was thinking about how I had arguments inside of insert-book-code.script and they all passed self. THAT MAKES SENSE NOW. :man_facepalming:

Wait though, would I even need to make the variables inside of book.script unique? Considering I’m using the factory to make a unique instance each time?

Thanks by the way for sticking it out with me.

Ok, I’m making progress though, managed to fix another error, it was the msg.post one, I was passing a string instead of a table and it didn’t like that, and I fixed it, still got a few errors to go though.


It’s spawning a book at least.

ERROR:GAMEOBJECT: Component '/instance0#random_book_code_label' could not be found when dispatching message 'set_text' sent from default:/instance0#random-book
ERROR:GAMEOBJECT: Instance '<unknown>' could not be found when dispatching message 'play_sound' sent from default:/minigame_go#insert-book-code
INFO:DLIB: SSDP: Started on address 10.0.0.78
ERROR:SCRIPT: ...games/inventory/insert-book-code/insert-book-code.script:25: Could not send message 'game_over' from 'default:/minigame_go#insert-book-code' to 'main:/main'.
stack traceback:
  [C]:-1: in function post
  ...games/inventory/insert-book-code/insert-book-code.script:25: in function <...games/inventory/insert-book-code/insert-book-code.script:24>

Ah ok, I’d probably have to pass in that instance for the url then.

local function generate_book_code(self)
	self.book_code = ""
	local charset = {} do
		-- Ký tự [0-9a-zA-Z] dưới dạng  mã ASCII: https://www.rapidtables.com/code/text/ascii-table.html
		for c = 48, 57  do table.insert(charset, string.char(c)) end
		for c = 65, 90  do table.insert(charset, string.char(c)) end
		for c = 97, 122 do table.insert(charset, string.char(c)) end
	end
	-- [0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}
	while (string.len(self.book_code) <= 19) do 
		if (#self.book_code % 5 == 0) then
			self.book_code = self.book_code .."-" 
		else
			self.book_code = self.book_code .. charset[math.random(1, #charset)] 
		end
	end
	-- Ok, this is the issue here. I already tried to pass self"#random_book_code_label" but that didn't work
	label.set_text("#random_book_code_label", self.book_code)
	msg.post("/computer#computer", "actual_book_code", {book_code = self.book_code})
end

Wait nope, fixed that issue too, turns out I got the wrong name for the label. :rofl: There’s still the play_sound issue, will try to figure that out, in fact I’m trying to find where it is. Got the sound to work. Gotta figure out how to make my spawned game object bigger, I’ll figure that out, I think you can specify scale with factory. Unless there’s a way to do that in the game object itself. Another one is to figure out how to check to see if your typed input matches the book code, hm. Oh yea, and trying to figure out how to return to the main collection and then loading the next minigame. We’ll get to that when we get to that.


1 Like

Alright, it sort of works, just one odd problem now, with the timer, after it’s done it’s giving me an error where it can’t find the main collection.

What is the code you are running in the timer?

// timer
timer.delay(1, false, function()
		msg.post("main:/main#main", "game_over")
	end)

// main
function on_message(self, message_id, message, sender)
	if message_id == hash("game_over") then
		pprint("Create nested function for loading and unloading minigames?")
	end
end

ERROR:SCRIPT: ...games/inventory/insert-book-code/insert-book-code.script:24: Could not send message 'game_over' from 'default:/minigame_go#insert-book-code' to 'main:/main#main'.
stack traceback:

I wonder if it has to do with the directory.
image

No no no. The way you have arranged stuff in your Assets (the panel on the left) in terms of filenames and folder structure has nothing to do with the url used in msg.post. It is the structure in the Outline that matter, and the ids you have assigned there.

2 Likes


I see, I think I might know the issue, I’d have to load the main collection before sending message posts to it, and probably unload the current collection I’m in. Thank Britzl. Or I start from main.collection, then load in the current collection I’m on then unload the latter when the timer goes down, i.e. unload current collection then it should call inside of main

if message_id == hash("proxy_unloaded") then
       pprint("Cycle through the minigames again.")
    end

Hate to revive a thread, solved one scenario but now have a similar scenario to this one. Basically I’m now trying to spawn a bunch of game objects that have a different sprite for each instance (basically they’re just alphabetical letters) and am using Factory and Properties as an example, however I don’t think I need to add functionality to the game object I’m spawning in its own script since it’s just being used in this specific collection. I would assume that me using self.letter would make each instance unique, so I don’t understand why it wouldn’t recognise the id, and since self.letter is an instance of the spawned game object, shouldn’t go.animate recognise that path? Thanks to anyone who responds.

local function random_position()
	return vmath.vector3(math.random(1, sys.get_config("display.width")),  math.random(1, sys.get_config("display.height")), 0)
end

local function spawn_letters(self)
	local charset = {} do
		-- Ký tự [0-9a-zA-Z] dưới dạng  mã ASCII: https://www.rapidtables.com/code/text/ascii-table.html
		for c = 97, 122 do table.insert(charset, string.char(c)) end
	end
	for i,v in ipairs(charset) do
		self.letter = factory.create("#alphabet_factory", random_position())
		sprite.play_flipbook(self.letter.."#alphabet_sprite","keyboard_"..v)
		go.animate(self.letter.."#alphabet_sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, self.color, go.EASING_INOUTCIRC, 2)
	end
end

function init(self)
	msg.post(".", "acquire_input_focus")
	spawn_letters(self)
	timer.delay(8, false, function()
		print("Failed.")
		msg.post("main:/main#main", "game_over", {score = 0})
	end)
end

function on_input(self, action_id, action)
end

function final(self)
	msg.post(".", "release_input_focus")
end

Errors below:

ERROR:SCRIPT: ...est-service/where-to-find-book/where_to_find_book.script:14: Could not find any instance with id '<unknown>'.
stack traceback:
  [C]:-1: in function animate
  ...est-service/where-to-find-book/where_to_find_book.script:14: in function spawn_letters
  ...est-service/where-to-find-book/where_to_find_book.script:20: in function <...est-service/where-to-find-book/where_to_find_book.script:18>

image

You can’t use string concatenation. Use:

msg.url(nil, self.letter, “alphabet_sprite”)

Thanks for replying britzl, but how would I determine what image the sprite should be set to?

Is this not what you are looking for as Britzl suggested?

local sprite_url = msg.url(nil, self.letter, “alphabet_sprite”)
sprite.play_flipbook(sprite_url,"keyboard_"..v)

Ah I see, yea I realise I made a typo on my variable name (and now I feel dumb). :expressionless: Thanks selimanac for replying.

I guess the problem is the animating part now.

ERROR:GAMEOBJECT: Properties can not be of type 'nil'.
ERROR:SCRIPT: ...est-service/where-to-find-book/where_to_find_book.script:14: only numerical values can be used as target values for animation
stack traceback:
  [C]:-1: in function animate
  ...est-service/where-to-find-book/where_to_find_book.script:14: in function spawn_letters
  ...est-service/where-to-find-book/where_to_find_book.script:20: in function <...est-service/where-to-find-book/where_to_find_book.script:18>
pprint(self.color)
1 Like

Ah I see, it’s a nil value, ok, I see now, I should’ve been animating the position property, not the color, that was my bad. It’s working now mostly. Tried bumping up the speed of the animation but it seems like they’re still not moving. Hm, shouldn’t it move though? I called random_position() twice. Just debugged it, yea random_position() works.

go.animate(self.letter, "position", go.PLAYBACK_LOOP_PINGPONG, random_position(), go.EASING_INOUTCIRC, math.random(1200, 2400))


Files are unfortunately too big: link to them. Again, if anyone’s willing to take a look I’d appreciate it, I understand if not, admittedly my organisation’s pretty bad.

Your URL works, random_position() works. So, what might be the problem?
Are you sure this duration is proper?
Did you try something like 1 or 2 for duration?
Are you sure the start position and end position is different or distance between them large enough for duration 1200-2400?

math.random(1200, 2400)
3 Likes

Thank you for pointing that out, no it wouldn’t actually make sense for it to be that big logically speaking. So I changed it to 1-10 instead, which is a lot better now, I still have to figure out how to make it not go offscreen, I wonder if it has to do with the fact I’m using rendercam so I’d have to translate from screen view to world view like with inputs. I think in the random_position method I’d have to tweak it so it converts from screen to world view.

I’m looking at the rendercam scripts and I don’t see a method like GetViewportSize(), I’ll see if I can look into it more. There’s a set_viewport() but I’m not sure if that’s what I’m looking for.

Also I just realised it’s theoretically possible to randomly generate a position and have a chance it be the same position twice, I’d probably have to make a method that checks to make sure that’s not the case and if it is, then rerandomise it.

If I do something like this,

local screen = vmath.vector3(action.x, action.y, 0)

wouldn’t it be grabbing the location of the cursor, i.e. action.x, action.y? That wouldn’t be the viewport size though.

Just going to use default camera since I’m not using orthogonal or perspective view.