pygame 中的 Spritesheet 帮助
Spritesheet help in pygame
我目前正在开发一款游戏,试图提高我的新手 python 技能。我的游戏在最基本的水平上运行 - 在我可以为我的精灵设置动画之前,我无法让自己继续开发它。这让我最头疼——因为盯着别人的代码看了好几个小时,复制和粘贴都无济于事,还看了无数的 youtube 视频。出于某种原因,我似乎无法理解如何从 spritesheet 中剥离图像的基本概念。我已经在 pygame 网站上看到它了,我就是不明白。我跟着孩子们会编码,但他的 spritesheet 有一个 'xml'?附加文件,这样他就可以复制并粘贴坐标。我的 spritesheet 是 192x192 像素,所以我试图通过以 48 分隔的坐标 load/split 图像。例如 - (0,0,48,0)。根据他的示例,我假设这些变量是 x、y、previousSpriteEndingx、previousSpriteEndingy,还因为这是我唯一能理解的东西。我将每个精灵位置分组到相应方向的列表中——上、下、左和右。 (我不想翻译和翻转我的 L/R,但现在我正在考虑,这会让我的游戏更快吗?因为它不必加载 4 个新图像?)
我终于明白了 运行,但它并没有显示我的精灵,它只是一个随着移动而宽度增加的黑框,但看起来它太大了,不能成为我的精灵。所以我知道我在坐标上做错了(当我按下时盒子消失了)。如果有人可以给我一个工作示例,我可以将其复制并粘贴到 运行 并进行剖析,请对其进行解释,以便初学者可以轻松理解,或者(我把最好的留到最后)在下面粘贴的代码中实现一些东西,我将永远感激不已。上次我在这里发帖时得到了很大的帮助,我希望能复制这些结果。这是我的 SpriteSheet 的 link
https://ibb.co/eZbd2G
import pygame
WIDTH = 1000
HEIGHT = 700
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
width = 25
height = 25
image = pygame.image.load("CharacterSprite.png")
self.image = pygame.transform.scale(image, (width, height))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2 - 480 #center of rectangle
self.rect.bottom = HEIGHT - 5 #pixels up from the bottom
self.speedx = 0
self.speedy = 0
self.walkingright = []
self.walkingleft = []
self.walkingup = []
self.walkingdown = []
self.direction = 'R'
#Facing Down
sprite_sheet = SpriteSheet('CharacterSprite.png')
image = sprite_sheet.get_image(0,0,48,0)
self.walkingdown.append(image)
image = sprite_sheet.get_image(48,0,96,0)
self.walkingdown.append(image)
image = sprite_sheet.get_image(96,0,144,0)
self.walkingdown.append(image)
image = sprite_sheet.get_image(144,0,192,0)
self.walkingdown.append(image)
#Facing Up
image = sprite_sheet.get_image(192,144,48,144)
self.walkingup.append(image)
image = sprite_sheet.get_image(48,144,96,144)
self.walkingup.append(image)
image = sprite_sheet.get_image(96,144,144,144)
self.walkingup.append(image)
image = sprite_sheet.get_image(144,144,192,144)
self.walkingup.append(image)
#Facing Right
image = sprite_sheet.get_image(192,96,48,96)
self.walkingright.append(image)
image = sprite_sheet.get_image(48,96,96,96)
self.walkingright.append(image)
image = sprite_sheet.get_image(96,96,144,96)
self.walkingright.append(image)
image = sprite_sheet.get_image(144,96,192,96)
self.walkingright.append(image)
#FacingLeft
image = sprite_sheet.get_image(192,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(48,48,96,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(96,48,144,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(144,48,192,48)
self.walkingleft.append(image)
def update(self):
pos = self.rect.x
if self.direction == "R":
frame = (pos // 30) % len(self.walkingright)
self.image = self.walkingright[frame]
if self.direction == "L":
frame = (pos // 30) % len(self.walkingleft)
self.image = self.walkingleft[frame]
if self.direction == "U":
frame = (pos // 30) % len(self.walkingup)
self.image = self.walkingup[frame]
if self.direction == "D":
frame = (pos // 30) % len(self.walkingdown)
self.image = self.walkingdown[frame]
self.speedx = 0 #Need these to make sure
self.speedy = 0 #Sprite stops moving on keyup
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -5
self.direction = 'L'
if keystate[pygame.K_RIGHT]:
self.speedx = 5
self.direction = 'R'
if keystate[pygame.K_UP]:
self.speedy = -5
self.direction = 'U'
if keystate[pygame.K_DOWN]:
self.speedy = 5
self.direction = 'D'
self.rect.x += self.speedx
self.rect.y += self.speedy
#Set Walls for Width and Height
if self.rect.right > WIDTH:
self.rect.rect = WIDTH
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name)
def get_image(self, x, y, width, height):
image = pygame.Surface([width, height])
image.blit(self.sprite_sheet, (0,0), (x, y, width, height))
image.set_colorkey(BLUE)
return image
def update(self):
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
self.rect.x += self.speedx
#kill if it goes off screen
if self.rect.left > WIDTH:
self.kill()
#Loading Graphics
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
projectiles = pygame.sprite.Group()
#Spawn x amount of mobs, add to all sprites and mobs
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
#Update Game Loop
all_sprites.update()
screen.fill(WHITE)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
这是您程序的工作版本(阅读评论)。主要问题是您没有将正确的宽度和高度 (48) 作为第三个和第四个参数传递给 sprite_sheet.get_image
。
要加载透明图像,您可以调用 convert_alpha()
:
self.sprite_sheet = pygame.image.load(file_name).convert_alpha()
并且在 Player
的 update
方法中,您还需要垂直移动的 y 坐标。
if self.direction == "U":
frame = (pos_y // 30) % len(self.walkingup)
import pygame
WIDTH = 1000
HEIGHT = 700
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
width = 25
height = 25
sheet = pygame.image.load('Character_Sprite.png').convert_alpha()
self.image = pygame.transform.scale(sheet, (48, 48))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2 - 480 #center of rectangle
self.rect.bottom = HEIGHT - 5 #pixels up from the bottom
self.speedx = 0
self.speedy = 0
self.walkingright = []
self.walkingleft = []
self.walkingup = []
self.walkingdown = []
self.direction = 'R'
sprite_sheet = SpriteSheet('Character_Sprite.png')
#Facing Down
# Start at x = 0. Pass 48 as the third and
# fourth argument (width and height).
image = sprite_sheet.get_image(0,0,48,48)
self.walkingdown.append(image)
image = sprite_sheet.get_image(48,0,48,48)
self.walkingdown.append(image)
image = sprite_sheet.get_image(96,0,48,48)
self.walkingdown.append(image)
image = sprite_sheet.get_image(144,0,48,48)
self.walkingdown.append(image)
#Facing Up
image = sprite_sheet.get_image(0,144,48,48)
self.walkingup.append(image)
image = sprite_sheet.get_image(48,144,48,48)
self.walkingup.append(image)
image = sprite_sheet.get_image(96,144,48,48)
self.walkingup.append(image)
image = sprite_sheet.get_image(144,144,48,48)
self.walkingup.append(image)
#Facing Right
image = sprite_sheet.get_image(0,96,48,48)
self.walkingright.append(image)
image = sprite_sheet.get_image(48,96,48,48)
self.walkingright.append(image)
image = sprite_sheet.get_image(96,96,48,48)
self.walkingright.append(image)
image = sprite_sheet.get_image(144,96,48,48)
self.walkingright.append(image)
#Facing Left
image = sprite_sheet.get_image(0,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(48,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(96,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(144,48,48,48)
self.walkingleft.append(image)
def update(self):
pos_x = self.rect.x
# You also need the y position for the vertical movement.
pos_y = self.rect.y
if self.direction == "R":
frame = (pos_x // 30) % len(self.walkingright)
self.image = self.walkingright[frame]
if self.direction == "L":
frame = (pos_x // 30) % len(self.walkingleft)
self.image = self.walkingleft[frame]
if self.direction == "U":
frame = (pos_y // 30) % len(self.walkingup)
self.image = self.walkingup[frame]
if self.direction == "D":
frame = (pos_y // 30) % len(self.walkingdown)
self.image = self.walkingdown[frame]
self.speedx = 0 #Need these to make sure
self.speedy = 0 #Sprite stops moving on keyup
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -5
self.direction = 'L'
if keystate[pygame.K_RIGHT]:
self.speedx = 5
self.direction = 'R'
if keystate[pygame.K_UP]:
self.speedy = -5
self.direction = 'U'
if keystate[pygame.K_DOWN]:
self.speedy = 5
self.direction = 'D'
self.rect.x += self.speedx
self.rect.y += self.speedy
#Set Walls for Width and Height
if self.rect.right > WIDTH:
self.rect.rect = WIDTH
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
class SpriteSheet(object):
def __init__(self, file_name):
# You have to call `convert_alpha`, so that the background of
# the surface is transparent.
self.sprite_sheet = pygame.image.load(file_name).convert_alpha()
def get_image(self, x, y, width, height):
# Use a transparent surface as the base image (pass pygame.SRCALPHA).
image = pygame.Surface([width, height], pygame.SRCALPHA)
image.blit(self.sprite_sheet, (0,0), (x, y, width, height))
return image
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
all_sprites.update()
screen.fill(WHITE)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
您还可以使用一些 for 循环来缩短精灵 sheet 切割代码:
# Facing Up
for x in range(0, 144+1, 48): # 144+1 because the `stop` is exclusive.
self.walkingdown.append(sprite_sheet.get_image(x, 0, 48, 48))
# Facing Up
for x in range(0, 144+1, 48):
self.walkingup.append(sprite_sheet.get_image(x, 144, 48, 48))
# Facing Right
for x in range(0, 144+1, 48):
self.walkingright.append(sprite_sheet.get_image(x, 96, 48, 48))
# Facing Left
for x in range(0, 144+1, 48):
self.walkingleft.append(sprite_sheet.get_image(x, 48, 48, 48))
这里有一个更短的方法来削减 sheet。您可以遍历图像列表并枚举它们以获取 y 索引并为 x 坐标添加一个嵌套的 for
循环,然后使用 pygame.Surface.subsurface
切出次表面。不再需要 SpriteSheet
class。
image_lists = (self.walkingdown, self.walkingleft, self.walkingright, self.walkingup)
for y, img_list in enumerate(image_lists): # Enumerate to get the y-position.
for x in range(4):
# Multiply x and y by 48 to get the correct coords and use the
# `subsurface` to cut the sheet into separate images.
img_list.append(sheet.subsurface(x*48, y*48, 48, 48))
@skrx already described all problems I only add that you can use pygame.Surface.subsurface 创建框架。
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert_alpha()
def get_image(self, x, y, width, height):
return self.sprite_sheet.subsurface((x, y, width, height))
我目前正在开发一款游戏,试图提高我的新手 python 技能。我的游戏在最基本的水平上运行 - 在我可以为我的精灵设置动画之前,我无法让自己继续开发它。这让我最头疼——因为盯着别人的代码看了好几个小时,复制和粘贴都无济于事,还看了无数的 youtube 视频。出于某种原因,我似乎无法理解如何从 spritesheet 中剥离图像的基本概念。我已经在 pygame 网站上看到它了,我就是不明白。我跟着孩子们会编码,但他的 spritesheet 有一个 'xml'?附加文件,这样他就可以复制并粘贴坐标。我的 spritesheet 是 192x192 像素,所以我试图通过以 48 分隔的坐标 load/split 图像。例如 - (0,0,48,0)。根据他的示例,我假设这些变量是 x、y、previousSpriteEndingx、previousSpriteEndingy,还因为这是我唯一能理解的东西。我将每个精灵位置分组到相应方向的列表中——上、下、左和右。 (我不想翻译和翻转我的 L/R,但现在我正在考虑,这会让我的游戏更快吗?因为它不必加载 4 个新图像?)
我终于明白了 运行,但它并没有显示我的精灵,它只是一个随着移动而宽度增加的黑框,但看起来它太大了,不能成为我的精灵。所以我知道我在坐标上做错了(当我按下时盒子消失了)。如果有人可以给我一个工作示例,我可以将其复制并粘贴到 运行 并进行剖析,请对其进行解释,以便初学者可以轻松理解,或者(我把最好的留到最后)在下面粘贴的代码中实现一些东西,我将永远感激不已。上次我在这里发帖时得到了很大的帮助,我希望能复制这些结果。这是我的 SpriteSheet 的 link https://ibb.co/eZbd2G
import pygame
WIDTH = 1000
HEIGHT = 700
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
width = 25
height = 25
image = pygame.image.load("CharacterSprite.png")
self.image = pygame.transform.scale(image, (width, height))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2 - 480 #center of rectangle
self.rect.bottom = HEIGHT - 5 #pixels up from the bottom
self.speedx = 0
self.speedy = 0
self.walkingright = []
self.walkingleft = []
self.walkingup = []
self.walkingdown = []
self.direction = 'R'
#Facing Down
sprite_sheet = SpriteSheet('CharacterSprite.png')
image = sprite_sheet.get_image(0,0,48,0)
self.walkingdown.append(image)
image = sprite_sheet.get_image(48,0,96,0)
self.walkingdown.append(image)
image = sprite_sheet.get_image(96,0,144,0)
self.walkingdown.append(image)
image = sprite_sheet.get_image(144,0,192,0)
self.walkingdown.append(image)
#Facing Up
image = sprite_sheet.get_image(192,144,48,144)
self.walkingup.append(image)
image = sprite_sheet.get_image(48,144,96,144)
self.walkingup.append(image)
image = sprite_sheet.get_image(96,144,144,144)
self.walkingup.append(image)
image = sprite_sheet.get_image(144,144,192,144)
self.walkingup.append(image)
#Facing Right
image = sprite_sheet.get_image(192,96,48,96)
self.walkingright.append(image)
image = sprite_sheet.get_image(48,96,96,96)
self.walkingright.append(image)
image = sprite_sheet.get_image(96,96,144,96)
self.walkingright.append(image)
image = sprite_sheet.get_image(144,96,192,96)
self.walkingright.append(image)
#FacingLeft
image = sprite_sheet.get_image(192,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(48,48,96,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(96,48,144,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(144,48,192,48)
self.walkingleft.append(image)
def update(self):
pos = self.rect.x
if self.direction == "R":
frame = (pos // 30) % len(self.walkingright)
self.image = self.walkingright[frame]
if self.direction == "L":
frame = (pos // 30) % len(self.walkingleft)
self.image = self.walkingleft[frame]
if self.direction == "U":
frame = (pos // 30) % len(self.walkingup)
self.image = self.walkingup[frame]
if self.direction == "D":
frame = (pos // 30) % len(self.walkingdown)
self.image = self.walkingdown[frame]
self.speedx = 0 #Need these to make sure
self.speedy = 0 #Sprite stops moving on keyup
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -5
self.direction = 'L'
if keystate[pygame.K_RIGHT]:
self.speedx = 5
self.direction = 'R'
if keystate[pygame.K_UP]:
self.speedy = -5
self.direction = 'U'
if keystate[pygame.K_DOWN]:
self.speedy = 5
self.direction = 'D'
self.rect.x += self.speedx
self.rect.y += self.speedy
#Set Walls for Width and Height
if self.rect.right > WIDTH:
self.rect.rect = WIDTH
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name)
def get_image(self, x, y, width, height):
image = pygame.Surface([width, height])
image.blit(self.sprite_sheet, (0,0), (x, y, width, height))
image.set_colorkey(BLUE)
return image
def update(self):
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
self.rect.x += self.speedx
#kill if it goes off screen
if self.rect.left > WIDTH:
self.kill()
#Loading Graphics
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
projectiles = pygame.sprite.Group()
#Spawn x amount of mobs, add to all sprites and mobs
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
#Update Game Loop
all_sprites.update()
screen.fill(WHITE)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
这是您程序的工作版本(阅读评论)。主要问题是您没有将正确的宽度和高度 (48) 作为第三个和第四个参数传递给 sprite_sheet.get_image
。
要加载透明图像,您可以调用 convert_alpha()
:
self.sprite_sheet = pygame.image.load(file_name).convert_alpha()
并且在 Player
的 update
方法中,您还需要垂直移动的 y 坐标。
if self.direction == "U":
frame = (pos_y // 30) % len(self.walkingup)
import pygame
WIDTH = 1000
HEIGHT = 700
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
width = 25
height = 25
sheet = pygame.image.load('Character_Sprite.png').convert_alpha()
self.image = pygame.transform.scale(sheet, (48, 48))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2 - 480 #center of rectangle
self.rect.bottom = HEIGHT - 5 #pixels up from the bottom
self.speedx = 0
self.speedy = 0
self.walkingright = []
self.walkingleft = []
self.walkingup = []
self.walkingdown = []
self.direction = 'R'
sprite_sheet = SpriteSheet('Character_Sprite.png')
#Facing Down
# Start at x = 0. Pass 48 as the third and
# fourth argument (width and height).
image = sprite_sheet.get_image(0,0,48,48)
self.walkingdown.append(image)
image = sprite_sheet.get_image(48,0,48,48)
self.walkingdown.append(image)
image = sprite_sheet.get_image(96,0,48,48)
self.walkingdown.append(image)
image = sprite_sheet.get_image(144,0,48,48)
self.walkingdown.append(image)
#Facing Up
image = sprite_sheet.get_image(0,144,48,48)
self.walkingup.append(image)
image = sprite_sheet.get_image(48,144,48,48)
self.walkingup.append(image)
image = sprite_sheet.get_image(96,144,48,48)
self.walkingup.append(image)
image = sprite_sheet.get_image(144,144,48,48)
self.walkingup.append(image)
#Facing Right
image = sprite_sheet.get_image(0,96,48,48)
self.walkingright.append(image)
image = sprite_sheet.get_image(48,96,48,48)
self.walkingright.append(image)
image = sprite_sheet.get_image(96,96,48,48)
self.walkingright.append(image)
image = sprite_sheet.get_image(144,96,48,48)
self.walkingright.append(image)
#Facing Left
image = sprite_sheet.get_image(0,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(48,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(96,48,48,48)
self.walkingleft.append(image)
image = sprite_sheet.get_image(144,48,48,48)
self.walkingleft.append(image)
def update(self):
pos_x = self.rect.x
# You also need the y position for the vertical movement.
pos_y = self.rect.y
if self.direction == "R":
frame = (pos_x // 30) % len(self.walkingright)
self.image = self.walkingright[frame]
if self.direction == "L":
frame = (pos_x // 30) % len(self.walkingleft)
self.image = self.walkingleft[frame]
if self.direction == "U":
frame = (pos_y // 30) % len(self.walkingup)
self.image = self.walkingup[frame]
if self.direction == "D":
frame = (pos_y // 30) % len(self.walkingdown)
self.image = self.walkingdown[frame]
self.speedx = 0 #Need these to make sure
self.speedy = 0 #Sprite stops moving on keyup
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -5
self.direction = 'L'
if keystate[pygame.K_RIGHT]:
self.speedx = 5
self.direction = 'R'
if keystate[pygame.K_UP]:
self.speedy = -5
self.direction = 'U'
if keystate[pygame.K_DOWN]:
self.speedy = 5
self.direction = 'D'
self.rect.x += self.speedx
self.rect.y += self.speedy
#Set Walls for Width and Height
if self.rect.right > WIDTH:
self.rect.rect = WIDTH
if self.rect.left < 0:
self.rect.left = 0
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > HEIGHT:
self.rect.bottom = HEIGHT
class SpriteSheet(object):
def __init__(self, file_name):
# You have to call `convert_alpha`, so that the background of
# the surface is transparent.
self.sprite_sheet = pygame.image.load(file_name).convert_alpha()
def get_image(self, x, y, width, height):
# Use a transparent surface as the base image (pass pygame.SRCALPHA).
image = pygame.Surface([width, height], pygame.SRCALPHA)
image.blit(self.sprite_sheet, (0,0), (x, y, width, height))
return image
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
all_sprites.update()
screen.fill(WHITE)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
您还可以使用一些 for 循环来缩短精灵 sheet 切割代码:
# Facing Up
for x in range(0, 144+1, 48): # 144+1 because the `stop` is exclusive.
self.walkingdown.append(sprite_sheet.get_image(x, 0, 48, 48))
# Facing Up
for x in range(0, 144+1, 48):
self.walkingup.append(sprite_sheet.get_image(x, 144, 48, 48))
# Facing Right
for x in range(0, 144+1, 48):
self.walkingright.append(sprite_sheet.get_image(x, 96, 48, 48))
# Facing Left
for x in range(0, 144+1, 48):
self.walkingleft.append(sprite_sheet.get_image(x, 48, 48, 48))
这里有一个更短的方法来削减 sheet。您可以遍历图像列表并枚举它们以获取 y 索引并为 x 坐标添加一个嵌套的 for
循环,然后使用 pygame.Surface.subsurface
切出次表面。不再需要 SpriteSheet
class。
image_lists = (self.walkingdown, self.walkingleft, self.walkingright, self.walkingup)
for y, img_list in enumerate(image_lists): # Enumerate to get the y-position.
for x in range(4):
# Multiply x and y by 48 to get the correct coords and use the
# `subsurface` to cut the sheet into separate images.
img_list.append(sheet.subsurface(x*48, y*48, 48, 48))
@skrx already described all problems I only add that you can use pygame.Surface.subsurface 创建框架。
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert_alpha()
def get_image(self, x, y, width, height):
return self.sprite_sheet.subsurface((x, y, width, height))