[PyGame] Breaking Raycasting loop - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: [PyGame] Breaking Raycasting loop (/thread-37905.html) |
Breaking Raycasting loop - XavierPlatinum - Aug-06-2022 I have this raycasting code I've been working on. It mostly functions except I can't figure out how to break out of all the loops when the ray hits something. As it is I can see blocks that are supposed to be invisible behind he first block that the ray hits. The points in the ray are in order from the player. If I can break out further when contact is made then further blocks will not be illuminated. def cast_rays(self): rays = [] for b in self.game.level.block_dict.values(): b.illuminated = False for ray in range(0, 360, 20): ray_points = [] for depth in range(20, 100, 5): x = self.rect.centerx - math.sin(ray) * depth y = self.rect.centery + math.cos(ray) * depth ray_points.append((x,y)) rays.append(ray_points) for block in self.game.level.block_dict.items(): if abs(block[0][0] - self.rect.centerx) < 200: if abs(block[0][1] - self.rect.centery) < 200: for ray in rays: for point in ray: if block[1].rect.collidepoint(point): block[1].illuminated = True break else: continue break RE: Breaking Raycasting loop - deanhystad - Aug-07-2022 When a ray hits a block, what should happen to the ray? Do you want to stop looping when any ray hits a block? RE: Breaking Raycasting loop - XavierPlatinum - Aug-08-2022 (Aug-07-2022, 09:41 PM)deanhystad Wrote: When a ray hits a block, what should happen to the ray? Do you want to stop looping when any ray hits a block? No. The plan was to have a list of points for each ray, check the points in order, and if it hits something, stop, set the tile to "illuminated" and start on the next ray. As it is, it continues through and illuminates any block it hits. RE: Breaking Raycasting loop - deanhystad - Aug-08-2022 I don't think you need to compute all the ray points. I would check each point as it is computed and stop when a collision is detected. def illuminate_block(self, blocks, ray_point): """ Find first block that collides with ray_point, Returns block or None """ for block in blocks: if block[1].rect.collidepoint(ray_point): block[1].illuminated = True return block return None def cast_rays(self): cx = self.rect.centerx cy = self.rect.centery blocks = [] for b in self.game.level.block_dict.values(): b.illuminated = False # Cull the block list here so it doesn't have to happen for each ray point. if abs(b[0][0] - cx) < 200 and abs(b[0][1] - cy) < 200: blocks.append[b] for ray in range(0, 360, 20): # Do expensive sin and cos once per ray sin_ray = math.sin(ray) cos_ray = math.cos(ray) for depth in range(20, 100, 5): ray_point = (cx - sin_ray * depth, cy + cos_ray * depth) if self.illuminate_block(blocks, ray_point) is not None: breakIf you don't like using an additional funciton you can use a while loop. def cast_rays(self): cx = self.rect.centerx cy = self.rect.centery blocks = [] for b in self.game.level.block_dict.values(): b.illuminated = False if abs(b[0][0] - cx) < 200 and abs(b[0][1] - cy) < 200: blocks.append[b[1]] for ray in range(0, 360, 20): sin_ray = math.sin(ray) cos_ray = math.cos(ray) depth = 20 while depth <= 100: for b in blocks: if b.rect.collidepoint((cx - sin_ray * depth, cy + cos_ray * depth)): b.illuminated = True depth = 100 break depth += 5What are the blocks[0]? If they are sprites there are pygame functions that will do the work for you. RE: Breaking Raycasting loop - XavierPlatinum - Aug-08-2022 block[0] is a tuple for x,y coordinates. I didn't use blocks[0] . I used for block in self.game.level.block_dict.items() . So I get a list of tuples for the key/value pairs. block[0] is a tuple for x,y coordinates which are dictionary keys. block[1] is the sprite. I did initially checked each point as made, but changed it in my futile struggle to get things to work. And for no real reason, I thought that pygame.rect.collidepoint() would be the fastest way to check.
RE: Breaking Raycasting loop - squeamishfall - Oct-03-2023 If it collides with an object, then mark the tile as "illuminated" and go on to the next one. In its current form, it penetrates and illuminates whatever obstruction it encounters. phrazle |