Как у вас есть несколько текстур с Raycasting? - PullRequest
0 голосов
/ 17 декабря 2018

Я смотрел в Интернете на приведение лучей для python и решил исследовать некоторый код, который был размещен;поэтому большая часть этого не мой код изначально.Я просто хочу понять, как это работает.

Программа запускает свои карты чтения текстовых документов, каждый из которых состоит из «1» и пробелов, например:

    11111111111111111
    1     11       11
    1 111 11 11 11 11
    1 1       1 11 11
    1 1 1       1  11
    1 1 111  11     1
    1 1      1111  11
    1   1  11   11 11
    1 1         1  11
    1 1    11   1  11
    1 1  1   1 111 11
    1 1   11     1 11
    1 1        1 1 11
    1 11 1     1    1
    1    1        111
    11111111111111111

Чтениекод, который компилирует это в полезную информацию, показывает, что ...

Преобразует строку в список, заменяет пробелы на "0", перечисляет список дважды (так что каждый отдельный символ может быть изолирован) изатем отправляет его в виде сетки для карты (где каждый «1» или «0» является отдельным элементом в списке).

Эта часть кода выглядит следующим образом:

    def create_level(file):
        if file[-4:] != '.txt': file += '.txt'
        f = open(os.path.join(path, file), 'r')
        file = f.readlines()

        for i, line in enumerate(file):
            file[i] = list(line.rstrip('\n'))
            for j, char in enumerate(file[i]):
                if char == ' ':
                    file[i][j] = 0
                else:
                    file[i][j] = int(char)

        f.close()

        mapBoundX  = len(file)
        mapBoundY  = len(file[0])
        mapGrid    = []

        for i, line in enumerate(file):
            mapGrid.append([])
            for j, char2 in enumerate(file[i]):
                if char2 != 0:
                    mapGrid[i].append(char2)
                else:
                    mapGrid[i].append(0)

        return mapBoundX, mapBoundY, mapGrid

В некоторых следующих функциях данные, взятые из предыдущего кода, преобразуются в фактическое приведение лучей.Я не совсем понимаю, что все это значит, но я учусь по ходу дела.Вот эта часть:

    def main():
        mapBoundX, mapBoundY, mapGrid = create_level(levelNum)
        posX, posY     = 8.5, 10.5
        dirX, dirY     = 1.0, 0.0
        planeX, planeY = 0.0, 0.66

        while True:
            #Input handling
            for event in pygame.event.get():
                if event.type == QUIT:
                    Quit()
                    return
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        Quit()
                        return

            #CEILING AND FLOOR
            pygame.draw.rect(SCREEN, ceiling_colour, (0, 0, WIDTH, (HEIGHT - map_size) / 2))
            pygame.draw.rect(SCREEN,   floor_colour, (0, (HEIGHT - map_size) / 2, WIDTH, (HEIGHT - map_size) / 2))

            for x in range(0, WIDTH, resolution):
                #Initial setup
                cameraX    = 2 * x / WIDTH - 1
                rayPosX    = posX
                rayPosY    = posY
                rayDirX    = dirX + planeX * cameraX + 0.000000000000001 #Add small value to avoid division by 0
                rayDirY    = dirY + planeY * cameraX + 0.000000000000001 #Add small value to avoid division by 0

                #Which square on the map the ray is in
                mapX = int(rayPosX)
                mapY = int(rayPosY)

                #The length of one ray from one x-side or y-side to the next x-side or y-side
                deltaDistX = sqrt(1 + rayDirY ** 2 / rayDirX ** 2)
                deltaDistY = sqrt(1 + rayDirX ** 2 / rayDirY ** 2)
                zBuffer    = []

                #Calculate step and initial sideDist
                if rayDirX < 0:
                    stepX = -1
                    sideDistX = (rayPosX - mapX) * deltaDistX
                else:
                    stepX = 1
                    sideDistX = (mapX + 1 - rayPosX) * deltaDistX

                if rayDirY < 0:
                    stepY = -1
                    sideDistY = (rayPosY - mapY) * deltaDistY
                else:
                    stepY = 1
                    sideDistY = (mapY + 1 - rayPosY) * deltaDistY

                #Digital differential analysis (DDA)
                while True:
                    #Jump to next map square
                    if sideDistX < sideDistY:
                        sideDistX += deltaDistX
                        mapX += stepX
                        side = 0
                    else:
                        sideDistY += deltaDistY
                        mapY += stepY
                        side = 1

                    #Check if ray hits wall or leaves the map boundries 
                    if mapX >= mapBoundX or mapY >= mapBoundY or mapX < 0 or mapY < 0 or mapGrid[mapX][mapY] > 0:
                        break

                #Calculate the total length of the ray
                if side == 0: rayLength = (mapX - rayPosX + (1 - stepX) / 2) / rayDirX
                else:         rayLength = (mapY - rayPosY + (1 - stepY) / 2) / rayDirY

                #Calculate the length of the line to draw on the screen
                lineHeight = (HEIGHT / rayLength) * wall_height

                #Calculate the start and end point of each line
                drawStart  = -lineHeight / 2 + (HEIGHT - map_size) / 2
                drawEnd    =  lineHeight / 2 + (HEIGHT - map_size) / 2

                #Calculate where exactly the wall was hit
                if side == 0: wallX = rayPosY + rayLength * rayDirY
                else:         wallX = rayPosX + rayLength * rayDirX
                wallX = abs((wallX - floor(wallX)) - 1)

                #Find the x coordinate on the texture
                texX = int(wallX * texWidth)
                if side == 1 and rayDirX > 0: texX = texWidth - texX - 1
                if side == 1 and rayDirY < 0: texX = texWidth - texX - 1

                c = max(1, (255.0 - rayLength * 27.2) * (1 - side * .25))

                yStart = max(0, drawStart)
                yStop = min(HEIGHT, drawEnd)
                pixelsPerTexel = lineHeight / texHeight
                colStart = int((yStart - drawStart) / pixelsPerTexel + .5)
                colHeight = int((yStop - yStart) / pixelsPerTexel + .5)

                yStart = int(colStart * pixelsPerTexel + drawStart + .5)
                yHeight = int(colHeight * pixelsPerTexel + .5)

                column = texture.subsurface((texX, colStart, 1, colHeight))
                column = column.copy()
                column.fill((c, c, c), special_flags=BLEND_MULT)
                column = pygame.transform.scale(column, (resolution, yHeight))
                SCREEN.blit(column, (x, yStart))

Теперь, к моей главной проблеме:

Я вижу ссылку на текстуру в разделе столбца, и она инициализируется ранее, но я не могу показатьсячтобы он загружал две разные текстуры одновременно.В идеале я хочу, чтобы некоторые блоки стен были одной текстурой, а некоторые - другой.Я попытался добавить третий символ, «2», в исходные текстовые документы карты, чтобы посмотреть, сможет ли программа их различить, но я не могу заставить это работать.

Если кто-то может объяснить, пожалуйстамне, как это работает, или что я могу делать неправильно при редактировании, эта помощь будет очень признательна.Спасибо!

...