Pygame平台游戏运行15秒后卡顿变慢问题求助
Pygame平台游戏运行15秒后卡顿的原因及解决方法
问题描述
我正在开发一款尚未完成的Pygame平台游戏,初始运行流畅,但启动15秒后角色移动变得卡顿、游戏运行缓慢。
相关代码
class Game_Level(Main): #SUB CLASS FOR CREATING THE LEVEL (INHERITANCE) #CONSTRUCTOR def __init__(self,x,y,scale_width,scale_height,speed,TILE_SIZE): self.TILE_SIZE = TILE_SIZE #CREATES AN ATTRIBUTE CALLED TILE_SIZE AND ASSIGNS TO IT THE VALUE OF THE TILE_SIZE PARAMETER super().__init__(x,y,scale_width,scale_height,speed) #INSTANCE ATTRIBUTES self.TILE_SIZE = TILE_SIZE #CREATES AN ATTRIBUTE CALLED TILE_SIZE AND ASSIGNS TO IT THE VALUE OF THE TILE_SIZE PARAMETER #CLASS ATTRIBUTES self.dirt_image = pygame.image.load('dirt_image1.jpg').convert() #IMAGE THAT IS DISPLAYED ON THE SCREEN AND USED FOR THE GAME MAP self.grass_image = pygame.image.load('grass_image1.jpg').convert() #IMAGE THAT IS DISPLAYED ON THE SCREEN AND USED FOR THE GAME MAP self.tile_rects = [] def game_level(self): self.game_map = [['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'], ['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'], ['0','0','0','0','0','0','0','2','2','0','0','0','0','0','0','0','0'], ['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'], ['0','0','0','0','2','2','0','0','0','0','2','2','0','0','0','0','0'], ['2','2','2','2','2','2','2','2','2','2','2','2','2','0','0','2','2'], ['1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1'], ['1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1'], ['1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1'], ['1','1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1']] self.camera_value[0] += (self.player_rect.x-self.camera_value[0]-325) #X-AXIS self.camera_value[1] += (self.player_rect.y-self.camera_value[1]-325) #Y-AXIS next_row = 0 for row in self.game_map: #LOOPS THROUGH EACH ROW each_block = 0 for each_tile in row: #LOOPS THROUGH EVERY STRING IN THE ROW if each_tile == '1': WINDOW.blit(self.dirt_image, (each_block * self.TILE_SIZE-self.camera_value[0], next_row * self.TILE_SIZE-self.camera_value[1])) if each_tile == '2': WINDOW.blit(self.grass_image, (each_block * self.TILE_SIZE-self.camera_value[0], next_row * self.TILE_SIZE-self.camera_value[1])) if each_tile != '0': self.tile_rects.append(pygame.Rect(each_block * self.TILE_SIZE, next_row * self.TILE_SIZE, self.TILE_SIZE, self.TILE_SIZE)) each_block += 1 next_row += 1 def collision_test(self, tiles): hit_list = [] for tile in tiles: if self.player_rect.colliderect(tile): hit_list.append(tile) return hit_list def collisions_with_tiles(self, movement, tiles): collision_types = {'top': False, 'bottom': False, 'right': False, 'left': False} self.player_rect.x += movement[0] hit_list = self.collision_test(tiles) for tile in hit_list: if movement[0] > 0: self.player_rect.right = tile.left collision_types['right'] = True elif movement[0] < 0: self.player_rect.left = tile.right collision_types['left'] = True self.player_rect.y += movement[1] hit_list = self.collision_test(tiles) for tile in hit_list: if movement[1] > 0: self.player_rect.bottom = tile.top collision_types['bottom'] = True elif movement[1] < 0: self.player_rect.top = tile.bottom collision_types['top'] = True return collision_types def player_movement(self): player_movement = [0, 0] if self.moving_right: self.moving_left = False player_movement[0] -= self.speed elif self.moving_left: self.moving_right = False player_movement[0] += self.speed player_movement[1] += self.player_y_momentum self.player_y_momentum += 0.3 if self.player_y_momentum > 8: self.player_y_momentum = 8 collisions = self.collisions_with_tiles(player_movement, self.tile_rects) if collisions['bottom']: self.player_y_momentum = 0 self.air_timer = 0 else: self.air_timer += 1 player = Game_Level(50,50,80,60,4,70) def game_loop(): clock = pygame.time.Clock() run = True while run: clock.tick(FPS) #MAINTAIN 60 FPS WINDOW.fill(blue) #CALLING THE METHODS player.player_movement() player.game_level() player.player_keys() #ENCAPSULATION IS USED HERE- MY METHODS AND ATTRIBUTES ARE NOT ACCESSIBLE OUTSIDE THE OBJECT player.player_animation() pygame.display.update() #IT WON'T SHOW THE MOST RECENT THING I DREW UNLESS I MANUALLY UPDATE IT for event in pygame.event.get(): if event.type == QUIT: pygame.quit() #STOP PYGAME sys.exit() game_loop()
卡顿原因分析
核心问题在于tile_rects列表的无限增长:
- 在
game_level方法中,每次帧循环都会遍历游戏地图,将非0的tile矩形添加到self.tile_rects中,但从未清空这个列表。 - 游戏每秒运行约60帧,每帧都会往列表里添加数十个Rect对象,15秒后列表会积累上千个重复的Rect。
- 后续的
collision_test和collisions_with_tiles方法需要遍历整个tile_rects列表做碰撞检测,随着列表越来越大,检测耗时呈线性增长,最终导致游戏卡顿。
解决方法
修改game_level方法,在生成新的tile矩形前先清空tile_rects列表:
def game_level(self): self.tile_rects.clear() # 或者使用 self.tile_rects = [] self.game_map = [['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'], # ... 原有地图代码 ...
这样每帧都会重新生成当前地图的tile矩形列表,避免重复积累,碰撞检测的耗时会保持稳定,游戏就能流畅运行。
内容的提问来源于stack exchange,提问作者CAKE
相关产品推荐
相关产品推荐

