First raycasting view

This commit is contained in:
Daniele Verducci 2023-01-02 20:26:52 +01:00
parent ec11c67f06
commit cb89bd8fa4

View File

@ -10,10 +10,12 @@ import sdl2.ext
import math import math
from time import time from time import time
WIN_WIDTH = 640 MAP_WIN_WIDTH = 640
WIN_HEIGHT = 640 MAP_WIN_HEIGHT = 640
DUNGEON_WIDTH = WIN_WIDTH RAYCAST_WIN_WIDTH = MAP_WIN_WIDTH
DUNGEON_HEIGHT = WIN_HEIGHT RAYCAST_WIN_HEIGHT = MAP_WIN_HEIGHT
DUNGEON_WIDTH = MAP_WIN_WIDTH
DUNGEON_HEIGHT = MAP_WIN_HEIGHT
PLAYER_SPEED = 10 PLAYER_SPEED = 10
RAY_LENGTH = 100 RAY_LENGTH = 100
MAP_SCALE = 80 MAP_SCALE = 80
@ -42,10 +44,14 @@ class Main:
# Graphics # Graphics
sdl2.ext.init() sdl2.ext.init()
self.mapWindow = sdl2.ext.Window("2D Map", size=(WIN_WIDTH, WIN_HEIGHT)) self.mapWindow = sdl2.ext.Window("2D Map", size=(MAP_WIN_WIDTH, MAP_WIN_HEIGHT))
self.mapWindow.show() self.mapWindow.show()
self.mapSurface = self.mapWindow.get_surface() self.mapSurface = self.mapWindow.get_surface()
self.raycastWindow = sdl2.ext.Window("3D View", size=(RAYCAST_WIN_WIDTH, RAYCAST_WIN_HEIGHT))
self.raycastWindow.show()
self.raycastSurface = self.raycastWindow.get_surface()
# Player # Player
self.player_position = {"x": int(DUNGEON_WIDTH/2), "y": int(DUNGEON_HEIGHT/2), "r": 0} # r is rotation in radiants self.player_position = {"x": int(DUNGEON_WIDTH/2), "y": int(DUNGEON_HEIGHT/2), "r": 0} # r is rotation in radiants
@ -93,8 +99,10 @@ class Main:
self.player_position["r"] = 2*math.pi self.player_position["r"] = 2*math.pi
sdl2.ext.draw.fill(self.mapSurface, sdl2.ext.Color(0,0,0,0)) # Clears screen sdl2.ext.draw.fill(self.mapSurface, sdl2.ext.Color(0,0,0,0)) # Clears screen
sdl2.ext.draw.fill(self.raycastSurface, sdl2.ext.Color(0,0,0,0)) # Clears screen
self.draw() self.draw()
self.mapWindow.refresh() self.mapWindow.refresh()
self.raycastWindow.refresh()
return 0 return 0
def draw(self): def draw(self):
@ -128,8 +136,8 @@ class Main:
playerAngle = self.player_position["r"] playerAngle = self.player_position["r"]
# Cast 60 rays from -30° to +30° (60° viewing angle) # Cast 60 rays from -30° to +30° (60° viewing angle)
for r in range(60): for i in range(60):
rayAngle = playerAngle - (r - 30)*DEGREE_IN_RADIANTS rayAngle = playerAngle - (i - 30)*DEGREE_IN_RADIANTS
# Check horizontal lines # Check horizontal lines
dof = 0 # Depth of field dof = 0 # Depth of field
@ -207,12 +215,30 @@ class Main:
rayY = rayY + yOffset rayY = rayY + yOffset
dof = dof + 1 dof = dof + 1
if self.dist(self.player_position["x"], self.player_position["y"], rayX, rayY) > self.dist(self.player_position["x"], self.player_position["y"], horizRayX, horizRayY): horizDist = self.dist(self.player_position["x"], self.player_position["y"], horizRayX, horizRayY)
vertDist = self.dist(self.player_position["x"], self.player_position["y"], rayX, rayY)
shortestDist = vertDist
if vertDist > horizDist:
rayX = horizRayX rayX = horizRayX
rayY = horizRayY rayY = horizRayY
shortestDist = horizDist
# Draw rays in 2D view
sdl2.ext.draw.line(self.mapSurface, sdl2.ext.Color(0,0,255,255), (self.player_position["x"], self.player_position["y"], rayX, rayY)) sdl2.ext.draw.line(self.mapSurface, sdl2.ext.Color(0,0,255,255), (self.player_position["x"], self.player_position["y"], rayX, rayY))
# ------ Draw 3D view ------
# Calculate line height based on distance
lineHeight = MAP_SCALE * RAYCAST_WIN_HEIGHT / shortestDist
if lineHeight > RAYCAST_WIN_HEIGHT:
lineHeight = RAYCAST_WIN_HEIGHT
# Center line vertically in window
lineOffset = RAYCAST_WIN_HEIGHT / 2 - lineHeight / 2
# Draw line
for x in range(i*10, i*10+10):
sdl2.ext.draw.line(self.raycastSurface, sdl2.ext.Color(255,255,255,255), (x, int(lineOffset), x, int(lineOffset + lineHeight)))
def dist(self, ax, ay, bx, by): def dist(self, ax, ay, bx, by):
return math.sqrt((bx-ax)*(bx-ax) + (by-ay)*(by-ay)) return math.sqrt((bx-ax)*(bx-ax) + (by-ay)*(by-ay))