Best way to make a "Level Selector" screen (SOLVED)

I need create buttons to access to level 1 or level 2 or level 3…level x, each button need have a text to indicate the level and need have a sprite to show number of stars (0, 1, 2 or 3).

What is the best method? create gui element with nodes or create gameobjects with sprite and text?
can you explain the best method please?

Maxi.

You want to use gui nodes. Gui nodes have many features that make them better for making buttons than regular game objects. They’re rendered on top of everything else and unaffected by the camera, they can be anchored to different sides of the screen, they can automatically stretch to fit different window sizes, etc.

You can use gui.pick_node() to test if a node is underneath a position, which lets you easily check if a button is under your cursor when you click, or make buttons that change on hover. You can check out the button example for a very simple button.

A simple way to make a bunch of buttons is to make a table of the button node names and every time you get mouse input, do gui.pick_node() on each element in the table to see if your mouse is over a button. For click functions you can use the same table to map a function to each node name.

1 Like

Excellent suggestion by @ross.grams! This really shows some of the flexibility and power of Lua’s table type.

1 Like

thanks, your help was great, I will share my code:

function init(self)
	msg.post(".","acquire_input_focus")
	
	self.buttons = {}
	
	--Start buttons position
	local startX = 1
	local startY = 1
	--Space between buttons
	local xSpace = 10
	local ySpace = 10
	--Number rows and colums
	local rows = 2
	local columns = 3
	--Tot level buttons
	local nButtons = rows * columns
	--Save every button id in a table
	for i=1,nButtons do
		table.insert(self.buttons, "btnNivel" .. i - 1)
	end
	--Get the button size
	local button_size = gui.get_size(gui.get_node("btnNivel0"))
	--Get the total width to center buttons x-axis
	local tot_width = button_size.x * columns + xSpace * columns
	local screen_width = tonumber(sys.get_config("display.width"))
	--Get the total height to center buttons y-axis
	local tot_height = button_size.y * rows + ySpace * rows
	local screen_height = tonumber(sys.get_config("display.height"))
	--Calculate the start position for buttons
	startX = screen_width / 2 - (tot_width / 2) - button_size.x / 2 - xSpace / 2
	startY = screen_height / 2 - (tot_height / 2) - button_size.y / 2 - ySpace / 2
	--Set the correct position
	local totButtons = 1
	while totButtons < nButtons do
		for fil=1,rows do
			for col=1,columns do
				local button = gui.get_node(self.buttons[totButtons]) 
				local posX = startX + (col) * button_size.x + xSpace * col
				local posY = startY + (fil) * button_size.y + ySpace * fil
				gui.set_position(button, vmath.vector3(posX, posY ,0))
				totButtons = totButtons + 1
			end
		end
	end
end

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

function on_input(self, action_id, action)
	if action_id == hash("click") and action.pressed then 
        for i=1,#self.buttons do
        	local button = gui.get_node(self.buttons[i]) 
			if gui.pick_node(button, action.x, action.y) then 
				print("click button")
				break
			end
		end
    end
end

you need have 6 nodes with name “btnNivel0”, “btnNivel1”…“btnNivel6” if you need add more levels, add more nodes “btnNivel7”…“btnNivelXXX”

I accept suggestions :slight_smile:

PS: I will try to make one node and clone it with code and set_id “btnNivel0”…“btnNivelXXX”

2 Likes

how can we do “toy blast” or “blossom blast” style level selector . are these maked using tile map?

Hi
I’m one of the responsible for the Blossom Blast level selector. The maps are made up of collections of 3 islands and are mixed sprites, spine, 3d meshes(quads) for all the moving effects.
The level buttons themselves are gameobjects on top of that that have their own sprite and script (script contains a level_nr property and functionality to dispatch a message to the “level start screen”.
Of course this was only one way to go and the above solutions storing all buttons in a table works just as good.

Nothing in the Blossom Blast map scenes are using tilemaps (even though we were quite interested in creating all the maps with a isometric tileengine from start) but you sure could do one much easier (and less content heavy) with a tile map.

1 Like

thanks for your interest.
You probably do not upload all the sprites and other game objects(meshes,spine etc.) in init func or etc. You upload them when the user scrolls up (or down). am i right?

Yes it’s correct. We actually recreated that map a few times so I’m ot sure how the end result is working right now but I think we have 3 collections loaded at the same (as one collection is bigger than the whole screen). They are being async loaded and unloaded as the user is scrolling.
This approach still gave a lot of headache as the actually content size grew quite big so we had to fiddle a lot with different compression techniques to be able to assure a future growth of the game (new worlds being added all the time). But I guess that is a whole other discussion.

2 Likes

I wanted to try and do something similar myself so I put together a new example that shows how to load and unload collections, each representing a segment of the map. The segments contain level markers that can be clicked to launch a dummy game.

Code: https://github.com/britzl/publicexamples/tree/master/examples/level_selector
Try it: http://britzl.github.io/publicexamples/level_selector/index.html

5 Likes