Python中的3D图片(几乎)具有正常性能

本文可以看作是这篇文章的答案,是针对初学者的用C ++编写这样的东西的问题,也就是说,重点是简单的可读代码而不是高性能。

阅读文章后,我想到了重复作者编写的程序的想法。我对C ++很熟悉,但是我从来没有在它上面写过任何复杂的程序,而喜欢使用python。这个想法诞生于此。我对性能特别感兴趣-我几乎可以确定每秒几帧是python的极限。我错了。

图片

图片

第一次尝试可以在这里找到这里的代码是完整的,不包括语言差异,哈克鲁因此,渲染为O(n ^ 2)-本质上是角度和距离上嵌套的循环:

         # iterating alpha
        alpha = player.view - player.fov / 2
        mapFB.drawRectangle(player.y - 1, player.x - 1, player.y + 1, player.x + 1, Color(255, 0, 0))
        rayNum = 0
        while alpha < player.fov / 2 + player.view:
            # iterating distance
            dist = 0
            x = player.x
            y = player.y
            while 0 < x < mapFB.w - 1 and 0 < y < mapFB.h - 1:
                  ...

因此,代码速度很慢(我在第8代Intel Core i5上每秒设法获得不到3-4帧)。

一种加快速度而不使代码复杂化的明显方法是用线性复杂度的运算代替内部循环。让我们从数学的角度考虑所有问题:我们需要确定玩家的坐标和视角所给定的光线的交点,以及坐标和大小所指定的块(为简单起见,为常数)。接下来,您需要选择最近的转账并将其退回。以下是相应的代码(完整代码在此处):

def block_cross(i, j, k, y_0, alpha, player):
    # cell coordinates
    x_cell = i * H
    y_cell = j * H
    # find collision points
    collisions = []

    if k != 0:
        x = (y_cell - y_0) / k
        y = y_cell
        if x_cell <= x <= x_cell + H and (x - player.x) / cos(alpha) < 0:
            collisions.append((x, y))

    if k != 0:
        x = (y_cell + H - y_0) / k
        y = y_cell + H
        if x_cell <= x <= x_cell + H and (x - player.x) / cos(alpha) < 0:
            collisions.append((x, y))

    x = x_cell
    y = y_0 + x * k
    if y_cell <= y <= y_cell + H and (x - player.x) / cos(alpha) < 0:
        collisions.append((x, y))

    x = x_cell + H
    y = y_0 + (x) * k
    if y_cell <= y <= y_cell + H and (x - player.x) / cos(alpha) < 0:
        collisions.append((x, y))

    # select the closest collision for the block
    dist = 1000 * H
    x = None
    y = None
    for collision in collisions:
        tmp = sqrt((collision[0] - player.x) ** 2 + (collision[1] - player.y) ** 2)
        if tmp < dist:
            dist = tmp;
            x = collision[0]
            y = collision[1]

    return x, y, dist

如此微不足道的10行变化会产生两倍以上的加速度,即每秒约5-6帧。这不再是混蛋,而是动态影像,但仍然很慢。
在寻找有关加速代码的想法时,我遇到了Cython简而言之,这是一个项目,可让您在不进行认真更改的情况下为python代码提供显着的加速。简要介绍一下他-在剧透下。

轮胎
 cpdef int fun(int num, float val):
    cdef int result
    # do some stuff
    return result

result int( int, , ). , . python-, cdef — python, cython. , python — , :

 cpdef int fun(int num, float val):
    cdef int result
    # do some stuff
    return result

 cdef int fun2(int *arr, float* arr_2):
    cdef int arr_3[10][10]
    # do some stuff
    return result

fun2 python, - fun — .

Cython提供了一些加速,尽管微不足道-每秒只有几帧。但是,相对而言,它并不是那么小-每秒8-9张图片,即python中最佳选项的+ 40%,而朴素算法的选项的+ 200%。这仍然是一个非常抽搐的画面,但出于教育目的是正常的。最后,我们的目标是自己编写并享受这个过程,但是对于真正的游戏,使用pygame之类的库,或者通常放下python并使用更合适的库,会更容易。

PS有趣的是,在注释中看到其他用于优化代码的选项。

Source: https://habr.com/ru/post/undefined/


All Articles