From 142a92b2fca47475132b4deed2d81f8418549e5f Mon Sep 17 00:00:00 2001 From: "Daniele Verducci (Slimpenguin)" Date: Mon, 2 Jan 2023 10:36:31 +0100 Subject: [PATCH] Working horizontal ray casting and interception --- raycaster.py | 100 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 89 insertions(+), 11 deletions(-) diff --git a/raycaster.py b/raycaster.py index 2e9f264..c78e5a2 100755 --- a/raycaster.py +++ b/raycaster.py @@ -8,22 +8,41 @@ import sys import sdl2.ext import math +from time import time WIN_WIDTH = 640 -WIN_HEIGHT = 480 +WIN_HEIGHT = 640 DUNGEON_WIDTH = WIN_WIDTH DUNGEON_HEIGHT = WIN_HEIGHT PLAYER_SPEED = 10 RAY_LENGTH = 100 +MAP_SCALE = 80 +DOF = 8 # Depth Of Field + +MAP = [ + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 1, + 1, 0, 0, 0, 1, 1, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +] +MAP_SIZE = 8 class Main: def __init__(self): + # Check valid map + if len(MAP) != MAP_SIZE * MAP_SIZE: + raise ValueError("Map size is {}, but should be a power of {}", len(MAP), MAP_SIZE) + # Graphics sdl2.ext.init() - self.window = sdl2.ext.Window("Raycaster", size=(WIN_WIDTH, WIN_HEIGHT)) - self.window.show() - self.surface = self.window.get_surface() + self.mapWindow = sdl2.ext.Window("2D Map", size=(WIN_WIDTH, WIN_HEIGHT)) + self.mapWindow.show() + self.mapSurface = self.mapWindow.get_surface() # Player self.player_position = {"x": int(DUNGEON_WIDTH/2), "y": int(DUNGEON_HEIGHT/2), "r": 0} # r is rotation in radiants @@ -70,24 +89,83 @@ class Main: self.player_position["r"] = 0 if self.player_position["r"] < 0: self.player_position["r"] = 2*math.pi - print(self.player_position) - sdl2.ext.draw.fill(self.surface, sdl2.ext.Color(0,0,0,0)) # Clears screen + sdl2.ext.draw.fill(self.mapSurface, sdl2.ext.Color(0,0,0,0)) # Clears screen self.draw() - self.window.refresh() + self.mapWindow.refresh() return 0 def draw(self): + self.draw2Dmap() + self.drawPlayer() + self.drawRays() + + def drawPlayer(self): # Player in 2D map - sdl2.ext.draw.fill(self.surface, sdl2.ext.Color(0,255,0,255), (self.player_position["x"] - 2, self.player_position["y"] - 2, 4, 4)) + sdl2.ext.draw.fill(self.mapSurface, sdl2.ext.Color(0,255,0,255), (self.player_position["x"] - 2, self.player_position["y"] - 2, 4, 4)) # Player line of sight in 2D map ray = { "x": int(self.player_position["x"] + math.cos(self.player_position["r"]) * 50), # deltaX + playerX "y": int(self.player_position["y"] + math.sin(self.player_position["r"]) * 50) # deltaY + playerY } - print(self.player_position) - sdl2.ext.draw.line(self.surface, sdl2.ext.Color(255,0,0,255), (self.player_position["x"], self.player_position["y"], ray["x"], ray["y"])) - return + sdl2.ext.draw.line(self.mapSurface, sdl2.ext.Color(255,0,0,255), (self.player_position["x"], self.player_position["y"], ray["x"], ray["y"])) + + def draw2Dmap(self): + # 2D map + for i in range(len(MAP)): + posX = i % MAP_SIZE * MAP_SCALE + posY = math.floor(i / MAP_SIZE) * MAP_SCALE + color = 0 + if MAP[i] == 1: + color = 255 + sdl2.ext.draw.fill(self.mapSurface, sdl2.ext.Color(color,color,color,255), (posX, posY, MAP_SCALE - 1, MAP_SCALE - 1)) + + def drawRays(self): + # Casts rays for raycasting + rayAngle = self.player_position["r"] + for r in range(1): + # Check horizontal lines + dof = 0 # Depth of field + if rayAngle == 0 or rayAngle == math.pi: + print("horiz") + # Looking left or right (ray will never intersect parallel lines) + rayY = self.player_position["y"] + rayX = self.player_position["x"] + dof = DOF # Set depth of field to maximum to avoid unneeded checks + elif rayAngle > math.pi: + aTan = -1/math.tan(rayAngle) + print("down") + # Looking up + rayY = (int(self.player_position["y"] / MAP_SCALE) * MAP_SCALE) - 0.00001 + rayX = (self.player_position["y"] - rayY) * aTan + self.player_position["x"] + yOffset = -MAP_SCALE + xOffset = -yOffset * aTan + else: + aTan = -1/math.tan(rayAngle) + print("up") + # Looking down + rayY = (int(self.player_position["y"] / MAP_SCALE) * MAP_SCALE) + MAP_SCALE + rayX = (self.player_position["y"] - rayY) * aTan + self.player_position["x"] + yOffset = MAP_SCALE + xOffset = -yOffset * aTan + + # Check if we reached a wall + while dof < 8: + mapX = int(rayX / MAP_SCALE) + mapY = int(rayY / MAP_SCALE) + mapArrayPosition = mapY * MAP_SIZE + mapX + if mapArrayPosition < MAP_SIZE*MAP_SIZE and MAP[mapArrayPosition] != 0: + dof = 8 # Hit the wall: we are done, no need to do other checks + else: + # Didn't hit the wall: check successive horizontal line + rayX = rayX + xOffset + rayY = rayY + yOffset + dof = dof + 1 + + # Draw ray + sdl2.ext.draw.line(self.mapSurface, sdl2.ext.Color(0,255,0,255), (self.player_position["x"], self.player_position["y"], rayX, rayY)) + +