【问题标题】:Faster drawing in python pygame在 python pygame 中更快地绘图
【发布时间】:2018-02-23 16:38:15
【问题描述】:

我使用 Python 和 pygame 编写了一个程序,它加载材料图片,然后创建块,每个块都分配有随机材料。 Block 是一个类,在绘图过程中,它会遍历存储有块的数组,但这非常慢。难道没有比将它们存储在数组中并迭代更快的方法吗?

class block:
    def __init__(self, texture, x, y):
           self.texture = texture
           self.x = x
           self.y = y


material = pygame.image
material.grass = pygame.image.load("textures/grass.png")
material.water = pygame.image.load("textures/water.png")
material.sand = pygame.image.load("textures/sand.png")

materials = [material.grass, material.water, material.sand]



white = (255,255,255);(width, height) = (2048, 1008);black = (0, 0, 0);screen = pygame.display.set_mode((width, height))

b_unit = 16

b = []

count = 0
cx = 0
cy = 0
while count < (width * height) / (b_unit * b_unit):
    b.append(block(random.choice(materials), b_unit * cx, b_unit * cy))
    cx += 1
    count += 1
    if cx == width / b_unit:
        cx = 0
        cy += 1

while True:
    for block in b:
        screen.blit(block.texture, (block.x + viewx, block.y + viewy))
    pygame.display.flip()

【问题讨论】:

  • 始终转换您的图像:stackoverflow.com/a/48574695/6220679
  • 我没有看到任何真正的加速技巧可以做到。您可以使用元组减少类的开销。但是速度的加快不会很明显。它们是什么类型的图像(浮点数、字节)?在 blit 期间是否发生了转换?
  • 一直单独对块进行 Blitting 也会很慢。如果在游戏过程中背景没有改变,最好在程序启动时将背景blocks blit 到一个大表面上,然后每帧只对该背景表面进行一次blit。
  • @J. Bakker 它们是 16x16 png 图像
  • @skrx 好的,我该怎么做?

标签: python pygame


【解决方案1】:

我已经在 cmets 中提到,您应该(几乎)始终convert your images 以提高性能。

它还可以帮助将单独的图像/pygame.Surfaces blit 到一个大背景表面上,然后每帧只对该背景进行一次 blit。我在这里使用两个嵌套的 for 循环来获取坐标并随机对两个图像之一进行 blit。

如果我在这里使用单独的精灵 (5184),我会得到大约 120 fps,而对于这个单一背景图像,我会得到大约 430 fps。

当然,我只是在这里进行 blitting,在真正的游戏中,您可能必须将图块的矩形存储在列表中或使用 pygame 精灵和精灵组,例如实现碰撞检测或其他与地图相关的逻辑,所以帧率会更低。

import itertools

import pygame as pg
from pygame.math import Vector2


BLUE_IMAGE = pg.Surface((20, 20))
BLUE_IMAGE.fill(pg.Color('lightskyblue2'))
GRAY_IMAGE = pg.Surface((20, 20))
GRAY_IMAGE.fill(pg.Color('slategray4'))


def main():
    screen = pg.display.set_mode((1920, 1080))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()

    images = itertools.cycle((BLUE_IMAGE, GRAY_IMAGE))
    background = pg.Surface(screen.get_size())
    # Use two nested for loops to get the coordinates.
    for y in range(screen.get_height()//20):
        for x in range(screen.get_width()//20):
            # This alternates between the blue and gray image.
            image = next(images)
            # Blit one image after the other at their respective coords.
            background.blit(image, (x*20, y*20))
        next(images)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        # Now you can just blit the background image once
        # instead of blitting thousands of separate images.
        screen.blit(background, (0, 0))
        pg.display.set_caption(str(clock.get_fps()))
        pg.display.flip()
        clock.tick(1000)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

旁注:不要将图像添加到 pygame.image 模块(这根本没有意义)。

material = pygame.image
material.grass = pygame.image.load("textures/grass.png")

在同一行中写多个语句,用分号分隔真的很丑陋,并且会降低代码的可读性。

white = (255,255,255);(width, height) = (2048, 1008)

【讨论】:

    猜你喜欢
    • 2015-08-13
    • 2022-07-19
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 2012-03-05
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    相关资源
    最近更新 更多