All skills

Structure a pygame (pygame-ce) game in Python: the init/event/update/draw loop, delta-time movement, Surface/Rect blitting, keyboard/mouse input, and Sprite/Group management with collision. Use when building or debugging a pygame game — when the user mentions pygame, pygame-ce, the game loop, blit, Surface, Rect, sprite groups, or clock.tick. Targets pygame-ce.

Use this Skill: https://skilld.dev/gh/gamedev-skills/awesome-gamedev-agent-skills/pygame-core

This session only. Nothing lands on disk.

referencessprites-and-collision.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

pygame sprites, collision & media (pygame-ce 2.5+)

Depth behind the pygame-core skill: group variants, pixel-perfect collision, spritesheets, animation, and audio/text.

Group variants

pygame.sprite ships several containers; pick by need:

Class Use for
Group the general case; update(*args) + draw(surface)
GroupSingle a slot holding at most one sprite (e.g. the player)
LayeredUpdates groups that draw by a per-sprite _layer (z-order)
RenderUpdates tracks dirty rects for partial-screen redraws
from pygame.sprite import LayeredUpdates
world = LayeredUpdates()
world.add(background, layer=0)
world.add(player, layer=10)        # higher layer draws on top
world.add(ui, layer=20)
world.update(dt)
world.draw(screen)

A sprite removes itself from all groups with self.kill(). Membership is two-way: group.has(sprite), sprite.groups().

Collision functions

spritecollide and groupcollide use rect overlap by default. The optional collided callback swaps in a more precise test:

import pygame
from pygame.sprite import collide_rect, collide_circle, collide_mask

# Circle collision (set sprite.radius, or it's derived from the rect):
pygame.sprite.spritecollide(player, rocks, False, collide_circle)

# Pixel-perfect via masks (see below):
pygame.sprite.spritecollide(player, spikes, False, collide_mask)

Other helpers: pygame.sprite.collide_rect_ratio(0.75) (shrunken rect), spritecollideany (fast boolean-ish "any hit"), and Rect methods colliderect, collidepoint, collidelist, collidelistall.

Pixel-perfect collision with masks

Rect collision is generous; for tight hitboxes build a Mask from each sprite's alpha and test overlap:

class Bullet(pygame.sprite.Sprite):
    def __init__(self, image, pos):
        super().__init__()
        self.image = image.convert_alpha()
        self.rect = self.image.get_rect(center=pos)
        self.mask = pygame.mask.from_surface(self.image)  # build once

# collide_mask uses each sprite's .mask:
if pygame.sprite.collide_mask(bullet, enemy):
    enemy.kill()

Rebuild the mask if the sprite's image changes (e.g. each animation frame), or keep a per-frame list of masks.

Slicing a spritesheet

def load_frames(path, frame_w, frame_h):
    sheet = pygame.image.load(path).convert_alpha()
    cols = sheet.get_width() // frame_w
    rows = sheet.get_height() // frame_h
    frames = []
    for r in range(rows):
        for c in range(cols):
            rect = pygame.Rect(c * frame_w, r * frame_h, frame_w, frame_h)
            frames.append(sheet.subsurface(rect))   # view into the sheet, no copy
    return frames

Simple frame animation

class AnimatedSprite(pygame.sprite.Sprite):
    def __init__(self, frames, fps, pos):
        super().__init__()
        self.frames = frames
        self.frame_time = 1 / fps
        self.timer = 0.0
        self.index = 0
        self.image = frames[0]
        self.rect = self.image.get_rect(center=pos)

    def update(self, dt):
        self.timer += dt
        while self.timer >= self.frame_time:
            self.timer -= self.frame_time
            self.index = (self.index + 1) % len(self.frames)
            self.image = self.frames[self.index]

Audio

pygame.mixer.init()                       # or rely on pygame.init()
jump_sfx = pygame.mixer.Sound("jump.wav") # short SFX, fully loaded
jump_sfx.set_volume(0.5)
jump_sfx.play()

pygame.mixer.music.load("theme.ogg")      # streamed music (one track at a time)
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play(loops=-1)         # -1 = loop forever

Prefer .ogg/.wav; keep many short effects as Sound, and long tracks on the single music stream.

Text

font = pygame.font.Font(None, 36)         # None = default font; or a .ttf path
# Antialiased text is slow to render — cache the Surface, re-render only on change.
label = font.render(f"Score: {score}", True, (255, 255, 255))
screen.blit(label, (10, 10))

Re-rendering text every frame is a common performance trap; render once and re-blit, re-rendering only when the string changes.

Source: SKILL.md on GitHub

No alerts5d3 checks · Risk SAFE
  • Gen Agent Trust Hub5d

    This skill provides standard templates and guidance for developing games using the pygame-ce framework. No malicious patterns, suspicious dependencies, or data exfiltration risks were detected.

  • Socket5d

    No alerts

  • Snyk5d

    Risk: LOW · No issues

Signed by skilld at e4e9569. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated last week

README badge

README badge for gamedev-skills/awesome-gamedev-agent-skills/pygame-core