character select

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Ati97

Hi guys,

Im working on my first little game, and i’m faceing a problem.
In my game you can control a character(kinematicbody2d) which can pick up boxes(rigidbody2d) and carry them.
I want to add more leves and characters to my game, i made another character but the only way i was able to make it selectable it’s that i made 2 scenes world1_character1 and world1_character2 so i have ‘‘2’’ worlds with one of the characters.

So my question is: is it possible to have just one scene with the world, and get the charaters in them?


:bust_in_silhouette: Reply From: njamster

Sure thing! Save each character as its own scene and then instance it from code once the level gets ready. It should look somewhat like this:

var player_character_path = "res://PlayerCharacter1.tscn"

func _ready():
    var player_character = load(player_character_path).instance()
    player_character.start_position = Vector2(100, 100)

Of course your start_position might differ and it’s possible that you don’t want to add the player as a direct child of the level, in which case you have to get the intended parent node first and then call add_child on that node instead.

Now all that’s left to do is asking the player to choose a character at some point in time and store that choice somewhere, most likely an AutoLoad. When the level is loaded, you would check that choice and set player_character_path accordingly.

Thank You for your answer

Can you help me with the player select aswell, how can i store the selection?

I imagine that i make a scene with buttons, one for each character then after the character selection it gets to a scene with the world selection with buttons aswell.
After that, it needs to combine the two selection somehow.

Ati97 | 2020-07-25 16:35

You would connect the button_pressed-signal of each Button to a callback that stores the choice in a variable that’s part of the AutoLoad, e.g.:

func _ready():
    for button in [$Button1, $Button2, $Button3]:
        button.connect("button_pressed", self, "_on_Button_pressed", [button])

func _on_Button_pressed(button : Button):
    Global.character_choice = $Button.text

Here I connect the signal for three different buttons named “Button1”, “Button2” and “Button3” and provide the callback with the Button-node as an extra-argument. Then I set the variable character_choice of the auto-loaded node called “Global” with the text of that button. Of course you don’t have to use the text here. As long as it allows you differentiate the selected choice from all other options it will be fine. :slight_smile:

Let me illustrate this by setting up the level selection with an integer instead:

func _ready():
    var level_id = 0
    for button in [$Button1, $Button2, $Button3]:
        level_id += 1
        button.connect("button_pressed", self, "_on_Button_pressed", [level_id])

func _on_Button_pressed(level_id : int):
    get_tree().change_scene("res://Levels/" + str(level_id))

Then each level would check Global.character_choice in _ready to spawn the correct character as shown already in my answer above:

var player_character_path = "res://PlayerCharacter1.tscn"

func _ready():
    var player_character = load("res://Characters/" + Global.character_choice).instance()
    player_character.start_position = Vector2(100, 100)

njamster | 2020-07-26 14:22

Thank You so much!!!

Even with your help, it took me like half a day to figure it out but i finally did it.

Thank you!

Ati97 | 2020-07-27 10:16

Hey njamster, can you share your final code?

Coihue | 2021-04-23 01:18