+2 votes

Hi all,

Have a look at this complete code. I want to select a random powerup to display. I have an array or powerup names, one is randomly chosen. Then, based on the random choice, the system needs to draw the sprite.

I look at all the if elif statements and wonder if there's not a more efficient method?

extends Node2D

onready var labeloutput = get_node("RichTextLabel")
var powerUpSprite

func _ready():
    spawnRandomPowerup()


func spawnRandomPowerup():

    #list of power ups
    var powerUpArray = ["speedUpBat","slowDownBat","speedUpOtherBat","slowDownOtherBat","speedUpBall","slowDownBall","makeBatLarger","makeBatSmaller","freezeBat","doublePoints","randomObstacle","powerBall"]

    #get like... totally random dude    
    randomize()

    #pick randomly from the list of power ups
    var theChosenOne = powerUpArray[randi()%powerUpArray.size()]

    #print all the available choices
    for choice in powerUpArray:
        labeloutput.add_text(choice)
        labeloutput.add_text("\n")

    #print the chosen one
    labeloutput.add_text("\n")
    labeloutput.add_text(theChosenOne)

    #render the chose powerup on screen
    renderPowerup(theChosenOne)


func renderPowerup(powerUp):

    powerUpSprite = Sprite.new()    #create a new sprite
    add_child(powerUpSprite)        #add it as a child 

    var powerUpImage                #the texture of the powerup will live here

    #I wonder, there must be a more efficient way to do this?
    if powerUp == "speedUpBat":
        powerUpImage = load("res://textures/speedUpBat.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "slowDownBat":
        powerUpImage = load("res://textures/slowDownBat.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "speedUpOtherBat":
        powerUpImage = load("res://textures/speedUpOtherBat.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "slowDownOtherBat":
        powerUpImage = load("res://textures/slowDownOtherBat.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "speedUpBall":
        powerUpImage = load("res://textures/speedUpBall.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "slowDownBall":
        powerUpImage = load("res://textures/slowDownBall.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "makeBatLarger":
        powerUpImage = load("res://textures/makeBatLarger.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "makeBatSmaller":
        powerUpImage = load("res://textures/makeBatSmaller.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "freezeBat":
        powerUpImage = load("res://textures/freezeBat.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "doublePoints":
        powerUpImage = load("res://textures/doublePoints.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "randomObstacle":
        powerUpImage = load("res://textures/randomObstacle.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))
    elif powerUp == "powerBall":
        powerUpImage = load("res://textures/powerBall.png")
        powerUpSprite.set_texture(powerUpImage)
        powerUpSprite.set_pos(Vector2(100,100))


func _on_Button_pressed():
    labeloutput.clear()
    powerUpSprite.hide()
    spawnRandomPowerup()
in Engine by (814 points)

if you keep the image file names the same as the powerUp names you could skip the if statement and do something like the following.

powerUpImage = load("res://textures/"+powerUp+".png")
powerUpSprite.set_texture(powerUpImage)
powerUpSprite.set_pos(Vector2(100,100))

that.... is so simple and so obvious (slaps face).
Thank you

It would be nice to turn the D comment into an answer ;)

although that solution works for that piece of code, it won't do much when you actually need to change something in the game besides the sprites. I assume those powerups will change variable values or something like that, so you will still need to check each case.

One solution for this could be to make a dictionary, each entry would be one powerup and contain the imagefile, etc, plus a callback for a function to activate that powerup.

This has been playing on my mind as I've been considering the exact issue. I haven't reached the effect of each power up yet but that's the perfect solution (dictionary). I guess I'll still need a huge if ELIF statement then. I can't seem to find anything about case statements in Godot being implemented.

no, with the dictinary you dont need any if statements, you just access the dictionary entry directly like

var selected_powerup = powerups[my_selection]
image = selected_powerup.image
hpchange += selected_powerup.hp

Thank you for this. I have to say I'm quite new at programming in general so please excuse my ignorance. I've been having a go at this but I can't seem to find out how to add all that data into a single dictionary to pull it out again as you've shown.

Imagine I have a dictionary called powerups.

I can do this kind of thing:

var powerUpDict = {
    powerUpName = "speedUpBat",
    batSpeedChange = 10,
    ballSpeedChange = 0,
    freezeBat = false,
    doublePoints = false,
    spawnRandomPowerup = false
}

But how can I add ANOTHER powerup to that dictionary so I can have them all within it? My understanding is if I do something like:

var powerUpDict = {
    powerUpName = "speedUpBat",
    batSpeedChange = 10,
    ballSpeedChange = 0,
    freezeBat = false,
    doublePoints = false,
    spawnRandomPowerup = false,
    powerUpName = "slowDownBat",
    batSpeedChange = -10,
    ballSpeedChange = 0,
    freezeBat = false,
    doublePoints = false,
    spawnRandomPowerup = false
}

... then I will have overwritten the duplicate named entries. Is that correct? I wonder if someone wouldn't mind pointing me in the right direction.

Anything to help, thank you :-)

You can't duplicate entries in a dictionary, what you need is a dictionary(powerups) of dictionaries(attributes of each powerup)

so, like

var powerUpDict = {
  "speedUpBat" : {
    batSpeedChange = 10,
    ballSpeedChange = 0,
    freezeBat = false,
    doublePoints = false,
    spawnRandomPowerup = false,
  },
  "slowDownBat" : {
    batSpeedChange = -10,
    ballSpeedChange = 0,
    freezeBat = false,
    doublePoints = false,
    spawnRandomPowerup = false
  }

}

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.

Categories