Shuffling an Array

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By javrocks

For this node i want random movement but the problem is that the choose function continuously shuffles the array and as a result direction keeps changing so i think i need to shuffle the array, stop it then return the first element. How would i do that???

extends KinematicBody2D

var direction = Vector2.RIGHT
var state = 1

func choose(array):
array.shuffle()
return array.front()

func move(delta):
position += direction * 100 * delta

func _physics_process(delta):

  	if state == 1:
	   direction = choose([Vector2.RIGHT,Vector2.LEFT,Vector2.UP])
	   move(delta)
:bust_in_silhouette: Reply From: timothybrentwood

The problem here is you are changing directions every frame so the actor only moves 100 * delta pixels before potentially changing directions. You need to only change directions after a certain amount of time has elapsed.

The best way to do this is to create a child Timer node and connect its timeout signal to a callback function that handles the logic of changing directions. An alternative, less preferable way is to accumulate delta and change directions after a certain period of time (in this case 2 seconds):

extends Node2D

var direction = Vector2.RIGHT
var state = 1
var time_since_last_direction_change = 0

func choose(array):
	array.shuffle()
	return array.front()

func move(delta):
	position += direction * 100 * delta

func _physics_process(delta):
	time_since_last_direction_change += delta
	if time_since_last_direction_change > 2:
		direction = choose([Vector2.RIGHT,Vector2.LEFT,Vector2.UP])
		time_since_last_direction_change = 0
		
	if state == 1:
		move(delta)

Ummm… is there something i can do to the choose function that would make it return 1 direction after shuffling the array

javrocks | 2021-11-08 20:36

That is exactly what yourchoose() function does as it is implemented. The problem is you are potentially changing directions every frame which means your actor will only move a few pixels in one direction before potentially change directions. I can’t imagine this is desired behavior in any game.

The remedy is what I listed above. If you have any questions about how to implement the Timer node I’ll be happy to help.

timothybrentwood | 2021-11-08 21:06

Ok thanks for that explanation
And yes how would you implement the Timer Node

javrocks | 2021-11-08 21:59

extends Node2D

var direction = Vector2.RIGHT
var state = 1
const possible_directions = [Vector2.RIGHT, Vector2.LEFT, Vector2.UP]
var direction_change_timer : Timer

func _ready():
	direction_change_timer = Timer.new()
	direction_change_timer.wait_time = 2 # whatever you want it to be
	direction_change_timer.connect("timeout", self, "_on_direction_change_timer_timeout")
	
	self.add_child(direction_change_timer)
	
	direction_change_timer.start()
	
func choose(array):
	array.shuffle()
	return array.front()

func move(delta):
	position += direction * 100 * delta

func _physics_process(delta):
	if state == 1:
		move(delta)

func _on_direction_change_timer_timeout():
	direction = choose(possible_directions)

timothybrentwood | 2021-11-08 22:54

Ok thanks this was helpful

javrocks | 2021-11-09 15:07

Excellent answer. Thought you deserved to be upvoted.

DaddyMonster | 2021-11-09 21:57