Anonymous
3-D игра по пошаговому руководству по созданию Doom
Сообщение
Anonymous » 11 май 2026, 01:45
Я следую руководству по созданию рейкастера в стиле Wolfenstein на Python/pygame. 3D-проекция работает так, будто я могу передвигаться, но стены выглядят очень плоскими, почти как в 2D. Я показал картинку того, как я хотел, чтобы стены выглядели. Я пока не могу добавлять встроенные изображения, но похоже, что они просто плоские.
python:
Код: Выделить всё
import pygame as pg
import sys
from settings import *
from map import *
from player import *
from raycasting import *
class Game:
def __init__(self):
pg.init()
self.screen = pg.display.set_mode(res)
self.clock = pg.time.Clock()
self.delta_time = 1
self.new_game()
def new_game(self):
self.map = Map(self)
self.player = Player(self)
self.raycasting = RayCasting(self)
def update(self):
self.player.update()
self.raycasting.update()
pg.display.flip()
self.delta_time = self.clock.tick(fps)
pg.display.set_caption(f'{self.clock.get_fps():.1f}')
def draw(self):
self.screen.fill('black')
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
pg.quit()
sys.exit()
def run(self):
while True:
self.check_events()
self.update()
self.draw()
if __name__ == '__main__':
game = Game()
game.run()
settings.py:
Код: Выделить всё
import math
res = width, height = 1600, 900
half_width = width // 2
half_height = height // 2
fps = 0
player_pos = 1.5, 5
player_angle = 0
player_speed = 0.004
player_rot_speed = 0.002
fov = math.pi / 3
half_fov = fov / 2
num_rays = width // 2
half_num_rays = num_rays // 2
delta_angle = fov / num_rays
max_depth = 20
screen_dist = half_width / math.tan(half_fov)
scale = width // num_rays
raycasting.py:
Код: Выделить всё
import pygame as pg
import math
from settings import *
class RayCasting:
def __init__(self, game):
self.game = game
def ray_cast(self):
ox, oy = self.game.player.pos
x_map, y_map = self.game.player.map_pos
ray_angle = self.game.player.angle - half_fov + 0.0001
for ray in range(num_rays):
sin_a = math.sin(ray_angle)
cos_a = math.cos(ray_angle)
# horizontal
y_hor, dy = (y_map + 1, 1) if sin_a > 0 else (y_map - 1e-6, -1)
depth_hor = (y_hor - oy) / sin_a
x_hor = ox + depth_hor * cos_a
delta_depth = dy / sin_a
dx = delta_depth * cos_a
for i in range(max_depth):
tile_hor = int(x_hor), int(y_hor)
if tile_hor in self.game.map.world_map:
break
x_hor += dx
y_hor += dy
depth_hor += delta_depth
# vertical
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:
break
x_vert += dx
y_vert += dy
depth_vert += delta_depth
# depth
if depth_vert < depth_hor:
depth = depth_vert
else:
depth = depth_hor
# projection
proj_height = screen_dist / (depth + 0.0001)
pg.draw.rect(self.game.screen, "white",
(ray * scale, half_height - proj_height // 2, scale, proj_height))
ray_angle += delta_angle
def update(self):
self.ray_cast()
Сонет 4.6
1778453151
Anonymous
Я следую руководству по созданию рейкастера в стиле Wolfenstein на Python/pygame. 3D-проекция работает так, будто я могу передвигаться, но стены выглядят очень плоскими, почти как в 2D. Я показал картинку того, как я хотел, чтобы стены выглядели. Я пока не могу добавлять встроенные изображения, но похоже, что они просто плоские. [img]https://i.sstatic.net/7AKOYUae.png[/img] python: [code]import pygame as pg import sys from settings import * from map import * from player import * from raycasting import * class Game: def __init__(self): pg.init() self.screen = pg.display.set_mode(res) self.clock = pg.time.Clock() self.delta_time = 1 self.new_game() def new_game(self): self.map = Map(self) self.player = Player(self) self.raycasting = RayCasting(self) def update(self): self.player.update() self.raycasting.update() pg.display.flip() self.delta_time = self.clock.tick(fps) pg.display.set_caption(f'{self.clock.get_fps():.1f}') def draw(self): self.screen.fill('black') def check_events(self): for event in pg.event.get(): if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE): pg.quit() sys.exit() def run(self): while True: self.check_events() self.update() self.draw() if __name__ == '__main__': game = Game() game.run() [/code] settings.py: [code]import math res = width, height = 1600, 900 half_width = width // 2 half_height = height // 2 fps = 0 player_pos = 1.5, 5 player_angle = 0 player_speed = 0.004 player_rot_speed = 0.002 fov = math.pi / 3 half_fov = fov / 2 num_rays = width // 2 half_num_rays = num_rays // 2 delta_angle = fov / num_rays max_depth = 20 screen_dist = half_width / math.tan(half_fov) scale = width // num_rays [/code] raycasting.py: [code]import pygame as pg import math from settings import * class RayCasting: def __init__(self, game): self.game = game def ray_cast(self): ox, oy = self.game.player.pos x_map, y_map = self.game.player.map_pos ray_angle = self.game.player.angle - half_fov + 0.0001 for ray in range(num_rays): sin_a = math.sin(ray_angle) cos_a = math.cos(ray_angle) # horizontal y_hor, dy = (y_map + 1, 1) if sin_a > 0 else (y_map - 1e-6, -1) depth_hor = (y_hor - oy) / sin_a x_hor = ox + depth_hor * cos_a delta_depth = dy / sin_a dx = delta_depth * cos_a for i in range(max_depth): tile_hor = int(x_hor), int(y_hor) if tile_hor in self.game.map.world_map: break x_hor += dx y_hor += dy depth_hor += delta_depth # vertical 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: break x_vert += dx y_vert += dy depth_vert += delta_depth # depth if depth_vert < depth_hor: depth = depth_vert else: depth = depth_hor # projection proj_height = screen_dist / (depth + 0.0001) pg.draw.rect(self.game.screen, "white", (ray * scale, half_height - proj_height // 2, scale, proj_height)) ray_angle += delta_angle def update(self): self.ray_cast() [/code] Сонет 4.6