Rocks not spawning as they should

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

Hey so I am finishing a game and I have a major glitch of asteroids not spawning in correctly… They just don’t spawn whatsoever… Nothing even appears in debug. Here are all the codes linked to the rocks:

var rock = preload("res://rock.xml")
var rockCount  = 0
var rockArray = []

func game(delta):
	var timeSinceLastRock = 0
	timeSinceLastRock = timeSinceLastRock * delta
	if timeSinceLastRock > 1:
			rock()
			timeSinceLastRock = 0
	if Input.is_action_pressed("ui_focus_next"):
		if IsSpacePressed == false:
			fire()
			IsSpacePressed = true
	else:
		IsSpacePressed = false
	var shipPos = get_node("spaceship").get_pos()
	if Input.is_action_pressed("ui_left"):
		shipPos.x = shipPos.x - 300 * delta
	if Input.is_action_pressed("ui_right"):
		shipPos.x = shipPos.x + 300 * delta
	get_node("spaceship").set_pos(shipPos)
	var laserid = 0
	for laser in laserArray:
		var laserPos = get_node(laser).get_pos()
		laserPos.y = laserPos.y - 300 * delta
		get_node(laser).set_pos(laserPos)
		if laserPos.y < 0:
			get_node(laser).queue_free()
			laserArray.remove(laserid)
		laserid = laserid + 1
	var rockid = 0
	for rock in rockArray:
		var rockPos = get_node(rock).get_pos()
		rockPos.y = rockPos.y + 150 * delta
		get_node(rock).set_pos(rockPos)
		if rockPos.y > 720:
			get_node(rock).queue_free()
			rockArray.remove(rockid)
		rockid = rockid + 1
	var laserid = 0
	for laser in laserArray:
		var rockid = 0
		for rock in rockArray:
			var rockPos = get_node(rock).get_pos()
			var laserPos = get_node(laser).get_pos()
			if laserPos.y < rockPos.y:
				if laserPos.x > rockPos.x - 10:
					if laserPos.x < rockPos.x + 10:
					get_node(rock).queue_free()
					rockArray.remove(rockid)
					get_node(laser).queue_free()
					laserArray.remove(laserid)
					score = score + 1
					get_node("score").set_text(str(score))
			rockid = rockid + 1
		laserid  = laserid + 1
	var rockid = 0
	for rock in rockArray:
		var rockPos = get_node(rock).get_pos()
		var shipPos = get_node("ship").get_pos()
		if rockPos.y > 500:
			if (rockPos.x -10) < (shipPos.x + 50):
				if (rockPos.x + 10) < (shipPos.x - 50):
					get_node("score").set_text("CRASH!!")
					gameRunning = false
#END OF FUNCTION

And the spawning function:

func rock():
	var rock_instance = rock.instance()
	rock_instance.set_name("rock"+str(rockCount))
	add_child(rock_instance)
	var rockPos = get_node("rock"+str(rockCount)).get_pos()
	rockPos.x = rand_range(0, 320)
	rockPos.y = -5
	get_node("rock"+str(rockCount)).set_pos(rockPos)
	rockArray.push_back("rock"+str(rockCount))
	rockCount = rockCount + 1
	print(rockArray)
#END OF FUNCTION

To clarify, they are instanced without error, but you cannot see them?

Zylann | 2016-05-26 22:57

var timeSinceLastRock = 0
timeSinceLastRock = timeSinceLastRock * delta
if timeSinceLastRock > 1:

This will always be 0. How does that work?

duke_meister | 2016-05-26 23:40

First, you named your function game(delta). I suspect you want it to be called on every frame, so you must call it from _process(delta).

Second, timeSinceLastRock is always zero because you declare it as a local variable, it won’t be remembered across frames. So instead, to spawn things at time intervals you should do something like this:

# Member variable
var timeSinceLastRock = 0

func _ready():
    # Tell Godot we run on every frame
    set_process(true)

func _process(delta):
	game(delta) # or you could put the contents of game() here, it doesn't matters

func game(delta):
	# Increment the variable
	timeSinceLastRock += delta
	if timeSinceLastRock > 1:
		# One second passed, spawn a rock!
		rock()
		# Reset time
		timeSinceLastRock = 0
	...

Note that you can also do this with a Timer node.

Zylann | 2016-05-28 11:22

:bust_in_silhouette: Reply From: puppetmaster-

You can do it in Godot way more easy.
(please don’t understand it like you do it false)

First you need 3 scene.

  • spaceship scene (KinematicBody2D)
  • laser scene (KinematicBody2D)
  • rock scene (KinematicBody2D)

Add each scene in to a group.

  • spaceship to group spaceship
  • laser to group laser
  • rock scene to group rock

Each scene should have a area2d with collisionNode.

Give spaceship scene a script with steering and shooting function and this.

_read()
	get_node("area2d").connect("body_enter",self,"onBodyEnter")
    
func onBodyEnter(body):
	if(body.is_in_group("rock")):
		#spaceship destroyed with rock
		destroyShip()

Give Rock a script with:

_read()
	get_node("area2d").connect("body_enter",self,"onBodyEnter")
    
func onBodyEnter(body):
	if(body.is_in_group("laser")):
		#rock destroyed with laser
		#free laser
		body.remove_from_group("laser")
		body.add_to_group("free")
		#free rock
		remove_from_group("rock")
		add_to_group("free")

In main game scene add spaceship scene and add a script to spawn rocks and game logic.
You don’t need set_name(). You can use the instancing laser and rock variable to work with them.

func _ready():
	rockScn = load("res://rock.xml")

func spawnNewRock():
	var rock = rockScn.instance()
	rock.set_pos(newRockSpawnPosition())
	get_node("allRockNode").add_child(rock)

To find out how many rocks you have you can use this:

get_tree().get_nodes_in_group("rock")

to free all in group free you can use this in your main game scene

func free_nodes():
	for freeNode in get_tree().get_nodes_in_group("free"):
		freeNode.free()