Module pacai.ui.spritesheet
The graphics for pacman are held in a spritesheet. This file knows how to read a spritesheet and map sprites to tokens.
Expand source code
"""
The graphics for pacman are held in a spritesheet.
This file knows how to read a spritesheet and map sprites to tokens.
"""
from PIL import Image
from pacai.core.directions import Directions
from pacai.ui import token
# The size of each sprite square.
SQUARE_SIZE = 50
# The row where several miscellaneous items appear on.
MISC_ROW = 13
# The different types of food that appear.
SPRITE_SHEET_FOOD_TYPES = [
token.DEFAULT_FOOD_BASE,
token.RED_FOOD_BASE,
token.BLUE_FOOD_BASE,
]
# The different wall types that appear (their base token number and spritesheet row).
SPRITE_SHEET_WALL_TYPES = [
(token.BLUE_WALL_BASE, 14),
(token.RED_WALL_BASE, 15),
]
# The order that the wall sprites appear in the sheet.
# True indicates that there is a wall adjacent in that cardinal direction (N, E, S, W).
# See token.getWallToken().
SPRITE_SHEET_WALL_ORDER = [
(False, False, False, False),
(False, False, False, True),
(False, False, True, False),
(False, False, True, True),
(False, True, False, False),
(False, True, False, True),
(False, True, True, False),
(False, True, True, True),
(True, False, False, False),
(True, False, False, True),
(True, False, True, False),
(True, False, True, True),
(True, True, False, False),
(True, True, False, True),
(True, True, True, False),
(True, True, True, True),
]
# The different types of agents in the spritesheet.
SPRITE_SHEET_AGENTS = [
(token.PACMAN_1, 0),
(token.PACMAN_2, 1),
(token.PACMAN_3, 2),
(token.PACMAN_4, 3),
(token.PACMAN_5, 4),
(token.PACMAN_6, 5),
(token.PACMAN_7, 6),
(token.GHOST_1, 7),
(token.GHOST_2, 8),
(token.GHOST_3, 9),
(token.GHOST_4, 10),
(token.GHOST_5, 11),
(token.GHOST_6, 12),
]
def loadSpriteSheet(path):
spritesheet = Image.open(path)
sprites = {}
# Load the food.
miscColumnIndex = 0
for foodTypeBase in SPRITE_SHEET_FOOD_TYPES:
for foodItem in [token.FOOD_OFFSET, token.CAPSULE_OFFSET]:
foodToken = foodTypeBase + foodItem
sprites[foodToken] = _cropSprite(spritesheet, MISC_ROW, miscColumnIndex)
miscColumnIndex += 1
# The scared ghost is after the food.
sprites[token.SCARED_GHOST_TOKEN] = _cropSprite(spritesheet, MISC_ROW, miscColumnIndex)
# Load all the wall sprites.
for (wallTypeBase, row) in SPRITE_SHEET_WALL_TYPES:
for wallIndex in range(len(SPRITE_SHEET_WALL_ORDER)):
adjacentWalls = SPRITE_SHEET_WALL_ORDER[wallIndex]
wallToken = token.getWallToken(wallTypeBase, *adjacentWalls)
sprites[wallToken] = _cropSprite(spritesheet, row, wallIndex)
# Load all the agents.
for (agentBaseToken, row) in SPRITE_SHEET_AGENTS:
# Load the stopped sprite.
sprites[agentBaseToken] = _cropSprite(spritesheet, row, 0)
# Now load animations.
for direction in Directions.CARDINAL:
for frame in range(token.ANIMATION_CYCLE):
# We need the offset to crop the sprite, so pass 0 in as the base token.
animationOffset = token.getAnimationToken(0, direction, frame)
agentToken = agentBaseToken + animationOffset
sprites[agentToken] = _cropSprite(spritesheet, row, animationOffset)
return sprites
def _cropSprite(spritesheet, row, col):
# (left, upper, right, lower)
rectangle = (
col * SQUARE_SIZE,
row * SQUARE_SIZE,
(col + 1) * SQUARE_SIZE,
(row + 1) * SQUARE_SIZE,
)
return spritesheet.crop(rectangle)
Functions
def loadSpriteSheet(path)
-
Expand source code
def loadSpriteSheet(path): spritesheet = Image.open(path) sprites = {} # Load the food. miscColumnIndex = 0 for foodTypeBase in SPRITE_SHEET_FOOD_TYPES: for foodItem in [token.FOOD_OFFSET, token.CAPSULE_OFFSET]: foodToken = foodTypeBase + foodItem sprites[foodToken] = _cropSprite(spritesheet, MISC_ROW, miscColumnIndex) miscColumnIndex += 1 # The scared ghost is after the food. sprites[token.SCARED_GHOST_TOKEN] = _cropSprite(spritesheet, MISC_ROW, miscColumnIndex) # Load all the wall sprites. for (wallTypeBase, row) in SPRITE_SHEET_WALL_TYPES: for wallIndex in range(len(SPRITE_SHEET_WALL_ORDER)): adjacentWalls = SPRITE_SHEET_WALL_ORDER[wallIndex] wallToken = token.getWallToken(wallTypeBase, *adjacentWalls) sprites[wallToken] = _cropSprite(spritesheet, row, wallIndex) # Load all the agents. for (agentBaseToken, row) in SPRITE_SHEET_AGENTS: # Load the stopped sprite. sprites[agentBaseToken] = _cropSprite(spritesheet, row, 0) # Now load animations. for direction in Directions.CARDINAL: for frame in range(token.ANIMATION_CYCLE): # We need the offset to crop the sprite, so pass 0 in as the base token. animationOffset = token.getAnimationToken(0, direction, frame) agentToken = agentBaseToken + animationOffset sprites[agentToken] = _cropSprite(spritesheet, row, animationOffset) return sprites