Problem creating shots

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By LaMoscaSAS
:warning: Old Version Published before Godot 3 was released.

Hello, I’m new to godot and programming. Problem is, I can not get my ship to fire. I have created a sprite-type node named “spr_nave_shoots” that initialized in graph 2d with the parameter “visible” disabled. Then, in the parent script, create an empty array. When left-clicking the mouse, I have told godot that, this value is equal to the sprite “spr_nave_shoots” with the difference that it will have the “visible” property activated. Once the sprite is stored inside the array, it will proceed to move the sprite, but when I try to get the position of the sprite and modify it, godot retorn me following error message: "Invalid get index ‘[Sprite: 563]’ (Based on ‘Array’). ".

These is my code:

 extends Node2D
    
    onready var nave = get_node("spr_nave")
    onready var nave_prt = get_node("prt_nave")
    onready var nave_shoot = get_node("spr_nave_shoot")
    onready var nave_shoots = []
    
    func _ready():
    	set_process(true)
    
    func _process(delta):
    	action_nave(delta)
    	mover_disparos_nave(delta)
    
    func move_shoot(shoot,delta):
    	var sh = shoot
    	var sh_p = shoot.get_pos()
    	
    
    func mover_disparos_nave(delta):
    	for i in nave_shoots:
    		move_shoot(nave_shoots[i],delta)
    
    func disparar(delta):
    	#var pos = nave_shoot.get_pos()
    	#pos.y -=200*delta
    	#nave_shoot.set_pos(pos)
    	var disparo = nave_shoot
    	var dis_pos = disparo.get_pos()
    	dis_pos = nave.get_pos()
    	disparo.show()
    	disparo.set_pos(dis_pos)
    	nave_shoots.push_back(disparo)
    
    func action_nave(delta):
    	if(Input.is_action_pressed("spr_nave_shoot")):
    			disparar(delta)

Thanks!

:bust_in_silhouette: Reply From: Zylann

Your for loop is not range-based, so here i is the sprite itself, not its index. You don’t need to write nave_shoots[i]:

for shoot in nave_shoots:
    move_shoot(shoot, delta)

Alternatively, range-based for would look like this:

for i in range(0, nave_shoots.size()):
    move_shoot(nave_shoots[i], delta)

Thank you very much! Now it works.

LaMoscaSAS | 2016-11-25 20:23

:bust_in_silhouette: Reply From: eons

If you look to the line you get the error, you may see the array is full of null objects (read errors, use breakpoints, analize variables and the tree).

I don’t understand why but seems you can’t assign an instanced node reference (from get_node) to an array, if you want to do that, use get_instance_ID on the node you got, then to recover the node with that id, do instance_from_id.


And pay attention that your shots will be working all on the same node, you are never duplicating or instancing new shots (look the platformer or shooter demos and read the docs for multiple instancing tutorials and explanations).

Hi, you’re right. Now I can shoot, but I’m working on the same node, and at the time of making a new shot, godot, puts it in the starting position. What I have to do is work with duplicate instances of the main node. I am right?

LaMoscaSAS | 2016-11-25 20:28

Yes, the best option could be to make a scene from the shot, then preload the shot on the ship.
Demos use this way and it works nice with export(PackedScene) var so you can choose the shot scene independent of the shot from the inspector.

Later, when you need a shot, just instance the preloaded, fix the proper global positions and other data and add the instance to the tree.
Careful where you add it, get_tree().get_root() is viewport, next comes scene root where is the lowest node you should add them.

And more, to keep track of your shots (and also for detection filtering) you can use groups instead of arrays, just add every instanced shot to a group (as many groups as you need).

Finally, remember to delete the shots (time based, screen, with a visibility notifier, etc.).

eons | 2016-11-25 21:40