In my game I need to cast rays to see which blocks are in the FirstPersonPlayer's field of view. Here is my code before implementing:
from ursina import \*
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
from load_assets import \*
import menu
block_pick = 1
block = 'grass'
equipped = 0
dev_menu = False
def update():
global block_pick
global block
global equipped
global hit
hit = \[\]
#cast rays from here.
if held_keys['1']: block_pick = 1
if held_keys['2']: block_pick = 2
if held_keys['3']: block_pick = 3
if held_keys['4']: block_pick = 4
if held_keys['5']: block_pick = 5
if held_keys['6']: block_pick = 6
if block_pick == 1:
block = 'grass'
if block_pick == 2:
block = 'dirt'
if block_pick == 3:
block = 'stone'
if block_pick == 4:
block = 'bricks'
if block_pick == 5:
block = 'stone bricks'
if block_pick == 6:
block = 'snow'
if held_keys['left mouse'] or held_keys['right mouse']:
hand.active()
else:
hand.passive()
if held_keys['f3']:
if not dev_menu:
dev_menu = True
else:
dev_menu = False
destroy(equipped)
equipped = Equipped()
class Voxel(Button):
def __init__(self, position = (0,0,0), texture = grass_texture):
super().__init__(
parent = scene,
position = position,
model = block_model,
origin_y = 0.5,
texture = texture,
color = color.color(0,0,random.uniform(0.9,1)),
highlight_color = color.light_gray,
scale = 0.5,
collider = 'box'
)
def input(self,key):
if self.hovered:
if key == 'right mouse down':
punch_sound.play()
if block_pick == 1:
voxel = Voxel(position = self.position + mouse.normal, texture = grass_texture)
if block_pick == 2:
voxel = Voxel(position = self.position + mouse.normal, texture = dirt_texture)
if block_pick == 3:
voxel = Voxel(position = self.position + mouse.normal, texture = stone_texture)
if block_pick == 4:
voxel = Voxel(position = self.position + mouse.normal, texture = brick_texture)
if block_pick == 5:
voxel = Voxel(position = self.position + mouse.normal, texture = stone_bricks_texture)
if block_pick == 6:
voxel = Voxel(position = self.position + mouse.normal, texture = snow_texture)
if key == 'left mouse down':
punch_sound.play()
destroy(self)
for z in range(16):
for x in range(16):
voxel = Voxel(position = (x,0,z))
for z in range(16):
for x in range(16):
voxel = Voxel(position = (x,-1,z),texture = stone_texture)
global player
player = FirstPersonController()
sky = Sky()
hand = Hand()
equipped = Equipped()
app.run()
I decided to add a raycast within the update loop, like this:
hit.extend(raycast(player.world_position, direction=player.forward, distance=math.inf).entities)
I also added an update function in the Voxel class:
def update(self):
if self in hit:
self.color = color.red
else:
self.color = color.white
I needed all the blocks in the player's view red, not just a single line of blocks like this:
A single line of blocks are red!
I tried using a boxcast(), like this:
hit.extend(boxcast(player.world_position, direction=player.forward, distance=math.inf, thickness = (4,4)).entities)
It resulted in an Assertion error, which is apparently caused by the computer's lack of computing power. Using a for loop to create multiple rays instead of just one ray resulted in a significant drop of performance.
for z in range(0,6):
print(player.forward/5)
hit.extend(raycast(player.world_position, direction=player.forward+(0,0,z/5), distance=math.inf).entities)
Check the top-right corner 7 FPS average. Anybody know how I can find all the blocks in the field of view of the player without an incredible drop of performance? Sorry about the indenting issues :/