Пигамные лаги с добавленными пигамными прямоугольниками - PullRequest
0 голосов
/ 11 октября 2018

Я запускаю игру на питоне с примерно 2 тыс. Прямоугольников, нарисованных на экране в каждом кадре.game

У меня проблема в том, что она работает на 12 кадрах в секунду, и я не знаю, как это исправить.Когда я удаляю все прямоугольники, он сдвигается до 100 кадров в секунду.Я не отображаю их все сразу, а только те, которые камера может видеть в данный момент.Как исправить эту проблему скачка задержки, это потому, что я использую прямоугольники пигмеев или потому, что я использую их неправильно?

вот код

import pygame
black = (0,0,0)
pygame.init()
gameDisplay = pygame.display.set_mode((0,0),pygame.FULLSCREEN)
gameDisplay.fill(black)
gameDisplay.convert()
clock = pygame.time.Clock()
display_width = 1920
display_height = 1080

from opensimplex import OpenSimplex
tmp = OpenSimplex()

dimensions = [100,100]
size = 40

def mapping(x):
    y = (x + 1) * 10 + 40
    return y

class GroundCell:
    def __init__(self,x,y,dim):
        self.x = x
        self.y = y
        self.dim = dim

tempcells = []
allCells = []

for a in range(0,dimensions[0]):
    tempcells = []
    for b in range(0,dimensions[1]):
        tempcells.append(GroundCell(a*size,b*size,mapping(tmp.noise2d(a*0.11,b*0.11))))
    allCells.append(tempcells)

font = pygame.font.Font("freesansbold.ttf", 20)
while True:
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                quit()
    for a in allCells:
        for b in a:
            if b.x in range(0,display_width) \
                and b.y in range(0,display_height) or\
                b.x+size in range(0,display_width) \
                and b.y+size in range(0,display_height) :
                pygame.draw.rect(gameDisplay,(b.dim,b.dim,b.dim),(b.x,b.y,size,size))

    fps = font.render('FPS: ' + str(int(clock.get_fps())), 1, (0, 0, 0))
    gameDisplay.blit(fps, (20, 20))

    pygame.display.update()
    clock.tick(120)
    gameDisplay.fill(black)

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Как объяснил @sloth, есть лучшие способы сделать то же самое, но если вы хотите знать, каковы реальные проблемы:

  • Вы не рисуете 2000 прямоугольников, выВы рисуете 10.000 из них, потому что ваше измерение составляет 100x100

  • Вы проверяете, виден ли прямоугольник в худшем виде с точки зрения производительности.Просто проверьте, что произойдет, если вы покинете чек и не будете рисовать прямоугольники.Вы увидите, что производительность улучшается, но она все еще далека от 120 кадров в секунду.Это потому, что для каждого прямоугольника вы генерируете список чисел от 0 до ширины экрана и другой список от нуля до высоты экрана.Вы также делаете это дважды.Это означает, что на экране 1920x1080: (1920 * 10000) + (1920 * 10000) + (1080 * 10000) + (1080*10000) = 60000000.Итак, 60 миллион чеков.Если у вас 120fps, это означает, что 60 миллионов * 120 = 7,2 миллиардов проверок в секунду.

Простое изменение проверки на что-то похожее на if b.x+size < display_width and b.y+size < display_height and b.x > 0 and b.y > 0: уже улучшитпроизводительность.

Тем не менее, это все еще 10000 прямоугольников, и это все еще 120 кадров в секунду, что означает 1200000 прямоугольников в секунду, и это практически без ускорения HW и с языком высокого уровня.Не ожидайте максимальной производительности.

0 голосов
/ 11 октября 2018

Вместо того, чтобы рисовать все эти линии на экране каждый тик, создайте Поверхность с шумом один раз и используйте ее снова.

Еще несколько примечаний:

Текстрендеринг дорогой.Если вы используете много рендеринга текста, лучше кэшируйте поверхности, созданные Font.render.Обратите внимание, что в Pygame есть также новый модуль freetype, который лучше, чем модуль font во всех отношениях.

Ваша проверка на наличие прямоугольника внутри экрана очень странная.Вы можете просто использовать что-то вроде if 0 < b.x < display_width ... или даже использовать класс Rect в Pygame, который предлагает хорошие методы, такие как contains().

Хороший и быстрый способ создания поверхности из произвольных данных - это использовать numpy и модуль surfarray Pygame.Не пугайтесь, это не так сложно использовать.

Вот пример, основанный на вашем коде:

import pygame
import numpy as np

black = (0,0,0)
pygame.init()
display_width = 1000
display_height = 1000
gameDisplay = pygame.display.set_mode((display_width, display_height))
gameDisplay.fill(black)
clock = pygame.time.Clock()

from opensimplex import OpenSimplex
tmp = OpenSimplex()

dimensions = [100,100]
size = 16

def mapping(x):
    y = (x + 1) * 10 + 40
    return y

# create an 2d array from the noise
def get_array():
    rgbarray = np.zeros((dimensions[0], dimensions[1]))
    for x in range(dimensions[0]):
        for y in range(dimensions[1]):
            c = int(mapping(tmp.noise2d(x*0.11, y*0.11)))
            # simple way to convert the color value to all three (r,g,b) channels
            rgbarray[x, y] = c | c << 8 | c << 16 
    return rgbarray

# create the array and copy it into a Surface
data = get_array()
surface = pygame.Surface((dimensions[0], dimensions[1]))
pygame.surfarray.blit_array(surface, data)

# scale the Surface to the desired size
scaled = pygame.transform.scale(surface, (dimensions[0]*size, dimensions[1]*size))

# simple way to cache font rendering
font = pygame.font.Font("freesansbold.ttf", 20)
cache = {}
def render(text):
    if not text in cache:
        cache[text] = font.render(text, 1, (0, 0, 0))
    return cache[text]

x = 0
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False

    x-=1
    if x < -1000:
        x = 0

    gameDisplay.blit(scaled, (x, 0))
    fps = render('FPS: ' + str(int(clock.get_fps())))
    gameDisplay.blit(fps, (20, 20))
    pygame.display.update()
    clock.tick(120)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...