Загрузка данных
import pgzrun
import math
WIDTH = 800
HEIGHT = 600
game_map = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
player_x = 2.5
player_y = 2.5
player_angle = 0.0
FOV = math.pi / 3
NUM_RAYS = WIDTH
DIST_TO_PROJ = (WIDTH / 2) / math.tan(FOV / 2)
def draw():
screen.fill("black")
# Небо и пол – целочисленные координаты
screen.draw.rect(Rect(0, 0, WIDTH, HEIGHT // 2), (100, 100, 200))
screen.draw.rect(Rect(0, HEIGHT // 2, WIDTH, HEIGHT // 2), (50, 50, 50))
for i in range(NUM_RAYS):
ray_angle = player_angle - FOV / 2 + (i / NUM_RAYS) * FOV
ray_dir_x = math.cos(ray_angle)
ray_dir_y = math.sin(ray_angle)
map_x = int(player_x)
map_y = int(player_y)
delta_dist_x = abs(1 / ray_dir_x) if ray_dir_x != 0 else float('inf')
delta_dist_y = abs(1 / ray_dir_y) if ray_dir_y != 0 else float('inf')
if ray_dir_x < 0:
step_x = -1
side_dist_x = (player_x - map_x) * delta_dist_x
else:
step_x = 1
side_dist_x = (map_x + 1.0 - player_x) * delta_dist_x
if ray_dir_y < 0:
step_y = -1
side_dist_y = (player_y - map_y) * delta_dist_y
else:
step_y = 1
side_dist_y = (map_y + 1.0 - player_y) * delta_dist_y
hit = False
side = 0
distance = 0
max_steps = 50
steps = 0
while not hit and steps < max_steps:
if side_dist_x < side_dist_y:
side_dist_x += delta_dist_x
map_x += step_x
side = 0
else:
side_dist_y += delta_dist_y
map_y += step_y
side = 1
if map_x < 0 or map_x >= len(game_map[0]) or map_y < 0 or map_y >= len(game_map):
hit = True
break
if game_map[map_y][map_x] > 0:
hit = True
if side == 0:
distance = side_dist_x - delta_dist_x
else:
distance = side_dist_y - delta_dist_y
steps += 1
if not hit:
continue
if map_x < 0 or map_x >= len(game_map[0]) or map_y < 0 or map_y >= len(game_map):
continue
if game_map[map_y][map_x] == 0:
continue
corrected_dist = distance * math.cos(ray_angle - player_angle)
if corrected_dist < 0.01:
corrected_dist = 0.01
wall_height = DIST_TO_PROJ / corrected_dist
brightness = 1.0 / (1.0 + corrected_dist * 0.1)
if side == 0:
color = (int(200 * brightness), int(100 * brightness), int(100 * brightness))
else:
color = (int(150 * brightness), int(80 * brightness), int(80 * brightness))
# Приведение координат к целым числам
rect_x = i
rect_y = int(HEIGHT / 2 - wall_height / 2)
rect_h = int(wall_height)
screen.draw.rect(Rect(rect_x, rect_y, 1, rect_h), color)
def update(dt):
global player_x, player_y, player_angle
speed = 3.0
rot_speed = 2.0
if keyboard.left or keyboard.a:
player_angle -= rot_speed * dt
if keyboard.right or keyboard.d:
player_angle += rot_speed * dt
if keyboard.up or keyboard.w:
new_x = player_x + speed * dt * math.cos(player_angle)
new_y = player_y + speed * dt * math.sin(player_angle)
if game_map[int(new_y)][int(new_x)] == 0:
player_x, player_y = new_x, new_y
if keyboard.down or keyboard.s:
new_x = player_x - speed * dt * math.cos(player_angle)
new_y = player_y - speed * dt * math.sin(player_angle)
if game_map[int(new_y)][int(new_x)] == 0:
player_x, player_y = new_x, new_y
def on_key_down(key):
if key == keys.ESCAPE:
exit()
pgzrun.go()