Este artigo pode ser considerado a resposta para este , onde se trata de escrever algo em C ++, voltado para iniciantes, ou seja, com ênfase no código legível simples em vez do alto desempenho.Depois de ler o artigo, tive a idéia de repetir o programa escrito pelo autor. Eu estou familiarizado com C ++, mas nunca escrevi nenhum programa complicado, preferindo python. Aqui nasceu a ideia de escrever sobre ela. Eu estava especialmente interessado em desempenho - eu tinha quase certeza de que alguns quadros por segundo são o limite para o python. Eu estava errado.A primeira tentativa pode ser encontrada aqui . Aqui o código está escrito na íntegra, sem contar as diferenças de idioma, de acordo com o dehaqreu. E por causa disso, a renderização é O (n ^ 2) - essencialmente loops aninhados em ângulo e distância:
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:
dist = 0
x = player.x
y = player.y
while 0 < x < mapFB.w - 1 and 0 < y < mapFB.h - 1:
...
Por esse motivo, o código é bastante lento (consegui obter menos de 3-4 quadros por segundo no Intel Core i5 de 8ª geração).Uma maneira óbvia de acelerar as coisas e não complicar muito o código é substituir o loop interno por operações de complexidade linear. Vamos considerar tudo do ponto de vista da matemática: precisamos determinar o ponto de interseção do raio dado pelas coordenadas do jogador e o ângulo de visão e o bloco especificado pelas coordenadas e tamanho (constante, por simplicidade). Em seguida, você precisa selecionar a transferência mais próxima e devolvê-la. Abaixo está o código correspondente (o código completo está aqui ):def block_cross(i, j, k, y_0, alpha, player):
x_cell = i * H
y_cell = j * H
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))
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
Uma mudança tão trivial de 10 linhas dá uma aceleração de mais que o dobro, isto é, cerca de 5-6 quadros por segundo. Isso não é mais idiota, mas uma imagem em movimento, mas ainda bem lenta.Procurando idéias sobre como acelerar o código, me deparei com o Cython . Em resumo, este é um projeto que permite que você dê aceleração significativa ao código python sem alterá-lo seriamente. Brevemente sobre ele - sob o spoiler.tyts cpdef int fun(int num, float val):
cdef int result
return result
result int( int, , ). , . python-, cdef — python, cython. , python — , :
cpdef int fun(int num, float val):
cdef int result
return result
cdef int fun2(int *arr, float* arr_2):
cdef int arr_3[10][10]
return result
fun2 python, - fun — .
Cython deu alguma aceleração, embora insignificante - apenas alguns quadros por segundo. No entanto, em números relativos, isso não é tão pequeno - 8 a 9 imagens por segundo, ou seja, + 40% para a melhor opção em python e + 200% para a opção com um algoritmo ingênuo. Essa ainda é uma imagem muito instável, mas normal para fins educacionais. No final, nosso objetivo é escrever por conta própria e aproveitar o processo, mas, para um jogo real, é mais fácil pegar uma biblioteca como pygame ou, geralmente, deixar de lado o python e pegar algo mais adequado.PS Seria interessante ver outras opções para otimizar o código nos comentários.