import pygame
import math
import random

pygame.init()

WIDTH, HEIGHT = 800, 600
HALF_WIDTH = WIDTH // 2
HALF_HEIGHT = HEIGHT // 2
FPS = 60

screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

MAP_WIDTH, MAP_HEIGHT = 50, 50
map_data = []

def generate_forest():
    global map_data
    map_data = []
    for y in range(MAP_HEIGHT):
        row = []
        for x in range(MAP_WIDTH):
            # Randomly place trees with a certain density
            if random.random() < 0.2:  # 20% chance of a tree
                row.append(1)
            else:
                row.append(0)
        map_data.append(row)

def cast_rays(px, py, pa):
    rays = []
    ray_angle = pa - math.radians(30)  # 60-degree FOV
    for ray in range(120):  # Number of rays
        ray_angle += math.radians(0.5)
        sin_a = math.sin(ray_angle)
        cos_a = math.cos(ray_angle)

        for depth in range(1, 20):
            # Calculate ray coordinates
            target_x = px + cos_a * depth * 0.5
            target_y = py + sin_a * depth * 0.5

            # Map indices
            mx = int(target_x)
            my = int(target_y)

            # Check for map boundaries
            if 0 <= mx < MAP_WIDTH and 0 <= my < MAP_HEIGHT:
                if map_data[my][mx] == 1:  # Hit a tree
                    # Record the distance and angle
                    distance = depth * 0.5 * math.cos(pa - ray_angle)
                    rays.append((ray, distance))
                    break
        else:
            # No wall hit
            rays.append((ray, 20))
    return rays

def render_scene(rays):
    screen.fill((135, 206, 235))  # Sky blue

    for ray, distance in rays:
        # Calculate the height of the tree
        shade = 255 / (1 + distance * distance * 0.1)
        foliage_color = (0, int(shade), 0)  # Dark green foliage
        stem_color = (101, 67, 33)  # Brown stem
        line_width = WIDTH // 120  # Width of each slice (column)

        total_line_height = HEIGHT / (distance + 0.1)
        stem_height = total_line_height * 0.25  # 25% of the total height
        foliage_height = total_line_height * 0.75  # 75% of the total height

        # Compute vertical positions
        total_line_offset = HALF_HEIGHT - total_line_height / 2
        foliage_y = total_line_offset
        stem_y = foliage_y + foliage_height

        # Draw the foliage
        pygame.draw.rect(
            screen,
            foliage_color,
            (ray * line_width, foliage_y, line_width, foliage_height)
        )

        # Draw the stem
        pygame.draw.rect(
            screen,
            stem_color,
            (ray * line_width, stem_y, line_width, stem_height)
        )

player_x, player_y = MAP_WIDTH // 2, MAP_HEIGHT // 2
player_angle = 0

def handle_input():
    global player_x, player_y, player_angle
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player_angle -= 0.05
    if keys[pygame.K_RIGHT]:
        player_angle += 0.05
    if keys[pygame.K_UP]:
        player_x += math.cos(player_angle) * 0.1
        player_y += math.sin(player_angle) * 0.1
    if keys[pygame.K_DOWN]:
        player_x -= math.cos(player_angle) * 0.1
        player_y -= math.sin(player_angle) * 0.1

generate_forest()

running = True
while running:
    clock.tick(FPS)
    handle_input()

    rays = cast_rays(player_x, player_y, player_angle)
    render_scene(rays)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    pygame.display.flip()

pygame.quit()

Change my tree with plain png texture (file: tree.png)