I tried to make this code execute code when the green cubes are clicked, and it worked:
from ursina import *
nav = [None, 0, 0]
"""nav[0] store the cubes hovered data so i can get information and change it (type(nav[0]) is entity)
nav[1] tells the player if it must move or not (0 and 1)
nav[2] tells the program when it should reset nav (when the movement is over)(with 0 and 1)"""
# Configurable variables
movement_speed = 0.1 # Speed of movement when holding WASD
rotation_speed = 40 # Speed of rotation (degrees per frame)
camera_distance = 15 # Distance of the camera from the player
target_threshold = 0.5 # Distance threshold to stop moving when reaching the target
control_mode = 0 # 0 = Move with click, 1 = Move with WASD
"""this is the function that is called when a green cube is clicked and store the cubes data (like position)
and tells the player when to start movement (with nav[1]):"""
def click():
global nav
nav = [
(mouse.hovered_entity.x,#cube x
mouse.hovered_entity.y + mouse.hovered_entity.scale[1] / 2,#cube y
mouse.hovered_entity.z),#cube z
1, #start or not
0]#reset nav to None when movment is over
"""I made a function that gets the player position (a_x,a_y) and
block that is clicked(b_x ,b_y) and return the I and j vector that i** 2+j**2 =1 .
if the distance of player from block is less than 0.5 it will make nav [ 2] True so the player will stop: """
def normalize_direction_vector(x_a, y_a, x_b, y_b):
global nav
dx = x_b - x_a
dy = y_b - y_a
magnitude = math.sqrt(dx**2 + dy**2)
try:
i = dx / magnitude
if magnitude < target_threshold:
nav[2] = 1
except:
i = 0
nav[2] = 1
try:
j = dy / magnitude
if magnitude < target_threshold:
nav[2] = 1
except:
j = 0
nav[2] = 1
return [i, j]
#u is the app(windows) and a is the player a white cube:
u = Ursina(fullscreen=1, development_mode=1)
a = Entity(model="cube", position=Vec3(0, 0, 0), scale=Vec3(1, 1, 1))
""" I made a 10*10 platform of green cubes
which when they are clicked the player will move and their action is click()
and the problem is when they are clicked the function doesnt run:"""
for i in range(10):
for j in range(10):
block = Entity(model='cube',
color=color.green,
position=Vec3(i, -1, j),
scale=Vec3(1, 1, 1),
collider="box",
on_click=click)#here is the problem
cam = camera
while True:
if held_keys["escape"]:
break
"""makes the cube that was hovered by the mouse green again so
it won't remain black(because the mouse makes the hovered blocks black later in the code.
I don't want them to remain black and become green again if mouse is not hovered) """
try:
hov.color = color.green
except:#if hov is None
pass
if control_mode: # WASD Movement
if held_keys["w"]:
a.x += movement_speed
a.z += movement_speed
if held_keys["s"]:
a.x -= movement_speed
a.z -= movement_speed
if held_keys["a"]:
a.x -= movement_speed
a.z += movement_speed
if held_keys["d"]:
a.x += movement_speed
a.z -= movement_speed
"""makes the player move if hov[1] is true(the player must move)
and make the player move (using line 16-35) .
if hov[2] is true the nav list will reset and the player won't move anymore:"""
if not control_mode and nav[1]: # Click-to-move
c = normalize_direction_vector(a.x, a.z, nav[0][0], nav[0][2])
if nav[2]:#check if the plauer must stop
nav = [None, 0, 0]
else:
a.x += c[0] * movement_speed
a.z += c[1] * movement_speed
"""controls the camera and the players view with mouse"""
a.look_at((mouse.x * 5 + a.x, 0, mouse.y * 5 + a.z,))
cam.x = a.x - camera_distance
cam.y = a.y + camera_distance
cam.z = a.z - camera_distance
cam.look_at((mouse.x * 5 + a.x, 0, mouse.y * 5 + a.z,))
a.rotate(Vec3(0, rotation_speed, 0))
"""folowing line will make the hovered cubes with mouse black ."""
try:
hov = mouse.hovered_entity
mouse.hovered_entity.color = color.black
except:#if no hov cubes
pass
u.step()#update
But when I changed my code to be in a function, like this:
python
from ursina import *
def click():
global nav
nav = [(mouse.hovered_entity.x, mouse.hovered_entity.y + mouse.hovered_entity.scale[1] / 2, mouse.hovered_entity.z), 1, 0]
def runner():
nav = [None, 0, 0]
# Configurable variables
movement_speed = 0.1 # Speed of movement when holding WASD
rotation_speed = 40 # Speed of rotation (degrees per frame)
camera_distance = 15 # Distance of the camera from the player
target_threshold = 0.5 # Distance threshold to stop moving when reaching the target
control_mode = 0 # 0 = Move with click, 1 = Move with WASD
def normalize_direction_vector(x_a, y_a, x_b, y_b):
global nav
dx = x_b - x_a
dy = y_b - y_a
magnitude = math.sqrt(dx**2 + dy**2)
try:
i = dx / magnitude
if magnitude < target_threshold:
nav[2] = 1
except:
i = 0
nav[2] = 1
try:
j = dy / magnitude
if magnitude < target_threshold:
nav[2] = 1
except:
j = 0
nav[2] = 1
return [i, j]
u = Ursina(fullscreen=1, development_mode=1)
a = Entity(model="cube", position=Vec3(0, 0, 0), scale=Vec3(1, 1, 1))
for i in range(10):
for j in range(10):
block = Entity(model='cube', color=color.green, position=Vec3(i, -1, j), scale=Vec3(1, 1, 1), collider="box", on_click=click)
cam = camera
while True:
if held_keys["escape"]:
break
try:
hov.color = color.green
except:
pass
if control_mode: # WASD Movement
if held_keys["w"]:
a.x += movement_speed
a.z += movement_speed
if held_keys["s"]:
a.x -= movement_speed
a.z -= movement_speed
if held_keys["a"]:
a.x -= movement_speed
a.z += movement_speed
if held_keys["d"]:
a.x += movement_speed
a.z -= movement_speed
if not control_mode and nav[1]: # Click-to-move
c = normalize_direction_vector(a.x, a.z, nav[0][0], nav[0][2])
if nav[2]:
nav = [None, 0, 0]
else:
a.x += c[0] * movement_speed
a.z += c[1] * movement_speed
a.look_at((mouse.x * 5 + a.x, 0, mouse.y * 5 + a.z,))
cam.x = a.x - camera_distance
cam.y = a.y + camera_distance
cam.z = a.z - camera_distance
cam.look_at((mouse.x * 5 + a.x, 0, mouse.y * 5 + a.z,))
try:
hov = mouse.hovered_entity
mouse.hovered_entity.color = color.black
except:
pass
a.rotate(Vec3(0, rotation_speed, 0))
u.step()
runner()
it does not work anymore.
Also, I do not want to change my code to do something like have the mainloop contained in a function, I want to keep it contained in a while
loop.
I believe it is because of the global keywords inside of the click() function. defining nav inside the runner() function gets scoped to that function, so the global nav inside click() doesn't get referred to the same variable
use nav as a global variable outside the runner function.
nav = [None, 0, 0]
and inside the functions include
global nav
Here is the discord if you need any more help