Python Game Development library providing comprehensive multimedia functionality for creating games and interactive applications.
—
Comprehensive mouse cursor control including system cursors, custom bitmap cursors, and color cursors. Provides both high-level cursor management and low-level cursor compilation utilities.
The Cursor class provides unified interface for all cursor types.
class Cursor:
def __init__(self, *args):
"""
Create cursor from various sources.
Parameters:
*args: Variable arguments depending on cursor type:
- (constant,) for system cursors
- (size, hotspot, xormasks, andmasks) for bitmap cursors
- (hotspot, surface) for color cursors
"""
type: str # "system", "bitmap", or "color"
data: tuple # Cursor-specific data
def copy(self) -> Cursor:
"""
Create copy of cursor.
Returns:
Cursor: New cursor object with same data
"""Functions for setting and querying the current system cursor.
def set_cursor(*args) -> None:
"""
Set the current mouse cursor.
Parameters:
*args: Cursor data in various formats:
- (cursor_object,) - Set from Cursor object
- (constant,) - Set system cursor by constant
- (size, hotspot, xormasks, andmasks) - Set bitmap cursor
- (hotspot, surface) - Set color cursor from surface
"""
def get_cursor() -> Cursor:
"""
Get the current cursor.
Returns:
Cursor: Current cursor object
"""Utilities for creating bitmap cursors from string representations.
def compile(
strings: tuple[str, ...],
black: str = "X",
white: str = ".",
xor: str = "o"
) -> tuple[tuple[int, ...], tuple[int, ...]]:
"""
Compile cursor from string representation.
Parameters:
strings: Tuple of strings representing cursor bitmap
black: Character representing black pixels
white: Character representing white pixels
xor: Character representing XOR pixels
Returns:
tuple[tuple[int, ...], tuple[int, ...]]: (xormasks, andmasks) bitmap data
"""
def load_xbm(cursor_file, mask_file) -> tuple:
"""
Load cursor from XBM format files.
Parameters:
cursor_file: Path to cursor XBM file
mask_file: Path to mask XBM file
Returns:
tuple: Cursor data suitable for Cursor creation
"""Built-in cursor constants for common system cursors.
# System cursor constants
SYSTEM_CURSOR_ARROW: int # Standard arrow cursor
SYSTEM_CURSOR_IBEAM: int # Text input cursor
SYSTEM_CURSOR_WAIT: int # Wait/busy cursor
SYSTEM_CURSOR_CROSSHAIR: int # Crosshair cursor
SYSTEM_CURSOR_WAITARROW: int # Arrow with wait symbol
SYSTEM_CURSOR_SIZENWSE: int # Resize NW-SE cursor
SYSTEM_CURSOR_SIZENESW: int # Resize NE-SW cursor
SYSTEM_CURSOR_SIZEWE: int # Resize W-E cursor
SYSTEM_CURSOR_SIZENS: int # Resize N-S cursor
SYSTEM_CURSOR_SIZEALL: int # Move/resize all directions
SYSTEM_CURSOR_NO: int # Not allowed cursor
SYSTEM_CURSOR_HAND: int # Hand/pointer cursorReady-to-use cursor objects for common cursor types.
# Pre-compiled cursor objects
arrow: Cursor # Standard arrow cursor
diamond: Cursor # Diamond-shaped cursor
ball: Cursor # Ball/circle cursor
broken_x: Cursor # Broken X cursor
tri_left: Cursor # Left-pointing triangle
tri_right: Cursor # Right-pointing triangleString templates for creating custom cursors with compile().
# String templates for cursor compilation
thickarrow_strings: tuple[str, ...] # Thick arrow cursor
sizer_x_strings: tuple[str, ...] # Horizontal resize cursor
sizer_y_strings: tuple[str, ...] # Vertical resize cursor
sizer_xy_strings: tuple[str, ...] # Diagonal resize cursor
textmarker_strings: tuple[str, ...] # Text marker cursorimport pygame
import pygame.cursors
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Set different system cursors
print("Changing to different system cursors...")
# Standard arrow (default)
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)
pygame.time.wait(1000)
# Hand cursor for clickable elements
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_HAND)
pygame.time.wait(1000)
# Text input cursor
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_IBEAM)
pygame.time.wait(1000)
# Wait cursor
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_WAIT)
pygame.time.wait(1000)
# Crosshair cursor
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_CROSSHAIR)
pygame.time.wait(1000)
# Get current cursor
current_cursor = pygame.cursors.get_cursor()
print(f"Current cursor type: {current_cursor.type}")
pygame.quit()import pygame
import pygame.cursors
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Use pre-compiled cursors
cursors_to_try = [
("Arrow", pygame.cursors.arrow),
("Diamond", pygame.cursors.diamond),
("Ball", pygame.cursors.ball),
("Broken X", pygame.cursors.broken_x),
("Triangle Left", pygame.cursors.tri_left),
("Triangle Right", pygame.cursors.tri_right),
]
for name, cursor in cursors_to_try:
print(f"Setting cursor: {name}")
pygame.cursors.set_cursor(cursor)
pygame.time.wait(1500)
pygame.quit()import pygame
import pygame.cursors
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Create custom cursor from string
custom_cursor_strings = (
" XX ",
" X..X ",
" X....X ",
" X......X ",
" X........X ",
"X..........X",
" X........X ",
" X......X ",
" X....X ",
" X..X ",
" XX ",
)
# Compile the cursor
cursor_data = pygame.cursors.compile(
custom_cursor_strings,
black='X', # Character for black pixels
white='.', # Character for white pixels
xor='o' # Character for XOR pixels (unused here)
)
# Create cursor object
size = (12, 11) # Width x Height
hotspot = (6, 5) # Center point
custom_cursor = pygame.cursors.Cursor(size, hotspot, cursor_data[0], cursor_data[1])
# Set the custom cursor
pygame.cursors.set_cursor(custom_cursor)
print("Custom cursor set! Move mouse to see it.")
pygame.time.wait(3000)
pygame.quit()import pygame
import pygame.cursors
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Create a colorful cursor surface
cursor_size = (32, 32)
cursor_surface = pygame.Surface(cursor_size, pygame.SRCALPHA)
# Draw a colorful cursor
center = (cursor_size[0] // 2, cursor_size[1] // 2)
# Draw concentric circles
pygame.draw.circle(cursor_surface, (255, 0, 0, 200), center, 15)
pygame.draw.circle(cursor_surface, (0, 255, 0, 200), center, 10)
pygame.draw.circle(cursor_surface, (0, 0, 255, 200), center, 5)
# Add crosshair
pygame.draw.line(cursor_surface, (255, 255, 255), (center[0], 0), (center[0], cursor_size[1]), 2)
pygame.draw.line(cursor_surface, (255, 255, 255), (0, center[1]), (cursor_size[0], center[1]), 2)
# Create color cursor
hotspot = center # Click point at center
color_cursor = pygame.cursors.Cursor(hotspot, cursor_surface)
# Set the color cursor
pygame.cursors.set_cursor(color_cursor)
print("Color cursor set! Move mouse to see the colorful cursor.")
pygame.time.wait(5000)
pygame.quit()import pygame
import pygame.cursors
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Context-Sensitive Cursors")
# Define areas with different cursors
button_rect = pygame.Rect(100, 100, 200, 100)
text_rect = pygame.Rect(400, 200, 300, 50)
resize_rect = pygame.Rect(650, 450, 100, 100)
# Cursor for different contexts
default_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)
button_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_HAND)
text_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_IBEAM)
resize_cursor = pygame.cursors.Cursor(pygame.cursors.SYSTEM_CURSOR_SIZENWSE)
current_cursor = None
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Get mouse position
mouse_pos = pygame.mouse.get_pos()
# Determine appropriate cursor based on mouse position
new_cursor = default_cursor
if button_rect.collidepoint(mouse_pos):
new_cursor = button_cursor
elif text_rect.collidepoint(mouse_pos):
new_cursor = text_cursor
elif resize_rect.collidepoint(mouse_pos):
new_cursor = resize_cursor
# Only change cursor if different
if new_cursor != current_cursor:
pygame.cursors.set_cursor(new_cursor)
current_cursor = new_cursor
# Draw interface elements
screen.fill((240, 240, 240))
# Draw button
pygame.draw.rect(screen, (100, 150, 255), button_rect)
pygame.draw.rect(screen, (0, 0, 0), button_rect, 2)
font = pygame.font.Font(None, 36)
text = font.render("Button", True, (255, 255, 255))
text_pos = (button_rect.centerx - text.get_width()//2,
button_rect.centery - text.get_height()//2)
screen.blit(text, text_pos)
# Draw text area
pygame.draw.rect(screen, (255, 255, 255), text_rect)
pygame.draw.rect(screen, (0, 0, 0), text_rect, 2)
text_label = font.render("Text Input Area", True, (0, 0, 0))
screen.blit(text_label, (text_rect.x + 5, text_rect.y + 10))
# Draw resize area
pygame.draw.rect(screen, (255, 200, 100), resize_rect)
pygame.draw.rect(screen, (0, 0, 0), resize_rect, 2)
resize_text = font.render("Resize", True, (0, 0, 0))
resize_pos = (resize_rect.centerx - resize_text.get_width()//2,
resize_rect.centery - resize_text.get_height()//2)
screen.blit(resize_text, resize_pos)
# Draw instructions
instructions = [
"Move mouse over different areas:",
"• Button area - Hand cursor",
"• Text area - I-beam cursor",
"• Resize area - Resize cursor",
"• Other areas - Default arrow"
]
small_font = pygame.font.Font(None, 24)
y = 20
for instruction in instructions:
text_surface = small_font.render(instruction, True, (0, 0, 0))
screen.blit(text_surface, (20, y))
y += 25
pygame.display.flip()
clock.tick(60)
pygame.quit()import pygame
import pygame.cursors
import math
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Animated Cursor")
class AnimatedCursor:
def __init__(self, frames, frame_duration=100):
self.frames = frames
self.frame_duration = frame_duration
self.current_frame = 0
self.last_update = pygame.time.get_ticks()
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.frame_duration:
self.current_frame = (self.current_frame + 1) % len(self.frames)
pygame.cursors.set_cursor(self.frames[self.current_frame])
self.last_update = now
# Create spinning cursor frames
def create_spinning_cursor_frames(num_frames=8):
frames = []
cursor_size = (32, 32)
center = (cursor_size[0] // 2, cursor_size[1] // 2)
for i in range(num_frames):
surface = pygame.Surface(cursor_size, pygame.SRCALPHA)
angle = (360 / num_frames) * i
# Draw rotating arrow
length = 12
angle_rad = math.radians(angle)
end_x = center[0] + length * math.cos(angle_rad)
end_y = center[1] + length * math.sin(angle_rad)
# Arrow shaft
pygame.draw.line(surface, (255, 255, 255), center, (end_x, end_y), 3)
# Arrow head
head_angle1 = angle_rad + math.radians(150)
head_angle2 = angle_rad - math.radians(150)
head_length = 8
head1_x = end_x + head_length * math.cos(head_angle1)
head1_y = end_y + head_length * math.sin(head_angle1)
head2_x = end_x + head_length * math.cos(head_angle2)
head2_y = end_y + head_length * math.sin(head_angle2)
pygame.draw.line(surface, (255, 255, 255), (end_x, end_y), (head1_x, head1_y), 2)
pygame.draw.line(surface, (255, 255, 255), (end_x, end_y), (head2_x, head2_y), 2)
# Create cursor
cursor = pygame.cursors.Cursor(center, surface)
frames.append(cursor)
return frames
# Create animated cursor
spinner_frames = create_spinning_cursor_frames(12)
animated_cursor = AnimatedCursor(spinner_frames, frame_duration=100)
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
# Toggle between animated and normal cursor
if hasattr(animated_cursor, 'active'):
animated_cursor.active = not animated_cursor.active
if not animated_cursor.active:
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)
else:
animated_cursor.active = True
# Update animated cursor
if hasattr(animated_cursor, 'active') and animated_cursor.active:
animated_cursor.update()
# Draw instructions
screen.fill((50, 50, 50))
font = pygame.font.Font(None, 48)
text1 = font.render("Animated Cursor Demo", True, (255, 255, 255))
text2 = font.render("Press SPACE to toggle animation", True, (200, 200, 200))
screen.blit(text1, (screen.get_width()//2 - text1.get_width()//2, 200))
screen.blit(text2, (screen.get_width()//2 - text2.get_width()//2, 300))
pygame.display.flip()
clock.tick(60)
pygame.quit()import pygame
import pygame.cursors
import tempfile
import os
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Create sample XBM files for demonstration
cursor_xbm_data = """#define cursor_width 16
#define cursor_height 16
static unsigned char cursor_bits[] = {
0x00, 0x00, 0x40, 0x02, 0x60, 0x06, 0x70, 0x0e, 0x78, 0x1e, 0x7c, 0x3e,
0x7e, 0x7e, 0x7f, 0xfe, 0x7f, 0xfe, 0x7e, 0x7e, 0x6c, 0x36, 0x46, 0x62,
0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00 };"""
mask_xbm_data = """#define mask_width 16
#define mask_height 16
static unsigned char mask_bits[] = {
0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xef, 0xf7,
0xcf, 0xf3, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0xc0 };"""
# Write temporary XBM files
with tempfile.NamedTemporaryFile(mode='w', suffix='.xbm', delete=False) as cursor_file:
cursor_file.write(cursor_xbm_data)
cursor_filename = cursor_file.name
with tempfile.NamedTemporaryFile(mode='w', suffix='.xbm', delete=False) as mask_file:
mask_file.write(mask_xbm_data)
mask_filename = mask_file.name
try:
# Load cursor from XBM files
xbm_cursor_data = pygame.cursors.load_xbm(cursor_filename, mask_filename)
# Create cursor object
size = (16, 16)
hotspot = (0, 0)
xbm_cursor = pygame.cursors.Cursor(size, hotspot, xbm_cursor_data[0], xbm_cursor_data[1])
# Set the XBM cursor
pygame.cursors.set_cursor(xbm_cursor)
print("XBM cursor loaded and set!")
pygame.time.wait(3000)
except Exception as e:
print(f"Error loading XBM cursor: {e}")
finally:
# Clean up temporary files
try:
os.unlink(cursor_filename)
os.unlink(mask_filename)
except:
pass
# Restore default cursor
pygame.cursors.set_cursor(pygame.cursors.SYSTEM_CURSOR_ARROW)
pygame.quit()System cursor constants and cursor compilation characters:
# System cursor types
SYSTEM_CURSOR_ARROW: int = 0 # Standard arrow
SYSTEM_CURSOR_IBEAM: int = 1 # Text selection
SYSTEM_CURSOR_WAIT: int = 2 # Wait/loading
SYSTEM_CURSOR_CROSSHAIR: int = 3 # Crosshair/precision
SYSTEM_CURSOR_WAITARROW: int = 4 # Arrow with hourglass
SYSTEM_CURSOR_SIZENWSE: int = 5 # Resize northwest-southeast
SYSTEM_CURSOR_SIZENESW: int = 6 # Resize northeast-southwest
SYSTEM_CURSOR_SIZEWE: int = 7 # Resize west-east
SYSTEM_CURSOR_SIZENS: int = 8 # Resize north-south
SYSTEM_CURSOR_SIZEALL: int = 9 # Move/resize all directions
SYSTEM_CURSOR_NO: int = 10 # Not allowed/prohibited
SYSTEM_CURSOR_HAND: int = 11 # Hand/pointing
# Default compilation characters
DEFAULT_BLACK: str = "X" # Black pixel character
DEFAULT_WHITE: str = "." # White pixel character
DEFAULT_XOR: str = "o" # XOR pixel characterInstall with Tessl CLI
npx tessl i tessl/pypi-pygame-ce