0 votes

I tried using this code for random obstacle generation.

extends Node2D

export (Array, PackedScene) var obstacles

var pos : Vector2 = Vector2()

func _ready():
    assert(len(scenes))
    add_random_obstacle(pos)

func add_random_obstacle(pos : Vector2) -> Node2D:
    return add_obstacle(floor(rand_range(0, len(obstacles))), pos)

func add_obstacle(type : int, pos : Vector2) -> Node2D:
    assert(type >= 0 and type < len(obstacles))
    var new_obstacle : Node2D = obstacles[type].instance()
    new_obstacle.position = pos
    add_child(new_obstacle)
   return new_obstacle

I created a ProgressionTester.tscn which is a Node2D node and added the code. It works perfectly fine. Random obstacles are being instanced. But I tried adding the same code in Enemy.tscn which is a Position2D node ; But I am getting assertion error and the obstacles are not being instanced. Can you please take a look in the project below ?

[ I have added the ProgressionTester.tscn in Tests folder and Enemy.tscn in the Enemy folder in the project below. ]
Here is the Project

asked May 27 in Projects by Yasin (53 points)

it might be that, the equivalent of obstacles in enemy_node which is spawnReference, is not an array, so you are calling len() on a single object, which create the error

I added array; Now I am not getting any errors but the Enemy(Position2D) node is moving back and forth as I set the animation player loop. The obstacles are not instanced.I think I have done some mistake in connecting the signal of Timer node in the Enemy.gd. Can you please take a look in that script
Here is the corrected Project.
Here is the Image.

1 Answer

0 votes
Best answer

replace "scenes" with "obstacles"

my fault in the old topic... sorry

answered May 27 by whiteshampoo (976 points)
selected Jun 4 by Yasin

Sorry about that; I had already corrected it. Now I am not getting any errors but the Enemy(Position2D) node is moving back and forth as I set the animation player loop to instance the obstacles. But the obstacles are not instanced. I think I have done some mistake in connecting the signal of Timer node in the Enemy.gd. Can you please take a look in that script ?
Here is the corrected Project.
Here is the Image.

  1. stuff after return will not get executed, because the function will end there.
  2. your signal from the Timer (without arguments) is connected add_obstacle (2 arguments).

You should check the Debugger-Tab on the buttom and watch for warnings and errors!

I made some changes in the project as you had told;

1. stuff after return will not get executed, because the function will end there.

I didn't understand this one. If you ment this two errors
Narrowing conversion (float is converted to int and loses precision) and The function 'addrandomobstacle()' returns a value, but this value is never used ; I had already got these errors in the ProgressionTester.tscn. But the obstacles were randomly instancing and the code was working fine.

2. your signal from the Timer (without arguments) is connected add_obstacle (2 arguments).

I have connected the timer signal with arguments to the function add_obstacle(type : int, pos : Vector2) -> Node2D:. I got rid of that error.

Still also I am getting the same result as in the Image
Here is the modified Project

Step 1: Remove from Player.gd:

func _process(delta):
    if Input.is_action_pressed("ui_up"):
        position.y -= 15
    if Input.is_action_pressed("ui_down"):
        position.y += 15
    if Input.is_action_pressed("ui_left"):
        position.x += 15
    if Input.is_action_pressed("ui_right"):
        position.x -= 15

and the last line of

func _physics_process(delta : float) -> void:
    get_input()
    move_and_slide(velocity)
    position.y -= 15 # <- only this

You should not set the position directly. the move_and_slide does this for you.
If you set the position manually, the physics (collisions) will give strange behaviour!
You should tweak the speed a little bit: (Line 4-5)

export (float, 200.0, 1000.0, 10.0) var progression_speed : float = 500.0
export (float, 200.0, 1000.0, 10.0) var movement_speed : float = 300.0

Step 2: Replace in Enemy.gd:

add_child(new_obstacle) 

to

get_parent().add_child(new_obstacle) 

if you add the obstacle as a child of your enemy, it will move with the enemy, not indipendently. and because you keep the enemy infront if you player, so the obstacle will.

Also replace:

func add_random_obstacle(pos : Vector2) -> Node2D:
    return add_obstacle(floor(rand_range(0, len(spawnReference))), pos)

with

func add_random_obstacle() -> Node2D:
    return add_obstacle(floor(rand_range(0, len(spawnReference))))

and

func add_obstacle(type : int, pos_ : Vector2)

with

func add_obstacle(type : int) -> Node2D:

Because you set the position to the global position of the enemy-node, you dont need to set the position.


Step 3: Profit!!!


Step 4: Reconnect Timer-timeout in Enemy.tscn:

remove the connection from the Timer to add_obstacle, and connect it to add_random_obstacle.

Now different obstacles will be spawned.


I think this is everything i changed and it works.

Thank you so much. Now the obstacles are instancing randomly.

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.