繁体   English   中英

较低的帧频,可能是因为图形未加速

[英]Low frame rate, possibly because un-accelerated graphics

因此,几个月前,我开始使用pygame创建游戏,它的俯视图类似于《星际争霸》,《帝国时代》等。我编写了约1320行代码来创建游戏基础。 但是,我在给图像加斑点时遇到帧速率问题,并且认为这是因为我无法在pygame中使用加速图形。 我目前对图像进行格斗的方式是提前在表面上对所有图像进行格斗,然后我将其地下化以创建整个屏幕的图像。 我应该使用一种更有效的方法吗?

因此,我的假设是,这将使您一团糟,而且我不想浪费您的时间。 基本上,每当我遮盖屏幕大小的表面时,帧率就会下降约20帧,是否有办法在pygame中避免这种情况?

    ##PYGAME INITATE##
import pygame, os
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()

_W,_H = pygame.display.Info().current_w, pygame.display.Info().current_h
flags = pygame.DOUBLEBUF | pygame.HWSURFACE
gameDisplay = pygame.display.set_mode((_W,_H),pygame.FULLSCREEN ) ## CREATES SCREEN YOU DISPLAY ON ##
gameDisplay.fill((0,0,0)) ## FILL COLOR OF SCREEN ##
pygame.display.set_caption("Dope Game")  ## SETS NAME ##
gameClock = pygame.time.Clock() ## CLOCK OF THE GAME ##
import math
import os
import random
import copy


SQRT = math.sqrt
PI = math.pi
cos = math.cos
sin = math.sin


## REPEATABLE FUNCTIONS ##

def loadScale(file,command,sizeX,sizeY):
    temp = pygame.image.load(file)
    tempInfo = temp.get_rect()
    tempInfo1,tempInfo2,tempInfo3,tempInfo4 = temp.get_rect()
    tempInfo3 = int(tempInfo3)
    tempInfo4 = int(tempInfo4)
    if (command == "ratio"):    
        tempInfo3 = tempInfo3*sizeX
        tempInfo4 = tempInfo4*sizeY
        temp = pygame.transform.scale(temp,(int(tempInfo3),int(tempInfo4) ) )

    elif (command == "size"):
        temp = pygame.transform.scale(temp, (sizeX,sizeY) )         

    return(temp)

## NON GAME RELATED CLASSES ##

class EnterFrame():
    def __init__(self,frameReset,function,parse,reset):
        self.frameReset = frameReset
        self.currentFrame = frameReset
        self.function = function
        self.parse = parse
        self.reset = reset
        if (self.reset != "onComplete"):
            self.reset = (reset-1)
        enterFrameTable.append(self)

    def step(self,enterFrameTable):
        if (self.currentFrame == 0):
            self.function(self.parse)
            if (self.reset != "onComplete"):
                if (self.reset > 0): 
                    self.currentFrame = self.frameReset
                    self.reset = self.reset-1
                else:
                    enterFrameTable.remove(self)
                    del self
            else:
                self.currentFrame = self.frameReset
        else:
            self.currentFrame = self.currentFrame-1

class PlayerCreation():
    def __init__(self): 
        self.x = _W
        self.y = _H
        self.view = [1600,1600]
        self.viewShift = []
        self.viewChangeSpeed = 25

    def moveView(self,key):
        add = EnterFrame(0,self.moveViewAction,key,"onComplete")
        self.viewShift.append([add,key])

    def moveViewAction(self,key):
        if (key == "up"):
            self.view[1] = self.view[1]-self.viewChangeSpeed
            Map.recenterView()
            if (self.view[1] < 0):
                self.view[1] = 0

        elif (key == "right"):
            self.view[0] = self.view[0]+self.viewChangeSpeed
            Map.recenterView()
            if (self.view[0] > Map.tileSize*4):
                self.view[0] = Map.tileSize*4


        elif (key == "down"):
            self.view[1] = self.view[1]+self.viewChangeSpeed
            Map.recenterView()
            if (self.view[1] > Map.tileSize*4):
                self.view[1] = Map.tileSize*4


        elif (key == "left"):
            self.view[0] = self.view[0]-self.viewChangeSpeed
            Map.recenterView()
            if (self.view[0] < 0):
                self.view[0] = 0

    def endMoveView(self,key):
        for i in range(len(self.viewShift)-1,-1,-1 ):
            if (self.viewShift[i][1] == key):
                enterFrameTable.remove(self.viewShift[i][0])
                del self.viewShift[i]               

class ImageCreation():
    def __init__(self,name,image,type,hitBox):
        self.name = name
        self.image = image
        self.type = type
        self.hitBox = hitBox
        self.rect = self.image.get_rect()
        if (self.hitBox != "none"):
            self.shiftX = hitBox[0][0]
            self.shiftY = hitBox[0][1]
            for i in range(1,len(hitBox) ):
                if (hitBox[i][0] < self.shiftX):
                    self.shiftX = hitBox[i][0]

                if (hitBox[i][1] < self.shiftY):
                    self.shiftY = hitBox[i][1]

        else:
            self.shiftX = self.rect[2]/2
            self.shiftY = self.rect[3]/2

        imageTable.append(self)

    def draw(self,x,y):
        image = self.image
        self.blit = gameDisplay.blit(image,(x,y) )

class MapCreation():
    def __init__(self):
        self.tileSize = 800
        self.size = self.tileSize*10
        self.tiles = []
        self.loadedTiles = []
        self.surface = pygame.Surface([self.tileSize*5,self.tileSize*5], pygame.SRCALPHA, 32) 
        self.centerTile = [5,5] 
        self.drawPoint = [(_W-self.tileSize)/2,(_H-self.tileSize)/2]
        self.amount = round(self.size/self.tileSize)

        backGround = loadScale("Grass.png","size",self.tileSize,self.tileSize)
        for i in range(0,self.amount):
            for u in range(0,self.amount):
                image = copy.copy(backGround)
                newTile = Tile(image,[u*self.tileSize,i*self.tileSize])
                self.tiles.append(newTile)



        info = imageFind("House.png")
        tile = self.tiles[55]
        imageObject(info,tile,[240,50])

        self.loadTiles("center")

    def recenterView(self):

        if (Player.view[0] > 3*self.tileSize):
            self.centerTile[0] = self.centerTile[0]+1
            Player.view[0] = Player.view[0]-self.tileSize
            self.loadTiles("right")
            print("right")

        elif (Player.view[0] < 1*self.tileSize):
            self.centerTile[0] = self.centerTile[0]-1
            Player.view[0] = Player.view[0]+self.tileSize
            self.loadTiles("center")
            print("center")


        if (Player.view[1] > 3*self.tileSize):
            self.centerTile[1] = self.centerTile[1]+1
            Player.view[1] = Player.view[1]-self.tileSize
            self.loadTiles("center")
            print("center")


        elif (Player.view[1] < 1*self.tileSize):
            self.centerTile[1] = self.centerTile[1]-1
            Player.view[1] = Player.view[1]+self.tileSize
            self.loadTiles("center")
            print("center")


    def loadTiles(self,load):
        tileIndex = self.centerTile[0]+self.centerTile[1]*self.amount
        if (load == "center"):
            self.loadedTiles = []
            for i in range(-2,3):
                for u in range(-2,3):
                    loadTile = tileIndex + i*self.amount + u
                    self.loadedTiles.append(self.tiles[loadTile])
                    self.tiles[loadTile].loaded = [u+2,i+2]

            self.surface = pygame.Surface([self.tileSize*5,self.tileSize*5], pygame.SRCALPHA, 32)       

            for i in range(0,len(self.loadedTiles) ):           
                sx = self.loadedTiles[i].loaded[0]*self.tileSize
                sy = self.loadedTiles[i].loaded[1]*self.tileSize
                self.surface.blit(self.loadedTiles[i].buttomLayer,(sx,sy) )


            for i in range(0,len(self.loadedTiles) ):           
                sx = self.loadedTiles[i].loaded[0]*(self.tileSize+2)
                sy = self.loadedTiles[i].loaded[1]*(self.tileSize+2)
                self.surface.blit(self.loadedTiles[i].middleLayer,(sx,sy) )

            for i in range(0,len(self.loadedTiles) ):           
                sx = self.loadedTiles[i].loaded[0]*(self.tileSize+2)
                sy = self.loadedTiles[i].loaded[1]*(self.tileSize+2)
                self.surface.blit(self.loadedTiles[i].topLayer,(sx,sy) )

        elif (load == "right"):
            self.loadedTiles = []
            for i in range(-2,3):
                for u in range(-2,3):
                    loadTile = tileIndex + i*self.amount + u
                    self.loadedTiles.append(self.tiles[loadTile])
                    self.tiles[loadTile].loaded = [u+2,i+2]

            ## OLD METHOD THAT WASNT WORKING ##
            ##subSurf = self.surface.subsurface(self.tileSize,0,self.tileSize*1,self.tileSize*5)
            ##self.surface = pygame.Surface([self.tileSize*5,self.tileSize*5], pygame.SRCALPHA, 32)
            ##self.surface.blit(subSurf,(0,0) )

            ## NEW METHOD ##
            self.surface.scroll(dx=-self.tileSize*1,dy=0)

    def draw(self):
        global Player       
        image = self.surface.subsurface(Player.view[0],Player.view[1],self.tileSize,self.tileSize)      
        image = pygame.transform.scale(image,(self.tileSize,self.tileSize) )
        gameDisplay.blit(image,((_W-self.tileSize)/2,(_H-self.tileSize)/2) )
        image = pygame.transform.scale(self.surface,(300,300) )
        gameDisplay.blit(image,(0,0 ) )

class Tile():
    def __init__(self,image,coords):
        transparentSurface = pygame.Surface([1000,1000], pygame.SRCALPHA, 32)
        self.x = coords[0]
        self.y = coords[1]
        self.loaded = False
        self.buttomLayer = image
        self.middleLayer = copy.copy(transparentSurface)
        self.topLayer = transparentSurface      

class imageObject():
    def __init__(self,info,tile,coords):
        self.info = info
        self.image = info.image
        self.rect = self.image.get_rect()

        self.x = coords[0]
        self.y = coords[1]

        self.hitBox = []

        if (self.info.hitBox != "none"):
            for i in range(0,len(self.info.hitBox) ):
                self.hitBox.append([self.info.hitBox[i][0]+self.x,self.info.hitBox[i][1]+self.y])
        #self.object = createObject(self.hitBox,True,"none")

        if (info.type == "background"):
            tile.buttomLayer.blit(self.image,(self.x,self.y) )
        if (info.type == "object"):
            tile.middleLayer.blit(self.image,(self.x,self.y) )
        if (info.type == "object alphas"):
            tile.topLayer.blit(self.image,(self.x,self.y) )


def imageFind(name):
    for i in range(0,len(imageTable) ):
        if (name == imageTable[i].name):
            return(imageTable[i])

    return("none") 

def imageLoad(types):
    if (types == "basic"):
        image = loadScale("House.png","ratio",1,1)
        basicHouse = ImageCreation("House.png",image,"object",[[190, 375], [350, 375], [350, 235], [190, 235]])

        image = loadScale("Grass.png","ratio",1,1)
        grass = ImageCreation("Grass.png",image,"background","none")

def enterFrameHandle(enterFrameTable): 
    for i in range(len(enterFrameTable)-1,-1,-1 ):
        enterFrameTable[i].step(enterFrameTable)

def EventHandle(event):
    global Player

    if (event.type == pygame.QUIT):
        endGame()

    elif(event.type == pygame.KEYDOWN):
        key = (pygame.key.name(event.key) )

        if (key == "escape"):
            endGame()       

        elif (key == "up" or key == "right" or key == "down" or key == "left"):
            Player.moveView(key)

    elif(event.type == pygame.KEYUP):
        key = (pygame.key.name(event.key) )
        if (key == "up" or key == "right" or key == "down" or key == "left"):
            Player.endMoveView(key)

def endGame():
    global QuitGame
    QuitGame = True

def mainLoop(): 

    ## GLOBALS ##
    global QuitGame
    QuitGame = False

    global Player
    Player = PlayerCreation()

    ## MAIN TABLES ##
    global enterFrameTable
    enterFrameTable = []

    global basicObjectTable
    basicObjectTable = []

    ## TEMP TABLES ##
    global imageTable
    imageTable = []


    ## START UP LOOPS ##

    imageLoad("basic")
    global Map
    Map = MapCreation()

    ## Temporary ##

    while (QuitGame == False):
        enterFrameHandle(enterFrameTable)
        for event in pygame.event.get():
            EventHandle(event)


        Map.draw()
        pygame.display.update() ## updates the screen ##

        gameDisplay.fill([0,0,0]) ## Clears screen for next frame ##
        gameClock.tick(64) ## The FPS ##
        fps = gameClock.get_fps()
        if (fps < 64 and fps != 0):
            fps = gameClock.get_fps()
            print("FPS HAS DROPPED TOO LOW DOWN TO",fps)


runGameNow = True

mainLoop()
pygame.quit()
quit()

寻找路径的问题是由于在寻找最近的点时在迭代线上进行选择

这个问题确实很直接。
您认为行数是疾病,原因必须是Pygame。 通常,或者至少在几乎任何情况下,如果您不是使用语言和库的神,那么问题可能出在语言或库之外。 因为很有可能,您几乎无法突破两者可以为您提供的服务的极限。
这一事实的致命一面是,如果您看一下屏幕上的眼睛,您会很快注意到,只要背景即将循环-那便是出现毛刺/帧下降的时候。 显然,这可能是导致库执行可疑操作的原因。

但是在您的代码中,这是您自己完成的实现。
所以最好的选择就是开始寻找。
为了对延迟发生的位置非常有信心-我们可以看一下Python附带的探查器(cProfiler)。

python -m cProfile -o sample_data.pyprof awesome_game.py
pyprof2calltree -i sample_data.pyprof -k

结果将显示以下内容: 在此处输入图片说明

从中我们可以看到pygame.SurfaceenterFrameHandle有很多处理时间。 我打赌pygame.SurfaceenterFrameHandle被调用。

因此,最好的选择是从eventFrameHandle链的末尾开始。
在此细分中,这就是loadTiles

马上,这里有很多警告标志。
这里至少有四个循环..循环不好,因为这些循环需要处理时间。

我通过简单地添加调试信息:

def loadTiles
    if load == "center":
        print('Loading center')
    elif load == "right":
        print('Loading right')

显然,只要出现毛刺, center就会触发。
这样可以将范围进一步缩小。 所以我在每个for循环周围添加了计时器。

  • 循环一:耗时0.0秒
  • 循环二:耗时0.29秒
  • 循环三:耗时0.5秒
  • 循环四:耗时0.6秒

总而言之,这些对您非常不利,因为它们直接影响渲染序列。 那为什么呢? 让我们进一步分解。
我们将从耗时0.3秒的第一个循环开始:

for i in range(0,len(self.loadedTiles) ):           
    sx = self.loadedTiles[i].loaded[0]*self.tileSize
    sy = self.loadedTiles[i].loaded[1]*self.tileSize
    self.surface.blit(self.loadedTiles[i].buttomLayer,(sx,sy) )

因此len(self.loadedTiles)将为25
这意味着该循环必须在每个渲染周期内迭代25次,其中调用loadTiles("center")

每个周期几乎精确地花费0.01秒,每个完整循环最多需要0.25秒。 如果您希望游戏中达到60 FPS,则没有循环或函数调用的时间可能不超过0.0166秒。

因此,我们已经超出了我们期望的FPS目标。 因此,如果我们想到达任何地方,我们必须把它缩短几毫秒。

循环本身并没有那么糟糕,我的意思是说有25次迭代,现代PC可以用比time()可以测量的time()更少的时间来做到这一点。 因此,所有这些都指向self.surface.blit()
这也与以下事实相关:上面的图表在pygame.surface.blit花费了总CPU时间的30%。因此,这是我们的第一个小偷。

观察其余的循环,它们基本上是相同的,只是数学中的数字较大,计算所需的时间稍长一些,因此可能是循环中的时间差。

那么,我们该怎么做才能缩短.blit时间呢?
好了,我们可以在每次循环迭代中停止调用blit,而只需移动sprite对象的位置,然后将它们逐个blit。
但是,老师,那几乎是同一回事?
好吧,是的,我很快就要成为忍者神龟了,这就是为什么。我们将精灵移动到批处理/组中,然后渲染组。 因此,我们可以更改位置(快速操作),并且因为我们将渲染移到了循环之外,所以我们也可以将它们转换为组对象并渲染组。

首先,我们将您的对象转换为pygame.sprite.Sprite ,这些都是聪明的小对象,包含碰撞检测, 四处走动等。

self.grass = pygame.sprite.Sprite()
self.grass.image = pygame.image.load("Grass.png")
self.grass.rect = pygame.Rect(0, 0, 60, 60)

然后将其添加到渲染组(批处理)中:

self.main_group = pygame.sprite.Group(self.grass)

Bam,而不是更新25个Sprite,现在您可以执行以下操作:

self.main_group.draw(gameDisplay)

哎呀,速度!

现在,您的代码不是为此设计的。
因此,将需要一些时间来修复和纠正此设计缺陷。
因为MapCreation您的原始代码尽可能地接近我需要花费几个小时,所以我忽略了这一点,并重新设计了整个MapCreation并修改了PlayerCreation以及如何移动地图(我每次都从尝试更改为更新,一个好主意,但是要实现1PM重写别人的代码要复杂得多。.....这是解决问题的新方法:

import pygame, os
from time import time
from collections import OrderedDict
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()

_W,_H = pygame.display.Info().current_w, pygame.display.Info().current_h
flags = pygame.DOUBLEBUF | pygame.HWSURFACE | pygame.RESIZABLE
gameDisplay = pygame.display.set_mode((500, 500))
gameDisplay.fill((0,0,0)) ## FILL COLOR OF SCREEN ##
pygame.display.set_caption("Dope Game")  ## SETS NAME ##
gameClock = pygame.time.Clock() ## CLOCK OF THE GAME ##
import math
import os
import random
import copy


SQRT = math.sqrt
PI = math.pi
cos = math.cos
sin = math.sin


## REPEATABLE FUNCTIONS ##

def loadScale(file,command,sizeX,sizeY):
    temp = pygame.image.load(file)
    tempInfo = temp.get_rect()
    tempInfo1,tempInfo2,tempInfo3,tempInfo4 = temp.get_rect()
    tempInfo3 = int(tempInfo3)
    tempInfo4 = int(tempInfo4)
    if (command == "ratio"):    
        tempInfo3 = tempInfo3*sizeX
        tempInfo4 = tempInfo4*sizeY
        temp = pygame.transform.scale(temp,(int(tempInfo3),int(tempInfo4) ) )

    elif (command == "size"):
        temp = pygame.transform.scale(temp, (sizeX,sizeY) )         

    return(temp)

## NON GAME RELATED CLASSES ##

class EnterFrame():
    def __init__(self,frameReset,function,parse,reset):
        self.frameReset = frameReset
        self.currentFrame = frameReset
        self.function = function
        self.parse = parse
        self.reset = reset
        if (self.reset != "onComplete"):
            self.reset = (reset-1)
        enterFrameTable.append(self)

    def step(self,enterFrameTable):
        if (self.currentFrame == 0):
            self.function(self.parse)
            if (self.reset != "onComplete"):
                if (self.reset > 0): 
                    self.currentFrame = self.frameReset
                    self.reset = self.reset-1
                else:
                    enterFrameTable.remove(self)
                    del self
            else:
                self.currentFrame = self.frameReset
        else:
            self.currentFrame = self.currentFrame-1

class PlayerCreation():
    def __init__(self): 
        self.x = _W
        self.y = _H
        self.view = [1600,1600]
        self.viewShift = []
        self.viewChangeSpeed = 25

    def moveView(self,key):
        add = EnterFrame(0,self.moveViewAction,key,"onComplete")
        self.viewShift.append([add,key])

    def moveViewAction(self,key):
        if (key == "up"):
            self.view[1] = self.view[1]-self.viewChangeSpeed
            Map.move_tile(0, 1) # Player moves up, so the tiles should move down ->  (0, 1) == (x, y)
            if (self.view[1] < 0):
                self.view[1] = 0

        elif (key == "right"):
            self.view[0] = self.view[0]+self.viewChangeSpeed
            Map.move_tile(-1, 0)
            if (self.view[0] > Map.tileSize*4):
                self.view[0] = Map.tileSize*4

        elif (key == "down"):
            self.view[1] = self.view[1]+self.viewChangeSpeed
            Map.move_tile(0, -1)
            if (self.view[1] > Map.tileSize*4):
                self.view[1] = Map.tileSize*4

        elif (key == "left"):
            self.view[0] = self.view[0]-self.viewChangeSpeed
            Map.move_tile(1, 0) 
            if (self.view[0] < 0):
                self.view[0] = 0

    def endMoveView(self,key):
        for i in range(len(self.viewShift)-1,-1,-1 ):
            if (self.viewShift[i][1] == key):
                enterFrameTable.remove(self.viewShift[i][0])
                del self.viewShift[i]               

class ImageCreation():
    def __init__(self,name,image,type,hitBox):
        self.name = name
        self.image = image
        self.type = type
        self.hitBox = hitBox
        self.rect = self.image.get_rect()
        if (self.hitBox != "none"):
            self.shiftX = hitBox[0][0]
            self.shiftY = hitBox[0][1]
            for i in range(1,len(hitBox) ):
                if (hitBox[i][0] < self.shiftX):
                    self.shiftX = hitBox[i][0]

                if (hitBox[i][1] < self.shiftY):
                    self.shiftY = hitBox[i][1]

        else:
            self.shiftX = self.rect[2]/2
            self.shiftY = self.rect[3]/2

        imageTable.append(self)

    def draw(self,x,y):
        image = self.image
        self.blit = gameDisplay.blit(image,(x,y) )

class MapCreation():
    def __init__(self):
        self.tileSize = 800
        self.size = self.tileSize*10
        self.tiles = []
        self.centerTile = [5,5] 
        self.amount = round(self.size/self.tileSize)

        self.sprites = OrderedDict()
        self.grass_image = pygame.image.load("Grass.png")
        self.grass_group = pygame.sprite.Group()

        for x in range(0, self.amount*60, 60):      ## 10*60, but we step 60 pixels, so in the end, this will be 10 steps.
            for y in range(0, self.amount*60, 60):  ## Which is the same as `for x in range(self.amount)` but we scale it up
                                                    ## to give us pixels instead of just the ammount.
                index = len(self.sprites) # -- Generate a index for this sprite. Used for access later (to update pos for instace)

                ## == Create the sprite, add a image to it and define a position and size.
                self.sprites[index] = pygame.sprite.Sprite()
                self.sprites[index].image = self.grass_image
                self.sprites[index].rect = pygame.Rect(x, y, 60, 60)

                ## == Then add the sprite to the grass group.
                self.grass_group.add(self.sprites[index])

    def move_tile(self, dx, dy):
        for index in self.sprites:
            x, y, width, height = self.sprites[index].rect
            ## == this is how you move the sprites:d
            self.sprites[index].rect = pygame.Rect(x+dx, y+dy, 60, 60)

    def draw(self):
        self.grass_group.update()
        self.grass_group.draw(gameDisplay)

class Tile():
    def __init__(self,image,coords):
        transparentSurface = pygame.Surface([1000,1000], pygame.SRCALPHA, 32)
        self.x = coords[0]
        self.y = coords[1]
        self.loaded = False
        self.buttomLayer = image
        self.middleLayer = copy.copy(transparentSurface)
        self.topLayer = transparentSurface      

class imageObject():
    def __init__(self,info,tile,coords):
        self.info = info
        self.image = info.image
        self.rect = self.image.get_rect()

        self.x = coords[0]
        self.y = coords[1]

        self.hitBox = []

        if (self.info.hitBox != "none"):
            for i in range(0,len(self.info.hitBox) ):
                self.hitBox.append([self.info.hitBox[i][0]+self.x,self.info.hitBox[i][1]+self.y])
        #self.object = createObject(self.hitBox,True,"none")

        if (info.type == "background"):
            tile.buttomLayer.blit(self.image,(self.x,self.y) )
        if (info.type == "object"):
            tile.middleLayer.blit(self.image,(self.x,self.y) )
        if (info.type == "object alphas"):
            tile.topLayer.blit(self.image,(self.x,self.y) )


def imageFind(name):
    for i in range(0,len(imageTable) ):
        if (name == imageTable[i].name):
            return(imageTable[i])

    return("none") 

def imageLoad(types):
    if (types == "basic"):
        image = loadScale("House.png","ratio",1,1)
        basicHouse = ImageCreation("House.png",image,"object",[[190, 375], [350, 375], [350, 235], [190, 235]])

        image = loadScale("Grass.png","ratio",1,1)
        grass = ImageCreation("Grass.png",image,"background","none")

def enterFrameHandle(enterFrameTable): 
    for i in range(len(enterFrameTable)-1,-1,-1 ):
        enterFrameTable[i].step(enterFrameTable)

def EventHandle(event):
    global Player

    if (event.type == pygame.QUIT):
        endGame()

    elif(event.type == pygame.KEYDOWN):
        key = (pygame.key.name(event.key) )

        if (key == "escape"):
            endGame()       

        elif (key == "up" or key == "right" or key == "down" or key == "left"):
            Player.moveView(key)

    elif(event.type == pygame.KEYUP):
        key = (pygame.key.name(event.key) )
        if (key == "up" or key == "right" or key == "down" or key == "left"):
            Player.endMoveView(key)

def endGame():
    global QuitGame
    QuitGame = True

def mainLoop(): 

    ## GLOBALS ##
    global QuitGame
    QuitGame = False

    global Player
    Player = PlayerCreation()

    ## MAIN TABLES ##
    global enterFrameTable
    enterFrameTable = []

    global basicObjectTable
    basicObjectTable = []

    ## TEMP TABLES ##
    global imageTable
    imageTable = []


    ## START UP LOOPS ##

    imageLoad("basic")
    global Map
    Map = MapCreation()

    ## Temporary ##

    while (QuitGame == False):
        enterFrameHandle(enterFrameTable)
        for event in pygame.event.get():
            EventHandle(event)


        pygame.display.update() ## updates the screen ##
        gameDisplay.fill([0,0,0]) ## Clears screen for next frame ##

        #Map.draw()
        Map.grass_group.update()
        Map.grass_group.draw(gameDisplay)

        gameClock.tick(64) ## The FPS ##
        fps = gameClock.get_fps()
        if (fps < 64 and fps != 0):
            fps = gameClock.get_fps()
            print("FPS HAS DROPPED TOO LOW DOWN TO",fps)

        pygame.display.flip()


runGameNow = True

mainLoop()
pygame.quit()
quit()

此代码很少在FPS中显示。
这样做的时候,它下降到〜63 FPS,因为我移动了窗口(这很麻烦,因为所有OpenGL引用都需要补偿新的窗口位置和在Pygame中触发的事件(调整大小,移动事件)。等等会增加负担,但发生一次,而不是每个渲染循环都可以。.因此是可以接受的)。

结论

  1. 该库很少会因为性能降低而出故障。
  2. 停止思考作为开发人员的一秒钟,然后观察屏幕,看看是否可以找到故障的根源。 在这种情况下,每次瓷砖围绕屏幕边缘旋转时都会出现明显的毛刺 。这是一个提示! 直观地看到此bug不需要任何编程技能。
  3. 使用探查器并调试您的代码大部分时间都花在哪里。
  4. 尝试查看其他人如何解决游戏设计。通过将所有内容放在类中,您处于正确的轨道上,但这在很大程度上有助于提高代码的可读性-尝试查看其他人类中的内容以及他们如何使用Pygame调用。

总而言之,这是一个非常有趣且不错的代码。
它不是为了性能而设计的,以后很难编写代码了。所以也许从头开始并不是一个坏主意吗? 但是,请保留旧的代码库以供参考,并避免明显的陷阱:

  • 渲染序列中的循环
  • 逐一渲染对象,改为使用批处理
  • 仅循环更新位置/统计信息,而不更新图形!

关于该主题的最后说明:图形卡是巨大的动力源。 他们每秒可以计算几百万次操作,如果不是更多的话。 而且,每当您在屏幕上blit某些东西时,图形卡都需要中断其计算和内存分配,以翻转缓冲区并更新您在屏幕上看到的内容。这是一项很慢的工作,因为它不是计算,而是操作任务(通常因此,与其向图形卡扔几百个blit ', blit向其发送纹理(算术数据描述事物的外观),对其进行数学运算。.然后调用blitdraw , (在这种情况下)一次,然后让图形卡进行所有数学运算-进行一次大的逻辑运算-并预先保存.x100的速度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM