0 votes

Hey folks,

Im trying to make a random item generator and want to use different art assets depending on the type of item is made. Each art asset is a grid with different sprites, so I want to first select the type of item, and then choose a random frame from that asset and use that for the sprite itself. Here is the code:

extends Area2D
var art_potions = preload("res://Assets/Art_Potion.tscn")
var art_medwep = preload("res://Assets/Art_MedWep.tscn")
onready var image = $Sprite

var possible_items = [

func _ready():

func roll_item_type():
    image = add_child(possible_items[0].instance())

func set_sprite():
    var image_h_number = image.get_hframes()
    var image_v_number = image.get_vframes()

    var hframe = randi() % image_h_number
    var vframe = randi() % image_v_number

    var randframe = Vector2(hframe, vframe)


the $Sprite is a sprite node bound to the item itself. it has the same art asset as art_potions. Changing the line from

onready var image = $Sprite


var image = null

gets me the same error.

The error is Invalid call. Nonexistent function 'gethframes' in base 'Nil'. The code works when the rollitemtype function is removed, so I guess the error comes from addchild, though I dont know how or why.

Any help would be appreciated.

EDIT: The 'artpotions' and 'artmedwep' are bots scenes with only a Sprite node.

in Engine by (14 points)
edited by

1 Answer

+1 vote

This line
image = add_child(possible_items[0].instance())
creates child node inside the object this script is attached to ($Area2D/Sprite) and then image variable becomes a reference to that node or something, try print(image) to know for sure.
So at the moment you call image.get_hframes(), the image variable is anything but Sprite.
Try to create an instance first and add it as child after it's processed by set_sprite().

by (68 points)
edited by

Well you found the issue, it prints Null. However, it does actually also set the sprite as it should. Any tips on how to find the correct node?

EDIT: Well I got it to work. I added this
var selected_item = possible_items[0].instance()
and replaced most references to image and now it works. Thanks for pointing me in the right direction.

I got it to work, looks like this now:

func roll_item_type():
    var selected_item = possible_items[0].instance()
    image = add_child(selected_item)

func set_sprite(selected_item):
    var image_h_number = selected_item.get_hframes()
    var image_v_number = selected_item.get_vframes()

    var hframe = randi() % image_h_number
    var vframe = randi() % image_v_number

    var randframe = Vector2(hframe, vframe)
    print(image_h_number, image_v_number, randframe)

I just had to make the Array adress into its own variable and now everything works like I wanted it to. Thanks for pointing me in the right direction.

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.