Устранение неполадок производительности PygamePython

Программы на Python
Anonymous
Устранение неполадок производительности Pygame

Сообщение Anonymous »

Я делал этот клон лягушки в PyGame. На данный момент я создал свою собственную пиксельную графику, реализовал тайловую карту и пару спрайтов. Проблема в производительности: когда мой автомобильный спрайт перемещается по экрану, он очень нервничает, подтормаживает и вообще сильно заикается!
Вы можете найти ссылку на мой Github здесь, если хотите проверить ресурсы: https://github.com/rf19rr/OpenFrogie
Обычно я бы хотел использовать концепции ООП, но я создаю это как пример процедурного подхода. / Практика функционального кодирования для учащихся 11 класса по учебной программе. Также было немного весело испытать себя таким образом.
Я пытался реализовать дельта-время, убедился, что все преобразуется с помощью альфа-канала и т. д.

Не знаю, что еще вызывает это замедление. Я просто слишком много откладываю на задний план и перегружаю очередь обработки?
Дайте мне знать, что вы думаете, заранее спасибо!
См. код здесь:
import pygame
import sys
import json

# --- Configuration ---
TILE_SIZE = 32
GRID_WIDTH = 12
GRID_HEIGHT = 16
SCREEN_SIZE = (GRID_WIDTH * TILE_SIZE, GRID_HEIGHT * TILE_SIZE)
FPS = 60
BACKGROUND_COLOR = (238, 187, 162)

# --- Resource Management ---
def load_assets():
"""Modified: Maps IDs to specific filenames and loads them."""
# Define your mapping here
# ID : "filename.png"
tile_manifest = {
0: "dirt-center.png",
1: "grass-dirt-top.png",
2: "grass-mid-center.png",
3: "grass-dirt-bottom.png",
4: "grass-water-top.png",
5: "water-transition-bottom.png",
6: "water-center.png",
7: "water-transition-top.png",
8: "grass-water-bottom.png",
9: "alcove-bottom-left.png",
10: "alcove-bottom-right.png",
11: "alcove-top-left.png",
12: "alcove-top-right.png",
}

try:
# 1. Load the JSON layout
with open("level.json", "r") as f:
map_data = json.load(f)

# 2. Load and scale images based on the manifest
tiles = {}
for tile_id, filename in tile_manifest.items():
path = f"assets/{filename}"
img = pygame.image.load(path).convert_alpha()
tiles[tile_id] = pygame.transform.scale(img, (TILE_SIZE, TILE_SIZE))

# load in our frog sprite
frog_img = pygame.image.load("assets/frog.png").convert_alpha()

# load in our car sprite
car_img = pygame.image.load("assets/car.png").convert_alpha()

return {
"tiles": tiles,
"map_layout": map_data["map"],
"frog": pygame.transform.scale(frog_img, (TILE_SIZE, TILE_SIZE)),
"car_sprite": pygame.transform.scale(car_img, (TILE_SIZE, TILE_SIZE)),
}
except (pygame.error, FileNotFoundError, json.JSONDecodeError) as e:
print(f"Resource Error: {e}")
sys.exit()

# --- State Management ---
def get_initial_state():
"""Returns the initial state of the game as a dictionary."""
return {
"frog_pos": (GRID_WIDTH // 2, GRID_HEIGHT - 1),
"is_running": True,
"cars": [
{"x": -1.0, "y": 12.0, "speed": 10},
# {"x": -1.0, "y": 5.0, "speed": 0.20},
# {"x": -1.0, "y": 5.0, "speed": 0.20}
]
}

def update_cars(cars, dt):
"""Processes all cars and returns a new list of car states."""
updated_cars = []
for car in cars:
new_car = car.copy()
new_car["x"] += new_car["speed"] * dt

# Reset if it exits the screen (looping)
if new_car["x"] > GRID_WIDTH:
new_car["x"] = -1.0

updated_cars.append(new_car)
return updated_cars

def update_game_state(state, event, dt):
"""Pure function: calculates a new state based on inputs."""
new_state = state.copy()
new_state["cars"] = update_cars(new_state["cars"], dt)

if event.type == pygame.QUIT:
new_state["is_running"] = False

elif event.type == pygame.KEYDOWN:
x, y = new_state["frog_pos"]
if event.key == pygame.K_UP and y > 0:
new_state["frog_pos"] = (x, y - 1)
elif event.key == pygame.K_DOWN and y < GRID_HEIGHT - 1:
new_state["frog_pos"] = (x, y + 1)
elif event.key == pygame.K_LEFT and x > 0:
new_state["frog_pos"] = (x - 1, y)
elif event.key == pygame.K_RIGHT and x < GRID_WIDTH - 1:
new_state["frog_pos"] = (x + 1, y)

return new_state

def draw_background(screen, assets):
"""Refactored: Renders tiles with a fallback for missing IDs."""
tile_images = assets["tiles"]
layout = assets["map_layout"]

for row_idx, row in enumerate(layout):
for col_idx, tile_id in enumerate(row):
# Use .get() to avoid crashing if an ID is missing
tile_surface = tile_images.get(tile_id)

if tile_surface:
screen.blit(tile_surface, (col_idx * TILE_SIZE, row_idx * TILE_SIZE))
else:
# Optional: Draw a bright magenta rectangle for missing assets
pygame.draw.rect(screen, (255, 0, 255),
(col_idx * TILE_SIZE, row_idx * TILE_SIZE, TILE_SIZE, TILE_SIZE))

def draw_game(screen, assets, state):
"""
1. Clear the screen (optional, but good practice).
2. Draw the background (this effectively 'erases' the previous frame's player).
3. Draw the sprites.
4. Update the display.
"""
# 1 Clear the screen surface (Fill with black)
screen.fill(BACKGROUND_COLOR)

# 2 Redraw the entire background from the map data
draw_background(screen, assets)

# Draw all cars
for car in state["cars"]:
screen.blit(assets["car_sprite"], (car["x"] * TILE_SIZE, car["y"] * TILE_SIZE))

# Frog is next
frog_surface = assets["frog"]

# calculate the frog cordinates based on state, screen size, and tile size.
frog_x, frog_y = state["frog_pos"]
screen_x = frog_x * TILE_SIZE
screen_y = frog_y * TILE_SIZE

# Draw the frog
screen.blit(frog_surface, (screen_x, screen_y))

pygame.display.flip()

# --- Main Driver ---
def main():
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)
clock = pygame.time.Clock()
dt = clock.tick(FPS) / 1000 # seconds since last frame

assets = load_assets()
state = get_initial_state()

while state["is_running"]:
for event in pygame.event.get():
state = update_game_state(state, event, dt)

draw_game(screen, assets, state)
clock.tick(FPS)

pygame.quit()
sys.exit()

if __name__ == "__main__":
main()

Вернуться в «Python»