如何使我的 pygade 代码 运行 更快?它只有 运行ning 4fps

How to make my pygade code run faster? It is only running at 4fps

我正在尝试在 pygame 中制作一个简单的 2d 游戏,但出于某种原因,它只能在 4fps.h 下运行,这导致它非常滞后和不稳定。我看过其他建议 convert() 的问题,但我没有任何图像。有什么办法让它更快??我希望它 运行 至少为 40 fps。我目前正在研究 MacO。到目前为止,这是我的代码:

import math
import sys
import pygame


from pygame.locals import *



pygame.init()
BLACK = (0,0,0)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE=(0,0,255)
PI = 3.141592653
font = pygame.font.SysFont('Times',12, True,False)
def write_text(text, pos,color):
    hi = font.render(text, True,color)
    screen.blit(hi, pos)
def draw_label_rect(text,color,object):
    pygame.draw.rect(screen, object.color, object.Display_Rect)
    hi =font.render( text, True, color)
    center_x = object.pos[0]+ 1/2*object.width
    center_y =object.pos[1] + 1/2 * object.length
    text_width = hi.get_width()
    text_height = hi.get_height()
    screen.blit(hi, (math.floor(center_x-1/2*text_width),math.floor(center_y-1/2*text_height)))
def draw_image_label_rect_centered(image, color, pos,scale_factor):
    pygame.draw.rect(screen, color,pos)
    image = pygame.image.load(image).convert_alpha()
    width = image.get_width()
    height = image.get_height()
    image2 = pygame.transform.smoothscale(image,(math.floor(width*scale_factor),math.floor(height*scale_factor)))
    new_width = image2.get_width()
    new_height = image2.get_height()

    center_x = pos[0]+ 1/2*pos[2]
    center_y =pos[1] + 1/2 * pos[3]

    screen.blit(image2, (center_x-1/2*new_width, center_y-1/2*new_height))

def draw_image_label_rect_behind(image, color, pos,scale_factor):
    pygame.draw.rect(screen, color,pos)
    image = pygame.image.load(image).convert_alpha()
    width = image.get_width()
    height = image.get_height()
    image2 = pygame.transform.smoothscale(image,(math.floor(width*scale_factor),math.floor(height*scale_factor)))

    center_x = pos[0]+ 1/2*pos[2]
    new_width = image2.get_width()

    screen.blit(image2, (center_x-1/2*new_width, pos[3]+pos[1]+1))


size = (1500, 700)
background = pygame.display.set_mode(size)
screen = pygame.surface.Surface((10000, 10000))

pygame.display.set_caption("HI")

done = False
clock = pygame.time.Clock()
FPS = 120
scroll_y = 0
scroll_x = 0
originalmousex = None
originalmousey = None


Rects= []
Objects = []
class Camera():
    def __init__(self):

        self.x = 5000
        self.y = 5000
        self.distance_x = 750
        self.distance_y = 350
    def move(self,offset_x,offset_y):
        self.x +=offset_x
        self.y +=offset_y
        for i in Objects:
            i.screenpos=(i.pos[0]-self.x+750,i.pos[1]-self.y+350)
            i.virtual_rect = pygame.Rect(i.screenpos[0],i.screenpos[1],i.width,i.length)

    def zoom_in(self):
        self.distance_x = math.floor(self.distance_x * 0.95)
        self.distance_y = math.floor( self.distance_y * 0.95)
    def zoom_out(self):
        self.distance_x = math.floor(self.distance_x * 1.05)
        self.distance_y = math.floor(self.distance_y * 1.05)

    def subsurfacing(self):
        self.camera_surface = screen.subsurface((self.x- self.distance_x,self.y - self.distance_y,2*self.distance_x,2*self.distance_y))

        background.blit(pygame.transform.smoothscale(self.camera_surface,(1500,700)),(0,0))


main_camera = Camera()

class InfantryRect():
    def __init__(self,number, color,formation,pos):
        self.number = number
        self.color = color
        self.formation = formation
        class_formation = self.formation
        self.pos = pos
        self.moving = False
        self.movingto = None
        self.startmovingframe = None
        self.screenpos = (self.pos[0]-main_camera.x+750,self.pos[1]-main_camera.y+350)
        if self.formation == 'line':
            lengthy = 25
            self.Display_Rect = pygame.Rect(self.pos[0],self.pos[1],lengthy*2,(self.number//lengthy)*2)
            self.length = self.Display_Rect.height
            self.width = self.Display_Rect.width
            self.virtual_rect = pygame.Rect(self.screenpos[0],self.screenpos[1],self.width,self.length)
            self.speed = 1


    def display(self):

        if self.formation== 'line':

          pygame.draw.rect(screen,self.color,[self.pos[0],self.pos[1],self.width,self.length])
          hi = font.render(str(self.number),True,(255,225,64))

          center_x = self.pos[0]+ 1/2*self.width
          center_y =self.pos[1] + 1/2 * self.length
          text_width = hi.get_width()
          text_height = hi.get_height()
          screen.blit(hi, (math.floor(center_x-1/2*text_width),math.floor(center_y-1/2*text_height)))
    def movingcreating(self,position):
        self.distance = math.hypot(position[0]-self.virtual_rect.x,position[1]-self.virtual_rect.y)
        if self.distance!=0:
            self.dx = ((position[0]-self.virtual_rect.x)/self.distance)*self.speed
            self.dy = ((position[1]-self.virtual_rect.y)/self.distance)*self.speed

    def move(self,position):


        if self.distance!=0:
            self.pos = (self.pos[0]+self.dx,self.pos[1]+self.dy)
            self.virtual_rect = pygame.Rect(int(self.pos[0]-main_camera.x+750),int(self.pos[1]-main_camera.y+350),self.width,self.length)
            self.Display_Rect = pygame.Rect(int(self.pos[0]),int(self.pos[1]),self.width,self.length)
            self.movingcreating(position)




TestInf = InfantryRect(100,RED,'line',[5000,5000])
Objects.append(TestInf)
count = 0
width = screen.get_width()
length = screen.get_height()
clock = pygame.time.Clock()
z_is_pressed = False
x_is_pressed = False
up_is_pressed = False
down_is_pressed = False
right_is_pressed = False
left_is_pressed = False
mouse_button_holding = False






frames = 0
while not done:

    for event in pygame.event.get():



        if event.type == pygame.QUIT:

            done = True


        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_pos = event.pos

            for i in Objects:

                if i.virtual_rect.collidepoint(mouse_pos):
                    print('Hello')
                    mouse_button_holding = i

                    break
            if mouse_button_holding==False:
                mouse_button_holding = 'scrolling'
                originalmousex = mouse_pos[0]
                originalmousey = mouse_pos[1]

        elif event.type == pygame.MOUSEBUTTONUP:
            if mouse_button_holding!= False and mouse_button_holding!='scrolling':

                mouse_button_holding.movingto = (event.pos[0] -0.5*mouse_button_holding.width-main_camera.x+5000 , event.pos[1]-0.5*mouse_button_holding.length-main_camera.y+5000)
                mouse_button_holding.movingcreating(event.pos)
                mouse_button_holding.moving = True
                mouse_button_holding.startmovingframe = frames
                mouse_button_holding = False
            originalmousex = None
            originalmousey = None
            mouse_button_holding = False






        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_z:
                z_is_pressed = True
            elif event.key ==pygame.K_x:
                x_is_pressed = True
            elif event.key == pygame.K_UP:
                up_is_pressed = True
            elif event.key == pygame.K_DOWN:
                down_is_pressed = True
            elif event.key == pygame.K_RIGHT:
                right_is_pressed = True
            elif event.key == pygame.K_LEFT:
                left_is_pressed = True

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_z:
                z_is_pressed = False
            elif event.key ==pygame.K_x:
                x_is_pressed = False



    if mouse_button_holding=='scrolling':

        main_camera.move(-(pygame.mouse.get_pos()[0]-originalmousex),-(pygame.mouse.get_pos()[1]-originalmousey))
        originalmousex = pygame.mouse.get_pos()[0]
        originalmousey = pygame.mouse.get_pos()[1]
    if z_is_pressed:

        main_camera.zoom_in()
    if x_is_pressed:
        main_camera.zoom_out()
    background.fill(BLACK)
    screen.fill(BLACK)
    # pygame.draw.line(screen, GREEN, [0, 0], [100, 100], 5)
    #for y_offset in range(0, 100, 10):
        #pygame.draw.line(screen,RED,[0,10+y_offset],[100,110+y_offset],5)
    #draw_label_rect('Hello',RED,[250,250,50,50],WHITE)
    TestInf.display()
    for i in Objects:
        if i.moving:
            i.move(i.movingto)

    main_camera.subsurfacing()
    print(clock.get_fps())
    clock.tick(60)
    pygame.display.update()
    frames+=1

pygame.quit()

主要问题是,screen 是一个 pygame.Surface 对象,大小为 10000x10000。该表面在每一帧中都会被清除,这就是导致性能影响的原因:

screen = pygame.surface.Surface((10000, 10000))
screen.fill(BLACK)

由于屏幕上只有一小块表面(次表面)blit

   def subsurfacing(self):
       self.camera_surface = screen.subsurface((self.x- self.distance_x,self.y - self.distance_y,2*self.distance_x,2*self.distance_y))
       background.blit(pygame.transform.smoothscale(self.camera_surface,(1500,700)),(0,0))

没有必要在每一帧中清除完整的screen表面。稍后通过 pygame.draw.rect:

清除被绘制到 window 中的区域
class Camera():

    # [...]

    def clearsubsurface(self, color):
        px = self.x- self.distance_x,self.y - self.distance_y
        py = 2*self.distance_x,2*self.distance_y
        pygame.draw.rect(screen, color, (px, py))
while not done:

    # [...]

    #screen.fill(BLACK)                <--- DELETE
    main_camera.clearsubsurface(BLACK)

    # [...]