> 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.
npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill 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+ (the actively maintained community fork; same
import pygame).
input handling, blitting, or sprite/group collision.
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.
pip install pygame-ce — it's themaintained fork and imports as pygame. Don't install both in one environment.
pygame.init(), `screen =pygame.display.set_mode((w, h)), clock = pygame.time.Clock()`.
frame (for event in pygame.event.get()), update state, redraw, then
pygame.display.flip().
dt = clock.tick(60) / 1000 (seconds)and scale all motion by dt. Keep positions as floats; blit at integer rects.
KEYDOWN/MOUSEBUTTONDOWN, for discreteactions) and polled (pygame.key.get_pressed(), for held movement).
Sprite + Group. Subclass pygame.sprite.Spritewith image/rect; group.update(dt) and group.draw(screen) handle the
batch. Run it and watch the window before assuming it works.
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()
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
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)
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
# 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()
pygame.event.get() (or pygame.event.pump()) every frame.
Scale by dt = clock.tick(fps) / 1000 and use pixels-per-second values.
rect coordinates are integers; store thetrue position as a Vector2 of floats and assign rect.center = round(...) each
frame.
.convert() (opaque) or.convert_alpha() (transparent) on loaded images once; un-converted surfaces blit
far slower.
pygame.display.flip() (or update()), or youdrew before screen.fill(...) so it was cleared away.
Draw background first, sprites last.
pip install pygame got the old one → for the maintained fork usepip install pygame-ce; having both installed causes import conflicts.
speed.
Group variants (GroupSingle, LayeredUpdates for z-order), pixel-perfectcollision with mask, slicing a spritesheet, simple animation, sound/music, and
text rendering, read references/sprites-and-collision.md.
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.Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take gamedev-skills/pygame-core from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference pip.
Without those the skill loads but fails at the first command.