Random Functions

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

I have 4 Player Functions

spawn_Player1()
spawn_Player2()
spawn_Player3()
spawn_Player4()

and 4 Enemy functions

spawn_Enemy1()
spawn_Enemy2()
spawn_Enemy3()
spawn_Enemy4()

this is my ready function

func _ready() -> void:
	$ScoreCount.text = str(Globals.Score) 
	set_process(true) 
	spawn_Player1(1):
	for i in range(4 + Globals.Score): 
		spawn_Enemy1()

If you click on the Player then the Main Scene resets and the Score stays.
And i want it that everytime the Main Scene resets that Player and Enemy is changed.
like if spawn_Player1 is loaded then spawn_Enemy1 and dont’t load spawn_Player2, spawn_Player3, spawn_Player4, spawn_Enemy2, spawn_Enemy3, spawn_Enemy4.

:slight_smile:

Can you show the contents of those spawn_Player* and spawn_Enemy* functions? I’d guess those functions can be combined into something much simpler, which in turn, would make it easier to randomly spawn a single player and enemy type (as you asked about above).

jgodfrey | 2020-11-15 15:59

onready var player_container1 = get_node("player_container1")
onready var Player1 = preload("res://Player/Player1.tscn")

var Enemy1 = [
preload("res://Enemy/Enemy2.tscn"),
preload("res://Enemy/Enemy3.tscn"),
preload("res://Enemy/Enemy4.tscn")
]

func spawn_Player1(num):
	for i1 in range(num):
		var p1 = player1.instance()
		p1.connect("player1_pressed", self, "_on_player1_pressed") #emited-signal
		player_container1.add_child(w1)

	
func _on_player1_pressed():
	if Globals.timeLeft > 0:
		Globals.timeLeft += 5
		if Globals.timeLeft > Globals.maxTime:
			Globals.timeLeft = Globals.maxTime
	Globals.Score += 1
	get_tree().change_scene("res://Game.tscn")
	
func spawn_Enemy1():
	var rand1 = floor(rand_range(0, Enemy1.size()))
	var piece1 = Enemy1[rand1].instance()
	add_child(piece1)

Rayu | 2020-11-15 17:26

:bust_in_silhouette: Reply From: AndyCampbell

As jgodfrey says, it would probably be best to combine your functions so you can call a single function with a varying parameter to get the effect you want.

However, if you really want to select from a hard-baked list of functions, you can use the call method which takes a string name

extends Node2D
    
const funcs = ["spawn_Player1", "spawn_Player2", "spawn_Player3", "spawn_Player4"]

func spawn_Player1():
	print("This is spawn_Player1")

func spawn_Player2():
	print("This is spawn_Player2")

func spawn_Player3():
	print("This is spawn_Player3")

func spawn_Player4():
	print("This is spawn_Player4")

func _ready():
	for f in funcs:
		call(f)

You would apply your logic to select from the array in _ready

Or, since the variable name is just a string, you could create the correct string on the fly in the loop in your example (but this is getting really ugly, and very easy to break)

var f = "spawn_Player" + str(i)
call(f)
:bust_in_silhouette: Reply From: jgodfrey

From your response in another question, it sounds like you’re still awaiting input here. With that in mind…

As I suggested in some of the above comments (and AndyCampbell mentioned in his answer) some of your code really should be combined and refactored to make your request simpler to satisfy. However, since refactoring your code isn’t something I have the bandwidth for ATM, here’s a simple (though not ideal) solution that works with your existing code base…

func _ready() -> void:
    $ScoreCount.text = str(Globals.Score) 
    set_process(true) 
    set actor_id(randi() % 4 + 1)
    if actor_id == 1:
        spawnPlayer1()
        spawnEnemy1()
    elif actor_id == 2:
        spawnPlayer2():
        spawnEnemy2():
    elif actor_id == 3:
        spawnPlayer3():
        spawnEnemy3():
    else:
        spawnPlayer4():
        spawnEnemy4():

If it were me, I’d probably refactor some of the code to work with functions shaped more like the following:

func spawnEnemy(enemy_id, enemy_count)

func spawnPlayer(player_id)
func _ready() -> void:
    $ScoreCount.text = str(Globals.Score) 
    set_process(true) 
    set actor_id(randi() % 4 + 1)   <-------------
    if actor_id == 1:                            |            
        spawnPlayer1()                           |
        spawnEnemy1()                            |
    elif actor_id == 2:                          |
        spawnPlayer2():                          |
        spawnEnemy2():                           |
    elif actor_id == 3:                          |
        spawnPlayer3():                          |
        spawnEnemy3():                           |
    else:                                        |
        spawnPlayer4():                          |
        spawnEnemy4():                           |

Expected end of statement after expression, got Identifier instead.

What does that mean?
And did you forget actor_id == 4 ?
is it a problem if i add it in ?

Rayu | 2020-11-17 06:00

Guh… Sorry, that syntax is for the wrong language (and, broken even in that case)… :frowning:

Try this:

var actor_id = randi() % 4 + 1

And, since that randi() call will only generate values between 1-4, the final else statement will process the 4 value.

jgodfrey | 2020-11-17 14:04