代码之家  ›  专栏  ›  技术社区  ›  SomeProgrammer

如何使我的pygade代码运行得更快?它只以每秒4帧的速度运行

  •  0
  • SomeProgrammer  · 技术社区  · 6 年前

    我试着在pygame中制作一个简单的2d游戏,由于某些原因它只能以4fps的速度运行,这导致它非常滞后和不稳定。我看过其他建议convert()的问题,但没有任何图像。有什么办法让它更快吗??我希望它至少每秒40帧。我目前正在研究MacOs。这是我目前的代码:

    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()
    
    0 回复  |  直到 6 年前
        1
  •  0
  •   Rabbid76    6 年前

    主要的问题是, screen 是一个 pygame.Surface 大小为1000x1000的对象。每个帧中都会清除此曲面,这就是导致性能影响的原因:

    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))
    

    没有必要把所有的 屏幕 每一帧的表面。只需清除稍后绘制到窗口中的区域,通过 pygame.draw.rect :

    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)
    
        # [...]