跳到主要内容
知仓学习社ZHICANG

pygame-core

>

不碰外部(只输出文字)无严重或高危命中gamedev-skills/awesome-gamedev-agent-skills

它会碰到什么

扫了多少2 个文本文件,11 KB
它会碰到什么不碰外部(只输出文字)
命中总数0 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

pygame Core

Build the foundation of a pygame game in Python: the main loop, delta-time

movement, drawing with Surface/Rect, input, and Sprite/Group management.

Targets pygame-ce 2.5.7 (the actively maintained community fork; same

import pygame).

When to use

  • Use when starting a pygame game, fixing the loop, frame-rate-dependent speed,

input handling, blitting, or sprite/group collision.

  • Use when code does import pygame and the project depends on pygame-ce

(or pygame).

**When not to use:** Python language questions unrelated to pygame. 3D rendering

(pygame is 2D). For cross-engine save/load use save-systems; for rebindable input

architecture see input-systems.

Core workflow

  1. Install pygame-ce, not legacy pygame. pip install pygame-ce — it's the

maintained fork and imports as pygame. Don't install both in one environment.

  1. Init and open a window. pygame.init(), `screen =

pygame.display.set_mode((w, h)), clock = pygame.time.Clock()`.

  1. Run one loop: events → update → draw → flip. Pump the event queue every

frame (for event in pygame.event.get()), update state, redraw, then

pygame.display.flip().

  1. Make it frame-rate independent. Get dt = clock.tick(60) / 1000 (seconds)

and scale all motion by dt. Keep positions as floats; blit at integer rects.

  1. Handle input two ways: event-based (KEYDOWN/MOUSEBUTTONDOWN, for discrete

actions) and polled (pygame.key.get_pressed(), for held movement).

  1. Organise objects with Sprite + Group. Subclass pygame.sprite.Sprite

with image/rect; group.update(dt) and group.draw(screen) handle the

batch. Run it and watch the window before assuming it works.

Patterns

1. Minimal game loop (the skeleton)

import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()

running = True
while running:
    dt = clock.tick(60) / 1000          # cap at 60 FPS; dt = seconds since last frame
    for event in pygame.event.get():    # MUST drain the queue or the OS thinks it hung
        if event.type == pygame.QUIT:
            running = False

    # update game state here, scaled by dt ...

    screen.fill((18, 18, 28))           # clear each frame
    # draw everything here ...
    pygame.display.flip()               # present the frame

pygame.quit()

2. Delta-time movement (frame-rate independent)

from pygame.math import Vector2

pos = Vector2(100, 100)        # keep position as floats
speed = 220                    # PIXELS PER SECOND, not per frame

# inside the loop, after computing dt:
keys = pygame.key.get_pressed()
direction = Vector2(
    keys[pygame.K_RIGHT] - keys[pygame.K_LEFT],
    keys[pygame.K_DOWN]  - keys[pygame.K_UP],
)
if direction.length_squared() > 0:
    direction = direction.normalize()      # equal speed on diagonals
pos += direction * speed * dt              # RIGHT: dt-scaled
screen.blit(player_img, (round(pos.x), round(pos.y)))  # blit at integer pixels

3. Input: events vs polling

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    elif event.type == pygame.KEYDOWN:        # discrete press: jump, menu, pause
        if event.key == pygame.K_SPACE:
            jump()
        elif event.key == pygame.K_ESCAPE:
            running = False
    elif event.type == pygame.MOUSEBUTTONDOWN:
        shoot_at(event.pos)                   # event.pos = (x, y)

# Polled state (read once per frame) for continuous/held input:
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
    move_left(dt)

4. A Sprite subclass + a Group

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        # convert() once at load makes blits much faster; _alpha keeps transparency.
        self.image = pygame.image.load("player.png").convert_alpha()
        self.rect = self.image.get_rect(center=(x, y))
        self.pos = pygame.math.Vector2(self.rect.center)
        self.speed = 240

    def update(self, dt):                      # Group.update(dt) calls this per sprite
        keys = pygame.key.get_pressed()
        self.pos.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * self.speed * dt
        self.rect.center = (round(self.pos.x), round(self.pos.y))

all_sprites = pygame.sprite.Group()
all_sprites.add(Player(400, 300))

# in the loop:
all_sprites.update(dt)        # calls each sprite's update(dt)
all_sprites.draw(screen)      # blits each sprite at its rect

5. Collision detection

# Sprite vs group: e.g. player picking up coins (True = remove collided coins).
collected = pygame.sprite.spritecollide(player, coins, dokill=True)
score += len(collected)

# Group vs group: bullets vs enemies (kill both on hit).
hits = pygame.sprite.groupcollide(bullets, enemies, True, True)

# Plain rect overlap (no sprites needed):
if player.rect.colliderect(door_rect):
    open_door()

Pitfalls

  • Window freezes / "not responding" → you didn't pump the event queue. Call

pygame.event.get() (or pygame.event.pump()) every frame.

  • Speed differs on faster machines → you moved by a fixed amount per frame.

Scale by dt = clock.tick(fps) / 1000 and use pixels-per-second values.

  • Sub-pixel movement snaps/jittersrect coordinates are integers; store the

true position as a Vector2 of floats and assign rect.center = round(...) each

frame.

  • Blits are slow / framerate drops → call .convert() (opaque) or

.convert_alpha() (transparent) on loaded images once; un-converted surfaces blit

far slower.

  • Nothing appears → you forgot pygame.display.flip() (or update()), or you

drew before screen.fill(...) so it was cleared away.

  • Wrong draw order → pygame uses painter's order; later blits cover earlier ones.

Draw background first, sprites last.

  • pip install pygame got the old one → for the maintained fork use

pip install pygame-ce; having both installed causes import conflicts.

  • Diagonal movement is faster → normalise the direction vector before scaling by

speed.

References

  • For Group variants (GroupSingle, LayeredUpdates for z-order), pixel-perfect

collision with mask, slicing a spritesheet, simple animation, sound/music, and

text rendering, read references/sprites-and-collision.md.

Related skills

  • love2d-core — the same loop concepts in LÖVE/Lua.
  • bevy-ecs — a heavier ECS engine when a project outgrows pygame.
  • input-systems / save-systems — engine-agnostic input and persistence.
  • platformer / roguelike — genre templates that pair with pygame.

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。