需要有关优化python 2d tileset呈现的建议​​

时间:2016-12-30 23:19:14

标签: python loops optimization render tile

我已经在基于2D等距磁贴的MORPG上工作了几个月,并意识到我的游戏画面渲染的帧速率非常低。 我现在已经进行了几周的研究和测试,并且只能在我的帧速率上获得微小的收益。我已经使用了cProfile并测试了我的帧率,我可以正常地在程序上达到100+ FPS,但是一旦我的" render()"函数被称为降至5 FPS。 这是该函数的(有点)浓缩版本:

for y in range(0, 42):
        for x in range(0, 42):
            if (player.mapY + y - 21 > 0) and (player.mapY + y - 21 < 128) and (player.mapX + x - 21 > 0) and (
                                player.mapX + x - 21 < 128):
                if (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) > -64 and (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX)+halfGraphicSizeX < 1024+32 and\
                    (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY) > -32 and (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY)+halfGraphicSizeY < 600+32:
                    if self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21)) is not 0:

                        canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY),
                                            image=groundGraphics[
                                                self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21))],
                                            anchor=NW)

                    if (self.getObjectAtYX(player.mapY + (y - 21), player.mapX + (x - 21)) is not 0):
                        canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
                                            # -34 for img height diff between ground & objects
                                            image=objectGraphics[
                                                self.getObjectAtYX(player.mapY + (y - 21), player.mapX + (x - 21))],
                                            anchor=NW)


            ghostCopy = list(gameState.itemsOnGround)
            for i in range(0, len(ghostCopy)):
                if ghostCopy[i].idNum > 0:
                    if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
                        ghostCopy[i].mapY):
                        canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY),
                                            image=itemGraphics[ghostCopy[i].idNum],
                                            anchor=NW)

            ghostCopy = ""
            ghostCopy = list(gameState.monster)
            for i in range(0, len(ghostCopy)):
                if ghostCopy[i].active == True and ghostCopy[i].hp > 0:
                    if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
                        ghostCopy[i].mapY):
                        canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
                                            # -34 for img height diff between ground & objects
                                            image=monsterGraphics[ghostCopy[i].type],
                                            anchor=NW)
                        canvas.create_rectangle(
                            (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 15,
                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 35),
                            (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 16 + 33,
                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 29), fill="black",
                            width=0)
                        canvas.create_rectangle(
                            (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 16,
                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 30),
                            (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 16 + (
                                32 * (ghostCopy[i].hp / ghostCopy[i].maxHp)),
                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34), fill="green",
                            width=0)

            ghostCopy = ""
            ghostCopy = list(gameState.sprite)
            for i in range(0, len(ghostCopy)):
                if ghostCopy[i].graphic[0:1] == "0":

                if ghostCopy[i].active == True and ghostCopy[i].username != "ME":
                    if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
                        ghostCopy[i].mapY):
                        #"graphicToDraw" variable is derived from an animation state but has
                        #been removed from here to make it easier to read
                        canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
                                            # -34 for img height diff between ground & objects
                                            image=graphicToDraw,
                                            anchor=NW)

            if (y == 21):
                if (x == 21):
                    #"graphicToDraw" variable is derived from an animation state but has
                    #been removed from here to make it easier to read
                    canvas.create_image(
                        (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                        (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
                        # -34 for img height diff between ground & sprites
                        image=graphicToDraw,
                        anchor=NW)

            ghostCopy = ""
            ghostCopy = list(gameState.spells)
            for i in range(0, len(ghostCopy)):
                if ghostCopy[i].active:
                    if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
                        ghostCopy[i].mapY):
                        canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
                                            (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
                                            image=spellGraphics[ghostCopy[i].id],
                                            anchor=NW)

render()函数属于map对象(self是指此代码段中的地图)。它有效地穿过x,y轴上的图块-21 .. 21,如果图块在地图图块边界(0 ... 128)内并且图块在屏幕尺寸(1024x600)内,则将其绘制到屏幕上

&#34; ghostCopy&#34;获取当前gamestate元素(例如法术)的快照,以便线程接收服务器数据在迭代过程中不会更新。

在一些优化测试中,我在开始时减少了y,x范围,以最小化总循环迭代量。 我读到使用纹理图集/ spritesheet可以提高渲染速度,但我无法使用它进行改进。

我尝试手动绘制通常在for循环中的常规场景中渲染的图像数量,并获得大约30+ fps。所以我的渲染函数比它可能慢25 fps。

我假设常量检查每个循环迭代以确定是否在屏幕内是否可以优化,但我不确定如何在不使用这样的循环的情况下这样做。

如果有人有任何建议我会非常感激..我已经坚持这个问题好几个星期了,并且我的游戏根本没有取得任何真正的进展:(

** [编辑] ** 大多数建议似乎都是为了限制数学表达式的数量。我还没有机会对此进行测试,但可能只是限制数学量会大大优化帧率吗?

2 个答案:

答案 0 :(得分:0)

您可以在外部(y)循环内部计算所有涉及常量和for y的表达式;例如,player.mapY + y - 21y * halfGraphicSizeXy * halfGraphicSizeY等:计算机每次只需一次,插入变量,并在整个代码中使用。同样适用于x,但不太有效。

答案 1 :(得分:0)

以下是应该改善性能的前19行代码的更新。在这个例子中,我所做的就是减少你执行数学运算的总次数。

for y in range(0, 42):
    for x in range(0, 42):
        player_y = player.mapY + y - 21
        player_x = player.mapX + x -21

        if  player_y > 0 and player_y < 128 and player_x > 0 and player_x < 128:
            start_drawing_x_half_graphic_size = startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX
            start_drawing_y_half_graphic_size = startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY

            if start_drawing_x_half_graphic_size > -64 and start_drawing_x_half_graphic_size + halfGraphicSizeX < 1024+32 and\
                start_drawing_y_half_graphic_size > -32 and start_drawing_y_half_graphic_size + halfGraphicSizeY < 600+32:

                if self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21)) is not 0:

                    canvas.create_image(start_drawing_x_half_graphic_size,
                                        start_drawing_y_half_graphic_size,
                                        image=groundGraphics[
                                            self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21))],
                                        anchor=NW)