Загрузка данных


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()