I’m making a snapping constructing system in Ursina Engine (Python3).
- Create an the world (floor, a and b entities)
- Add a FirstPersonController
- Detect if left mouse button was pressed and if that’s the case begin Place class
- On Place class, create self.block and drag it to the place the mouse is pointing (raycast) or if raycast == None (it means the raycast did not collide with something), father or mother self.block to the digicam and put it in entrance of the participant’s digicam with a distance of 5 meters.
- Detect if self.block is at a distance of 1 meter of any snap level
- They’re within the Dice’s class, in 1 meter away from every face from the dice’s mannequin.
- The snap detection works by getting the gap between self.block and each snap level on this planet. If the gap between a sure snap level and self.block, then it is going to set the self.block’s place to the snap level
The snapping detection is just not very optimized and it’s not detecting the closest snapping level.
If you can also make the code higher and/or clear up the snapping downside, please put up your evaluation. Any assistance is welcome.
from ursina import *
from ursina.prefabs import *
from ursina.shaders import *
from direct.process import Process
from FPC import *
app = Ursina()
participant = FirstPersonController()
mouse.locked = False
Entity.default_shader = lit_with_shadows_shader
pivot = Entity()
direc_light = DirectionalLight(father or mother=pivot, y=2, z=3, shadows=True, rotation=(45, -45, 45), shadow_map_resolution = Vec2(4024, 4024))
amb_light = AmbientLight(father or mother=pivot, coloration = coloration.rgb(100, 100, 100), shadows = True)
world = Entity(mannequin="dice", scale=(20,.5,20), collider="mesh", coloration = coloration.white, everlasting = True)
participant.place = world.place
participant.y = 20
'''
Class Dice with a mannequin and eight snap items
UPDATE. Put a snapper in every face of the dice
'''
can_place_another_block = True
class Dice(Entity):
def __init__(self, father or mother = None, identify="main_cube", conn_name="connectors", color = coloration.blue, place = (0,0,0), collider="mesh"):
tremendous().__init__(
father or mother=father or mother,
identify=identify,
mannequin="dice",
place = place,
coloration=color,
collider=collider,
)
self.level = checklist()
self.snap_points = [
(0, 1, 0),
(0, -1, 0),
(1, 0, 0),
(-1, 0, 0),
(0, 0, 1),
(0, 0, -1),
]
for i in vary(len(self.snap_points)):
snap_point = Entity(father or mother = self,
identify = conn_name,
mannequin="dice",
world_x=self.x+self.snap_points[i][0],
world_y=self.y+self.snap_points[i][1],
world_z=self.z+self.snap_points[i][2],
scale=.1,
coloration=coloration.crimson,
collider="field"
)
self.level.append(snap_point)
a = Dice(collider="field", place=(0,0,0))
b = Dice(collider="field", place=(2,0,0))
class Place(Entity):
def __init__(self):
tremendous().__init__()
self.block = Dice(father or mother = None, identify="second_cube", conn_name="invalid_connector", color = coloration.inexperienced, place = mouse.world_point, collider = None)
self.connectors_list = checklist()
# Loop via all entities on this planet
for entity in scene.entities:
# If an entity is of sort connectors, them
if(entity.identify == "connectors"):
entity.coloration = coloration.yellow
self.connectors_list.append(entity)
## BUG IN CLOSEST ##
'''
get all entities to test and the principle entity
test the closest
'''
def closest(self, entity, iterable):
distances = []
for i in iterable:
i.coloration = coloration.black
for calculate_entity in iterable:
nearest = distance(calculate_entity, entity)
distances.append(nearest)
min_index = 0
list_len = len(distances)
for index in vary(list_len):
if distances[index] < distances[min_index]:
min_index = index
print(distances, "nn")
print(distance(self.block, iterable[min_index]))
#iterable[min_index].scale = 1.5
return iterable[min_index]
def replace(self):
closest = self.closest(self.block, self.connectors_list)
if distance(self.block, closest) < 1:
self.block.place = closest.world_position
closest.coloration = coloration.inexperienced
if held_keys['left mouse down']:
destroy(closest)
else:
strive:
cube_position = raycast(digicam.world_position, course=digicam.ahead, distance=5, traverse_target=scene, ignore=(participant, ), debug=False)
print(cube_position.world_point)
if cube_position.world_point == None:
self.block.father or mother = digicam
self.block.x = 0
self.block.y = 0
self.block.z = 5
self.block.world_rotation_x = 0
else:
self.block.father or mother = None
self.block.world_position = cube_position.world_point
self.block.x = 0
self.block.y = 0
#print(self.block.screen_position + self.block.world_position)
besides Exception as e:
print(e)
##
## for i, level in enumerate(self.block.level):
## level.x=self.x+self.block.snap_points[i][0],
## level.y=self.y+self.block.snap_points[i][1],
## level.z=self.z+self.block.snap_points[i][2],
##
def enter(self, key):
international can_place_another_block
if key == 'left mouse down':
print("HI")
Dice(place=self.block.world_position, collider="field")
destroy(self.block)
can_place_another_block = True
destroy(self)
def enter(key):
international can_place_another_block
if key == 'proper mouse down' and can_place_another_block == True:
can_place_another_block = False
Place()
if key == 'escape':
mouse.locked = False
if key == 'p':
destroy(mouse.hovered_entity)
if key == 'l':
mouse.locked = True
app.run()
```