I get 25% CPU usage on this simple project. I hope it's okay if I just post the whole thing. It probably something to do with the rendering code. It's definitely the project though, my fans get loud, then I exit the program, and quiet again.
#python3 -OO main.py
import pygame
import json
import sys
import os
#OS
xMax = 800
yMax = 640
xWin = 1366 - xMax #pins window to top right of the display
yWin = 0
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" % (xWin, yWin)
#PYGAME
pygame.init()
pygame.font.init()
pygame.display.set_caption("Mountain of Doom")
screen = pygame.display.set_mode((xMax, yMax))
font = pygame.font.SysFont(None, 30)
with open('saves/save.json') as save_file:
data = json.load(save_file)
tileSize = 16
tile_images = {
1: pygame.image.load("resources/graphics/sprites/grass.png"),
#ABOUT 10 MORE CALLS
}
with open("resources/maps/demo.json", "r") as json_file:
json_data = json.load(json_file)
tileMap = json_data["tileMap"]
class Background:
def __init__(self, tile_images, tileSize, tileMap):
self.tile_images = tile_images
self.tileSize = tileSize
self.tileMap = tileMap
def draw(self, screen):
background = pygame.Surface((len(self.tileMap[0]) * self.tileSize, len(self.tileMap) * self.tileSize))
for row in range(len(self.tileMap)):
for col in range(len(self.tileMap[0])):
tile_id = self.tileMap[row][col]
if tile_id in self.tile_images:
tile_image = self.tile_images[tile_id]
background.blit(tile_image, (col * self.tileSize, row * self.tileSize))
screen.blit(background, (0, 0))
class Player:
def __init__(self, position, player_path):
self.position = position
self.image = pygame.image.load(player_path)
self.speed = 16
def move(self, keys):
x, y = self.position
speed = self.speed
if keys[pygame.K_UP] and y > 0:
y -= speed
elif keys[pygame.K_DOWN]:
y += speed
elif keys[pygame.K_LEFT] and x > 0:
x -= speed
elif keys[pygame.K_RIGHT]:
x += speed
self.position = (x, y)
def draw(self, screen):
screen.blit(self.image, (self.position))
def update_data(player):
data['player_x'] = player.position[0]
data['player_y'] = player.position[1]
with open('saves/save.json', 'w') as save_file:
json.dump(data, save_file)
def main():
background = Background(tile_images, tileSize, tileMap)
player_path = "resources/graphics/sprites/player1.png"
position = (data['player_x'], data['player_y'])
player = Player(position, player_path)
clock = pygame.time.Clock()
while True:
clock.tick(60)
mbreak = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
mbreak = True
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
mbreak = True
background.draw(screen)
player.move(keys)
player.draw(screen)
text = f'{player.position[0]}, {player.position[1]}'
img = font.render(text, True, (0xFFFFFFFF))
screen.blit(img, (20, 20))
pygame.display.update()
if mbreak:
break
update_data(player)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
2 Answers 2
The code is not easy to run because I don't have your local files. However, I was able to throw some together in MS Paint. Although I didn't notice any performance issues (you might need to update your packages?), I think that the main issue is that you are repeatedly computing the background Surface in your Background class. Personally, I would just put together the background once and then blit it for each drawing animation. You also might want some input validation.
class Background:
def __init__(self, tile_images, tile_size, tile_map):
"""
Creates a background image and makes it easy to draw.
:param tile_images: from tile_id to source
:param tile_size: positive integer number of pixels
:param tile_map: 2D array from (row, col) to tile_id
"""
if tile_size < 1:
raise ValueError("Tile size less than 1 pixel!")
n_rows = len(tile_map)
if n_rows < 1:
raise ValueError("Less than 1 map row!")
n_cols = len(tile_map[0])
if n_cols < 1:
raise ValueError("Less than 1 map col!")
background = pygame.Surface((n_cols * tile_size, n_rows * tile_size))
for row in range(n_rows):
for col in range(n_cols):
tile_id = tile_map[row][col]
tile_image = tile_images[tile_id]
background.blit(tile_image, (col * tile_size, row * tile_size))
self.background = background
def draw(self, screen):
screen.blit(self.background, (0, 0))
That change reduced the CPU utilization from an average of 2.5% to an average of 0.5% for me. Hope that helps. Welcome to the community.
-
1\$\begingroup\$ This is what jumped out at me as well. Creating objects in a tight loop in pygame (and they're all tight loops) is a red flag. Ideally do all your object creation at init-time. \$\endgroup\$pjz– pjz2023年08月20日 02:23:35 +00:00Commented Aug 20, 2023 at 2:23
FROM:
tile_images = {
1: pygame.image.load("resources/graphics/sprites/grass.png"),
2: pygame.image.load("resources/graphics/sprites/water.png"),
3: pygame.image.load("resources/graphics/sprites/tree.png").,
4: pygame.image.load("resources/graphics/sprites/bones.png"),
5: pygame.image.load("resources/graphics/sprites/rocks.png"),
6: pygame.image.load("resources/graphics/sprites/brick1.png"),
7: pygame.image.load("resources/graphics/sprites/brick2.png"),
8: pygame.image.load("resources/graphics/sprites/tree2.png")
}
TO:
tile_images = {
1: pygame.image.load("resources/graphics/sprites/grass.png").convert_alpha(),
2: pygame.image.load("resources/graphics/sprites/water.png").convert_alpha(),
3: pygame.image.load("resources/graphics/sprites/tree.png").convert_alpha(),
4: pygame.image.load("resources/graphics/sprites/bones.png").convert_alpha(),
5: pygame.image.load("resources/graphics/sprites/rocks.png").convert_alpha(),
6: pygame.image.load("resources/graphics/sprites/brick1.png").convert_alpha(),
7: pygame.image.load("resources/graphics/sprites/brick2.png").convert_alpha(),
8: pygame.image.load("resources/graphics/sprites/tree2.png").convert_alpha()
}
This got my CPU usage down from 25%-26% to 7%-8%.
Explore related questions
See similar questions with these tags.
top
on Linux? IDK if it's worth profiling it withperf record
to see if there's a lot of CPU time spent in a shared library (such as a graphics lib). Also, if your X server uses a lot of CPU time while this is running, that could also be a thing. Do you have proper graphics drivers for your video hardware set up? \$\endgroup\$