mirror of
https://github.com/Project-Redacted/Gayme.git
synced 2025-05-14 06:52:16 +00:00
117 lines
No EOL
4.5 KiB
Python
117 lines
No EOL
4.5 KiB
Python
import pygame as pg
|
|
import math
|
|
from settings import *
|
|
|
|
class RayCasting():
|
|
def __init__(self, game):
|
|
self.game = game
|
|
self.ray_casting_result = []
|
|
self.objects_to_render = []
|
|
self.textures = self.game.object_renderer.wall_textures
|
|
|
|
def get_objects_to_render(self):
|
|
self.objects_to_render = []
|
|
for ray, values in enumerate(self.ray_casting_result):
|
|
depth, proj_height, texture, offset = values
|
|
|
|
if proj_height < HEIGHT:
|
|
wall_column = self.textures[texture].subsurface(
|
|
offset * (TEXTURE_SIZE - SCALE), 0, SCALE, TEXTURE_SIZE
|
|
)
|
|
wall_column = pg.transform.scale(wall_column, (SCALE, proj_height))
|
|
wall_pos = (ray * SCALE, HALF_HEIGHT - proj_height // 2)
|
|
else:
|
|
texture_height = TEXTURE_SIZE * HEIGHT / proj_height
|
|
wall_column = self.textures[texture].subsurface(
|
|
offset * (TEXTURE_SIZE - SCALE), HALF_TEXTURE_SIZE - texture_height // 2,
|
|
SCALE, texture_height
|
|
)
|
|
wall_column = pg.transform.scale(wall_column, (SCALE, HEIGHT))
|
|
wall_pos = (ray * SCALE, 0)
|
|
|
|
self.objects_to_render.append((depth, wall_column, wall_pos))
|
|
|
|
def ray_cast(self):
|
|
self.ray_casting_result = []
|
|
ox, oy = self.game.player.pos
|
|
x_map, y_map = self.game.player.map_pos
|
|
|
|
texture_vert, texture_horz = 1, 1
|
|
|
|
ray_angle = self.game.player.angle - HALF_FOV + 0.0001 # 0.0001 to avoid division by zero
|
|
for ray in range(NUM_RAYS):
|
|
sin_a = math.sin(ray_angle)
|
|
cos_a = math.cos(ray_angle)
|
|
|
|
# horizontal
|
|
y_horz, dy = (y_map + 1, 1) if sin_a > 0 else (y_map - 1e-6, -1)
|
|
|
|
depth_horz = (y_horz - oy) / sin_a
|
|
x_horz = ox + depth_horz * cos_a
|
|
|
|
delta_depth = dy / sin_a
|
|
dx = delta_depth * cos_a
|
|
|
|
for i in range(MAX_DEPTH):
|
|
tile_horz = int(x_horz), int(y_horz)
|
|
if tile_horz in self.game.map.world_map:
|
|
texture_horz = self.game.map.world_map[tile_horz]
|
|
break
|
|
x_horz += dx
|
|
y_horz += dy
|
|
depth_horz += delta_depth
|
|
|
|
# verticals
|
|
x_vert, dx = (x_map + 1, 1) if cos_a > 0 else (x_map - 1e-6, -1)
|
|
|
|
depth_vert = (x_vert - ox) / cos_a
|
|
y_vert = oy + depth_vert * sin_a
|
|
|
|
delta_depth = dx / cos_a
|
|
dy = delta_depth * sin_a
|
|
|
|
for i in range(MAX_DEPTH):
|
|
tile_vert = int(x_vert), int(y_vert)
|
|
if tile_vert in self.game.map.world_map:
|
|
texture_vert = self.game.map.world_map[tile_vert]
|
|
break
|
|
x_vert += dx
|
|
y_vert += dy
|
|
depth_vert += delta_depth
|
|
|
|
# Select the shortest distance to the wall, and the corresponding texture
|
|
if depth_vert < depth_horz:
|
|
depth, texture = depth_vert, texture_vert
|
|
y_vert %= 1
|
|
offset = y_vert if cos_a > 0 else (1 - y_vert)
|
|
else:
|
|
depth, texture = depth_horz, texture_horz
|
|
x_horz %= 1
|
|
offset = (1 - x_horz) if sin_a > 0 else x_horz
|
|
|
|
# Draw the ray for debugging
|
|
if DEBUG_MODE:
|
|
pg.draw.line(self.game.screen, 'blue', (ox * 100, oy * 100),
|
|
(100 * ox + 100 * depth * cos_a, 100 * oy + 100 * depth * sin_a), 1)
|
|
|
|
# Remove fish-eye effect
|
|
if FISH_EYE_FIX:
|
|
depth *= math.cos(self.game.player.angle - ray_angle)
|
|
|
|
# Projection
|
|
proj_height = SCREEN_DIST / (depth + 0.0001) # 0.0001 to avoid division by zero
|
|
|
|
# Draw walls
|
|
#colour = [255 / (1 + depth ** 5 * 0.0002)] * 3
|
|
#pg.draw.rect(self.game.screen, colour,
|
|
# (ray * SCALE, HALF_HEIGHT - proj_height // 2, SCALE, proj_height))
|
|
|
|
# Ray casting result
|
|
self.ray_casting_result.append((depth, proj_height, texture, offset))
|
|
|
|
ray_angle += DELTA_ANGLE
|
|
|
|
|
|
def update(self):
|
|
self.ray_cast()
|
|
self.get_objects_to_render() |