【问题标题】:Pygame slow after python updatepython更新后Pygame变慢
【发布时间】:2017-12-18 19:57:47
【问题描述】:

我正在我的家用计算机上使用 pygame 制作一个 python 游戏,用于使用 python 3.6.3 和 pygame 1.9.3 运行的学校。在开发我的游戏时,我也在学校工作,它正常工作,只是像预期的那样慢,但是当我开始加载图像时,它随机选择图像并且没有在学校计算机而不是家用计算机上加载正确的图像(我认为这可能是由于数组的变化和加载它们)。我很快发现我在学校运行 python 3.5.3,然后在更新 python 和 pygame 时,游戏运行非常慢并且无法玩。图像加载正确,但速度变化很大。

总结:

Pygame 在家工作很棒 pygame 1.9.3 python 3.6.3。 在学校工作正常,直到加载图像 python 3.5.3。 更新学校纠正了它,但现在运行缓慢。

我很想解决这个问题,无论是在其他 python 版本上工作还是在学校计算机上以可变速度运行。 如果有任何可以轻松实现的优化,那将非常有用,而且我不确定如何有效地加载图像

代码:

导入 pygame 随机导入 导入数学

def main():

    #load images?:
    bg = pygame.image.load("background6.png")

    wall = 100
    zombies = []
    currentnumber = 0
    gamepaused = False

    moveupx = False
    movedownx = False
    moveupy = False
    movedowny = False

    movex = 0
    movey = 0



    movespeed = 10
    time10 = False

    white = (255, 255, 255)
    black = (0, 0, 0)
    red = (255, 0, 0)
    blue = (0, 0, 255)
    fullscreen = pygame.FULLSCREEN



    pygame.init()
    pygame.font.init()
    myfont = pygame.font.SysFont('Comic Sans MS', 100)

    clock = pygame.time.Clock()
    clock.tick(30)

    #creating sprite groups
    heads = pygame.sprite.Group()
    bodys = pygame.sprite.Group()
    bullets = pygame.sprite.Group()
    allsprites = pygame.sprite.Group()
    players = pygame.sprite.Group()

    playerr = Player()
    allsprites.add(playerr)
    players.add(playerr)
    heads.add()
    bodys.add()



    gameDisplay = pygame.display.set_mode((1920, 1080), fullscreen)
    pygame.display.set_caption("Last Stand")

    gameExit = False

    pygame.display.update()
    #This will get the ticks from inisilising pygame in ms
    pretime = pygame.time.get_ticks()


    while not gameExit:
        time = pygame.time.get_ticks()-pretime
        #print (time/1000)
        timerounded = round(time/1000)
        timedisplay = round(time/1000,1)
        spawnbullet = False

        mouse = pygame.mouse.get_pos()

        # background things
        gameDisplay.fill(white)
        gameDisplay.blit(bg, (0, 0))

        if timerounded % 10 == 0:
            if timerounded != currentnumber:

                time10 = True
                currentnumber = timerounded

            else:
                time10 = False


        #start gameimput look e is event and it loops for each event in pygame
        #IT WILL GO THOUGH EACH EVEN!!!!!!! SO CHEACK FOR EACH EVENT
        for e in pygame.event.get():

            if e.type == pygame.MOUSEBUTTONDOWN:
                #so only if it will shoot foward NEED TO ADD FEEDBACK LATER
                if mouse[0] < 1500:
                    spawnbullet = True


            #so the problem is that if there is a key up for s then it would kill the key down for w as it would be set
            # to 0

            if e.type == pygame.KEYDOWN and e.key == pygame.K_w:
                moveupy = True
            if e.type == pygame.KEYDOWN and e.key == pygame.K_s:
                movedowny = True

            if e.type == pygame.KEYUP and e.key == pygame.K_w:
                moveupy = False
            if e.type == pygame.KEYUP and e.key == pygame.K_s:
                movedowny = False



            if e.type == pygame.KEYDOWN and e.key == pygame.K_a:
                moveupx = True
            if e.type == pygame.KEYDOWN and e.key == pygame.K_d:
                movedownx = True

            if e.type == pygame.KEYUP and e.key == pygame.K_a:
                moveupx = False
            if e.type == pygame.KEYUP and e.key == pygame.K_d:
                movedownx = False



            if e.type == pygame.QUIT:
                gameExit = True

            if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
                gameDisplay = pygame.display.set_mode((1920, 1080), fullscreen)
                gameExit = True
                # CAHNGE BACK LATER

        # END event loop

        #LOGIC FOR MOVING THE PLAYER:
        if moveupy == True:
            movey = -movespeed
        if movedowny == True:
            movey = movespeed
        if movedowny == False and moveupy == False:
            movey = 0

        if moveupx == True:
            movex = -movespeed
        if movedownx == True:
            movex = movespeed
        if movedownx == False and moveupx == False:
            movex = 0



        # Updating player have to do this at the start as need the angle and the top left cords
        for player in players:
            #REALLY NOT WOKRING THE MOVEX DOESNT WORK AND THE CHANGING HTE X AND WHY DOESNT WORK!!!

            player.move(movex, movey)
            angle, topleft = player.update(mouse)

        # needed another name for bullet so went for bullett
        if spawnbullet == True:
            bullett = Bullet(angle, topleft)
            #having the bullets only in the bullets class so it can render after the player
            bullets.add(bullett)

        #creating zombies
        if random.randint(0,2) == 1:
            ztype = "fast"
        else:
            ztype = "slow"

        #so at the start it spawns one for sure
        if time == 0:
            startlocation = [5, random.randint(320, 920)]

            zombies, heads, bodys = createz(zombies, ztype, startlocation, heads, bodys)


        if random.randint(0,10000) >9950-(timerounded**2): #So the time incraeed the odds expernetray
            startlocation = [5, random.randint(320, 920)]

            # WOULD LIKE THE ZOMBIES TO RUN FASTER AS THE GAME GOES ON!
            zombies, heads, bodys = createz(zombies, ztype, startlocation, heads, bodys)

        #updating Z

        zombies, totaldamnge  = updatez(zombies, heads, bodys)
        #updating bullets
        for bullet in bullets:
            bullet.update()

        #print(totaldamnge)
        wall -= totaldamnge
        #Cheacking for hitting bullets
        colstions(zombies, heads, bodys, bullets)

        if time10 == True:
            wall += 25
            if wall >100: wall = 100
        walltext = myfont.render(str(wall)+"%",False, (0, 0, 0))
        gameDisplay.blit(walltext,(1600,100))
        #print(wall)
        timedisplayer = myfont.render(str(timedisplay) + "Seconds", False, (0, 0, 0))
        gameDisplay.blit(timedisplayer, (10, 5))



        #drawing:
        #so cant use allsprites so might just wont have zomnbie head and zombie body in it

        #I CAN CHANGE WHEN WHAT IS DRAW AND WHAT IS ON WHAT
        bullets.draw(gameDisplay)
        allsprites.draw(gameDisplay)
        heads.draw(gameDisplay)
        bodys.draw(gameDisplay)


        pygame.display.update()

        clock.tick(30)

def colstions(zombies, heads, bodys, bullets):
    #so as having both hp and having the zombie having a head and body with 2 diffrent hitboxes
    headdamage = 140
    bodydamge = 60

    #so this part had sooooooo many proplems frist with like all the while loops next spend a long time trying to find what was wrong when it was just the head in bodys and vis versa


    if len(pygame.sprite.groupcollide(bullets, heads,False, False)) != 0 or len(pygame.sprite.groupcollide(bullets, bodys,False, False)) != 0:
        for bullet in bullets:
            hitthehead = False
            hitthebody = False
            zheadkilledzombie = False
            zbodykilledzombie = False
            counter1 = 0
            counter2 = 0
            for head in heads:
                #so it doesnt make the bullet hit more than one zombie head
                if hitthehead == False:
                    if pygame.sprite.collide_circle(bullet, head):
                        hp = zombies[counter1].hpordead(headdamage)
                        hitthehead = True
                        if hp <= 0:
                            zheadkilledzombie = True
                            head.kill()

                        print("hithead")
                counter1 += 1
            #so it doesnt check for body hits if it has hit a heah
            if hitthehead == False:
                for body in bodys:
                    if hitthebody == False:

                        #If it colldes and if the zombie is not already dead from the head shots
                        if pygame.sprite.collide_rect(bullet, body):
                            print("hitbody")
                            hp = zombies[counter2].hpordead(bodydamge)
                            hitthebody = True
                            if hp <= 0:

                                zbodykilledzombie = True
                                body.kill()
                    counter2 += 1

            if hitthehead == True or hitthebody == True:
                bullet.kill()
            #so killing the head if the body hit killed the zombie
            if zheadkilledzombie == True:
                zombiekilled = False
                counter3 = 0
                for body in bodys:
                    if zombiekilled == False:
                        hp = zombies[counter3].hpordead(0)
                        if hp <= 0:
                            body.kill()
                            zombies.pop(counter3)
                            zombiekilled = True
                        counter3 += 1

            #killing the body if killing is arealy dead
            if zbodykilledzombie == True:
                zombiekilled = False
                counter4 = 0
                for head in heads:
                    if zombiekilled == False:

                        hp = zombies[counter4].hpordead(0)
                        if hp <= 0:
                            head.kill()
                            zombies.pop(counter4)
                            zombiekilled = True
                        counter4 += 1




def createz(zombies, ztype, startlocation, heads, bodys, ):
    createdzombie = Zombie(startlocation, ztype)

    zombies.append(createdzombie)

    Hcords = (startlocation[0]+20, startlocation[1]-57)
    Bcords = (startlocation[0], startlocation[1])

    #need to have it also say what type of z it is.
    heads.add(head(Hcords,ztype))
    bodys.add(body(Bcords,ztype))


    print ("created")
    #dont think i need to return?
    return zombies, heads, bodys


def updatez(zombies, heads, bodys):
    totaldamnge = 0
    #somthing ent working
    Hcordsx = []
    Hcordsy = []
    Bcordsx = []
    Bcordsy = []
    ATWALLupdateanimationN = []



    for x in range(len(zombies)):


        cords, walldamge, updateanimationN = zombies[x].update()
        ATWALLupdateanimationN.append(updateanimationN)
        totaldamnge += walldamge

#putting all the cords into arrays just after reading them
        Hcordsx.append(cords[0]+ 20)
        Hcordsy.append(cords[1] - 57)

        Bcordsx.append(cords[0])
        Bcordsy.append(cords[1])

    counter = 0

    for body in bodys:

        Bcords = (Bcordsx[counter], Bcordsy[counter])
        body.update(Bcords, ATWALLupdateanimationN[counter])


        counter += 1

    counter = 0

    #I have to use the counter as cant do 1 per 1 on the head in heads thing so have to have a seperat counter
    for head in heads:
        Hcords = (Hcordsx[counter],Hcordsy[counter])
        head.update(Hcords,ATWALLupdateanimationN[counter])

        counter += 1





    return zombies, totaldamnge

class Bullet(pygame.sprite.Sprite):
    def __init__(self,angle, playerpos):
        pygame.sprite.Sprite.__init__(self)
        #Chanig the scale of the image so it doesnt stick out the gun too much
        self.image = pygame.transform.rotozoom(pygame.image.load("bulletpixel 6.png"), angle, 0.8)

        self.rect = self.image.get_rect()

        self.speed = 60
        self.angle = angle
        self.rect.x =  (self.rect.x + playerpos[0])
        self.rect.y = (self.rect.y + playerpos[1])

    def update(self):
        #moging it depending on its angle. so spliting up to horizontal and vertical bny taking thee cos and sin of the angle
        self.rect.x -= int(self.speed*math.cos(-self.angle*math.pi/180))

        self.rect.y -= int(self.speed*math.sin(-self.angle*math.pi/180))
        #could make this better for so when top of screen also deleate
        if self.rect.x <= -5:
            pygame.sprite.Sprite.kill(self)

        if self.rect.y <= -20 or self.rect.y >= 2000:
            pygame.sprite.Sprite.kill(self)
    def kill(self):
        pygame.sprite.Sprite.kill(self)


class Player(pygame.sprite.Sprite):

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.angle = 0
        #for now sttg to to zombie as didnt save the player image
        self.image = pygame.image.load("player2.png")
        self.rect = self.image.get_rect()
        #need to create an image for player.
        #ok so got too choess so i could     if e.type == MOUSEMOTION:
        #and just have less than more than or like so i can 3 locations it is pointed or could have the player angle towards the mouse pointer and also the shotsneed to be angled anywhay so.

        self.rect.x = 1600
        self.rect.y = 600
        self.center = self.image.get_rect().center
        #setting the starting location
        self.movingamoutx = 1640
        self.movingamouty = 500
        self.posforbullet = (1640, 500)



    def  update(self,mouse):
        # SO THIS THIS IS MAD
        #Code for  making the player follow the mouse:
        #First sets the image to the stating image if this is not here the image gets bugged out from rotating many times
        self.image = pygame.image.load("player2.png")
        #Taking the x and y apart from the mouse
        mouse_x, mouse_y = mouse
        #calulationg the relative position of the mouse by subtracting the player postion
        #I subtracke the previs frame player pos to calulate the new anlge as that is the only way i can get the angle from the gun and not the player  and so it will go to the curcer
        #This does in fact make it be one frame behind for the angle but as it is 30 fps this will not make a differnce
        #subtracking 10 so it comes from a but up from the center and so is on the cetner of the curcer
        rel_x, rel_y = mouse_x - self.posforbullet[0], mouse_y - self.posforbullet[1]-10
        #calqulating the angle by using atan2
        #this takes 2 vectors and calclated the angle inbeween them NOT 100 ON THIS this is in rad so it needs to be degress so is changed to degress by timesing my 180/ pi
        # also Return atan(y / x), in radians. The result is between -pi and pi. The vector in the plane from the origin to point (x, y) makes this angle with the positive X axis.
        #The point of atan2() is that the signs of both inputs are known to it, so it can compute the correct quadrant for the angle. For example, atan(1) and atan2(1, 1) are both pi/4, but atan2(-1, -1) is -3*pi/4.
        self.angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
        #the angle is inverted so to make it be where it is pointed subtracted 180 degress
        self.angle -= 180
        #seting self.rotated to the image rotated to by the angle
        self.rotated = pygame.transform.rotate(self.image, self.angle)
        #getting the cords of the new rotated image
        rotRect = self.rotated.get_rect()
        #keeping the old center from before
        rotRect.center = self.rotated.get_rect().center
        #setting the new cords to image rotated cords, the adding is the amout that is getting moved by
        self.rect = (rotRect[0]+ self.movingamoutx), (rotRect[1]+ self.movingamouty)
        #setting the image to the new rotated one
        self.image = self.rotated

        #Creating a variable basited of the center of the rotated image so the bullet can shoot from the image then
        #adding the move amouts to put it into spot then subtracting to make it really shoot from the barrel and not the
        #true center

        #self.posforbullet = (rotRect.center[0] + self.movingamoutx-int(math.cos(self.changedangle)*20) ,rotRect.center[1]+ self.movingamouty-40)
        self.posforbullet = (rotRect.center[0] + self.movingamoutx-15 ,rotRect.center[1]+ self.movingamouty-45)
        return self.angle, self.posforbullet

    def move(self,movex, movey):
        self.movingamoutx += movex
        self.movingamouty += movey

        #cheaking to see if the player is trying to go to far away
        if self.movingamouty <= 320:
            self.movingamouty = 320
        elif self.movingamouty >= 840:
            self.movingamouty = 840

        if self.movingamoutx >= 1700:
            self.movingamoutx = 1700
        elif self.movingamoutx <= 1500:
            self.movingamoutx = 1500

class head(pygame.sprite.Sprite):
    def __init__(self,cords, type):

        pygame.sprite.Sprite.__init__(self)
        if type == "fast":
            self.type = "fast"
            self.image = pygame.transform.scale(pygame.image.load("fasthead.png"),[70,60])
        else:
            self.type = "slow"
            self.image = pygame.transform.scale(pygame.image.load("slowhead.png"),[70,60])


        self.rect = self.image.get_rect()

        self.rect.x = cords[0]
        self.rect.y = cords[1]
        self.ticks = 0
        self.putheadonbodyx = -11
        self.putheadonbodyy = -2
        self.firsttimewall = True


    def update(self,newcords,updateanimationNumber):
        self.ticks += 1


        if updateanimationNumber != 100:
            if self.firsttimewall == True:
                self.firsttimewall = False
                updateanimationNumber = 1

            if self.type == "slow":

                if updateanimationNumber == 2:
                    self.image = pygame.image.load("satwallhead1.png")
                elif updateanimationNumber == 1:
                    self.image = pygame.image.load("satwallhead2.png")

            if self.type == "fast":

                if updateanimationNumber == 2:
                    self.image = pygame.image.load("fatwallhead1.png")
                elif updateanimationNumber == 1:
                    self.image = pygame.image.load("fatwallhead2.png")


            self.rect = self.image.get_rect()
        self.rect.x = newcords[0] + self.putheadonbodyx
        self.rect.y = newcords[1] + self.putheadonbodyy


    def kill(self):
        pygame.sprite.Sprite.kill(self)


class body(pygame.sprite.Sprite):
    def __init__(self, cords, type):
        pygame.sprite.Sprite.__init__(self)
        if type == "fast":
            self.type = "fast"
            self.image = pygame.image.load("fastbody1.png")
            self.tickamout = 10
        else:
            self.type = "slow"
            self.image = pygame.image.load("slowbody1.png")
            self.tickamout = 15

        self.rect = self.image.get_rect()
        self.rect.x = cords[0]
        self.rect.y = cords[1]
        self.ticks = 0
        self.number = 0
        self.firsttimewall = True

    def update(self, newcords, Atwallnumber):
        self.ticks += 1
        if Atwallnumber == 100:


        #This is so it only trys to change image it if is time to changer
            if self.ticks % self.tickamout == 0:
                self.number += 1
                if self.number == 5:
                    self.number = 1
                if self.type == "slow":
                    if self.number == 1:
                        self.image = pygame.image.load("slowbody1.png")
                    elif self.number == 2:
                        self.image = pygame.image.load("slowbody2.png")
                    elif self.number == 3:
                        self.image = pygame.image.load("slowbody3.png")
                    elif self.number == 4:
                        self.image = pygame.image.load("slowbody4.png")

                elif self.type == "fast":
                    if self.number == 1:
                        self.image = pygame.image.load("fastbody1.png")

                    elif self.number == 2:
                        self.image = pygame.image.load("fastbody2.png")
                    elif self.number == 3:
                        self.image = pygame.image.load("fastbody3.png")
                    elif self.number == 4:
                        self.image = pygame.image.load("fastbody4.png")
                self.rect = self.image.get_rect()
        else:
            self.atwall(Atwallnumber)


        #Dont think that chaning the codes from the get rect will be too  much of a problem and also could save the
        #images beofre having ot load them
        self.rect.x = newcords[0]
        self.rect.y = newcords[1]



    def atwall(self,updateanimationNumber):
        #seeing if this is the first time

        if self.firsttimewall == True:
            self.firsttimewall = False
            updateanimationNumber = 1

        if self.type == "slow":

            if updateanimationNumber == 2:
                self.image = pygame.image.load("satwallbody1.png")

            elif updateanimationNumber == 1:
                self.image = pygame.image.load("satwallbody2.png")
        else:
            if updateanimationNumber == 2:
                self.image = pygame.image.load("fatwallbody1.png")

            elif updateanimationNumber == 1:
                self.image = pygame.image.load("fatwallbody2.png")
        self.rect = self.image.get_rect()


    def kill(self):
        pygame.sprite.Sprite.kill(self)


class Zombie():


    def  __init__(self, startlocation, ztype):
        if ztype == "fast":
            self.speed = 11
            self.hp = 100
        else:
            self.speed = 6
            self.hp = 200

        self.location = startlocation
        self.walldamage = 0
        self.ticks = 0
        #So it will stay 100 before it gets to the wall
        self.updateanimationnumber = 100




    def update(self):

        if self.location[0] < 1300: #the y direction
            self.walldamage = 0
            self.location[0] += self.speed #as this should be 30 frams a second it should move 3 pixies each time
        #so if at the wall
        elif self.location[0] >= 1300:
            self.walldamage = 0
            #cjamge the % number to change how fast the wall dies
            if self.ticks % 30 == 0:
                self.walldamage = 5
                self.updateanimationnumber = 1
            #so it will have to hitting animation when dealing damgage
            elif self.ticks % 15 == 0:
                self.updateanimationnumber = 2
            if self.ticks % 15 != 0:
                self.updateanimationnumber = 0
        self.ticks += 1



        return self.location, self.walldamage, self.updateanimationnumber



    def hpordead(self,subtrackhp):
        self.hp -= subtrackhp
        return self.hp


if __name__ == '__main__':
    main()

【问题讨论】:

  • 您加载图像的次数过多会降低代码速度。在__init__ 中加载图像并将其保留为self.original,然后将原始图像分配给self.image 或将其旋转并分配旋转版本。
  • 不要在 Stack Overflow 上使用太多代码。我们想要concise but runnable 示例,以便我们可以复制和粘贴代码并正确测试它。我们不能说是图像是唯一的问题还是代码有其他问题。
  • @skrx 抱歉发了代码,这是我第一次遇到堆栈溢出问题。该代码完全不同于从先前随机加载的图像中选择的图像,因此我不确定如何发布可能包含库存图像的代码。谢谢

标签: python optimization pygame python-3.6


【解决方案1】:

您应该在全局范围或其他模块中加载图像并导入它们,然后在您的程序中重用它们。不要将它们加载到您的函数或__init__ 方法中,这些方法会一直在while 循环中或在您创建实例时被调用。从硬盘读取速度很慢。

另外,使用表面的convertconvert_alpha 方法来提高性能(converted 表面的 blitted 更快),例如:

# All uppercase letters indicate that it's a constant and should never be changed.
MY_IMAGE = pygame.image.load('my_image.png').convert()  # Or `.convert_alpha()`

# Load the images once at program start. You can also do that in
# another module and import them or load all images automatically
# and put them into a dictionary.
PLAYER_IMAGE = pygame.image.load("player2.png").convert_alpha()
BULLET_IMAGE = pygame.image.load("bulletpixel 6.png").convert_alpha()

class Player(pygame.sprite.Sprite):

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = PLAYER_IMAGE  # Either assign the global image directly ...

#-----------------------------------
    # or pass the image to __init__.
    def __init__(self, image):
        pygame.sprite.Sprite.__init__(self)
        self.image = image

player = Player(PLAYER_IMAGE)

在 Bullet 类中,您可以旋转原始图像。 transform.rototzoom 创建一个新的表面/图像并且不修改原始的。

class Bullet(pygame.sprite.Sprite):
    def __init__(self, angle, playerpos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.transform.rotozoom(BULLET_IMAGE, angle, 0.8)

【讨论】:

  • 谢谢,但是我如何从全局范围中传递每个图像,而不必每次都通过许多函数传递许多图像。对于我认为我应该能够在 init 中使用的播放器。我应该对所有负载使用转换吗?你知道为什么在旧的 python 上会有随机图像吗?谢谢
  • 要么直接引用全局图像,要么将它们传递给__init__ 方法并将它们分配给self.image
  • “你知道为什么在旧的 python 上会有随机图像吗?” 我不明白你的意思,请详细说明。跨度>
  • 抱歉,我对如何引用“全局图像”感到困惑。如果通过我可以使用提到的 2D 数组系统,或者一个带有两个列表的字典,将 create 函数传入,然后传入 init。当从学校的旧版本 python 到与家里相同的 python 时,它修复了僵尸将“随机”选择每个僵尸图像的问题,例如每个僵尸会有另一个僵尸随机图像。更新时修复了该错误,但导致游戏运行速度慢得多。谢谢
  • 我添加了另一个示例。是的,您通常应该convertconvert_alpha(对于具有透明度的图像)您的图像,否则性能真的会差很多。
【解决方案2】:

您加载图片的次数过多。在__init__ 中只加载一次,然后从一个变量分配给另一个变量。

例如在Player 中加载图像到self.original 并稍后分配

 self.image = self.original

 self.image = pygame.transform.rotate(self.original, self.angle)

类似

            self.number += 1
            if self.number == 5:
                self.number = 1

            if self.type == "slow":
                if self.number == 1:
                    self.image = pygame.image.load("slowbody1.png")
                elif self.number == 2:
                    self.image = pygame.image.load("slowbody2.png")
                elif self.number == 3:
                    self.image = pygame.image.load("slowbody3.png")
                elif self.number == 4:
                    self.image = pygame.image.load("slowbody4.png")

            elif self.type == "fast":
                if self.number == 1:
                    self.image = pygame.image.load("fastbody1.png")

                elif self.number == 2:
                    self.image = pygame.image.load("fastbody2.png")
                elif self.number == 3:
                    self.image = pygame.image.load("fastbody3.png")
                elif self.number == 4:
                    self.image = pygame.image.load("fastbody4.png")

__init__中的所有图片加载到两个列表中

 self.slowimages = [
      pygame.image.load("slowbody1.png"),
      pygame.image.load("slowbody2.png"),
      pygame.image.load("slowbody3.png"),
      pygame.image.load("slowbody4.png"),
 ]

 self.fastimages = [
      pygame.image.load("fastbody1.png"),
      pygame.image.load("fastbody2.png"),
      pygame.image.load("fastbody3.png"),
      pygame.image.load("fastbody4.png"),
 ]

以后你可以使用一行来分配没有if/elif的图像

 if self.type == "slow":
     self.image = self.slowimages[self.number - 1]
 elif self.type == "fast":
     self.image = self.fastimages[self.number - 1]

甚至可以将所有内容加载到一个包含两个列表的字典中

 self.all_images = {
      "slow": [
          pygame.image.load("slowbody1.png"),
          pygame.image.load("slowbody2.png"),
          pygame.image.load("slowbody3.png"),
          pygame.image.load("slowbody4.png"),
      ],
      "fast": [
          pygame.image.load("fastbodu1.png"),
          pygame.image.load("fastbodu2.png"),
          pygame.image.load("fastbodu3.png"),
          pygame.image.load("fastbodu4.png"),
      ],
 ]

以后您可以使用一行来分配不带if/elif 的图像

 self.image = self.all_images[self.type][self.number - 1]

顺便说一句,在 self.number 中您可以保留值 0..3 而不是 1..4,然后在 self.all_images[self.type][self.number - 1] 中您可以使用 self.number 而不是 self.number - 1

然后代替

     self.number += 1
     if self.number == 5:
         self.number = 1

你可以使用modulo 得到一行

     self.number = (self.number + 1) % 4

代替

  self.rect.x = newcords[0]
  self.rect.y = newcords[1]

一行就可以搞定

  self.rect.topleft = newcords

【讨论】:

  • 感谢所有帮助,如果我在 init 中加载图像,正如@skrx 所述,每次创建僵尸时都会调用它。
  • 是的,这是加快速度的下一步,您可以保存在全局变量或类变量中(而不是像当前示例中的实例变量) - 两者都只会加载一次。您还可以在开始时生成所有旋转的图像并将它们保留在列表中,然后仅从列表image = rotated[angle] 中获取,但对于许多图像,它将需要更多内存:)
  • 或者你可以创建类 ResourceManager 来加载图像/声音/等。当您第一次需要它并且稍后它会将其保存在内存中(“缓存”)以便下次从内存中获取它时,它还可以在您第一次请求时生成旋转图像,然后它可以将其保存在内存中,所以它不必再次旋转。
猜你喜欢
  • 1970-01-01
  • 2016-03-11
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
  • 2023-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多