用途:通过不同的序列图片在界面上展示连贯的动画
结果如下:
参考文章:pygame之旅 - 知乎 (zhihu.com)
项目结构目录
角色类
import os
import pygame,sys
dir = "persent/magic/"
class Hero(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.kinds = ["attack","hit","idle","miss"] # 角色的所有动作
self.state = 'idle' # 当前状态
self.current_frame = -1 # 当前动作序列的到第几张
self.current_image = None # 当前动作序列对应的图片
self.all_frame = {} # 所有的动作,表现为"动作名称":动作序列
self.frames = [] # 当前动作序列
self.last_updated = 0 #更新的时间
# 设置绘制的主屏幕,上层传入
def setScreen(self,screen):
self.screen = screen
#更新动作
def update(self):
self.handle_state() # 切换动作
self.animate() # 连贯一个动作
self.screen.blit(self.current_image,self.rect)# 绘制
# 切换当前动作的序列帧
def animate(self):
now = pygame.time.get_ticks()
if now - self.last_updated > 100:
self.last_updated = now
self.current_frame = (self.current_frame + 1) % len(self.frames)
self.current_image = self.frames[self.current_frame]
# 初始化时加载图片
def load_image(self):
listName = "hero"+str(self.ID) # 人物文件夹名字
for i in self.kinds: # 任务文件夹下面的几个动作名字
self.all_frame.setdefault(i,[]) # 设置"动作名":列表
frames = os.listdir(dir+listName+'/'+i) # 获取动作的所有图片名字
for j in frames: # 遍历所有图片
filename = dir+listName+'/'+i+'/'+j # 组装成对应可以读取名字
print(filename)
# 读取图片
self.all_frame[i].append(
pygame.image.load(filename)
)
self.state = self.kinds[2] # 将状态切换为idle
self.handle_state() # 更新对应序列
self.current_frame = 0 # 重置当前帧
self.current_image = self.all_frame.get('idle')[0] # 设置当前图片
self.rect = self.all_frame.get('idle')[0].get_rect() # 获取图片对应
self.rect.midbottom = (100,100)# 设置图片大小
# 设置图片位置
self.rect.x = 100
self.rect.y = 100
# 更换当前动作状态序列帧
def handle_state(self):
if self.state == 'idle':
self.frames = self.all_frame.get("idle")
elif self.state == "hit":
self.frames = self.all_frame.get("hit")
elif self.state == "miss":
self.frames = self.all_frame.get("miss")
elif self.state == "attack":
self.frames = self.all_frame.get("attack")
# ["attack","hit","idle","miss"] 改变角色状态
def changeState(self,num:int):
if num >0 and num<len(self.kinds):# 在规定的状态里面
if self.state != self.kinds[num]:# 状态改变
self.current_frame = 0
self.state = self.kinds[num] # 修改状态
角色生成类:
class heroProduct:
def __init__(self,screen):
self.screen = screen
# 创建一个人物
def createHero(self):
hero = Hero()
hero.setScreen(screen)
hero.load_image()
return hero
代码入口
import pygame
import persent.script.Heroproduct as Heroproduct
import persent.script.AbilityManage as AbilityManage
pygame.init()
pygame.display.set_caption("hight") # 设置窗口名字
screen_width, screen_height = 560, 780 # 设置窗口大小
screen = pygame.display.set_mode((screen_width, screen_height))
clock = pygame.time.Clock() # 设置时钟
heroproduct = Heroproduct.heroProduct(screen)
hero = heroproduct.createHero()
start = True
while start:
clock.tick(60)
hero.update()
for event in pygame.event.get(): # 循环获取事件
if event.type == pygame.QUIT: # 若检测到事件类型为退出,则退出系统
start = False
if event.type == pygame.KEYDOWN:
# 具体是哪一个按键的处理
if event.key == pygame.K_0:
hero.changeState(0)
elif event.key == pygame.K_1:
hero.changeState(1)
elif event.key == pygame.K_2:
hero.changeState(2)
elif event.key == pygame.K_3:
hero.changeState(3)
pygame.display.update() # 更新屏幕内容
pygame.quit()
结果如下:
发现出现问题,动画出现残影,看网上说需要先绘制背景,再绘制角色可以解决,随意填个颜色screen.fill(255)
while start:
clock.tick(60)
screen.fill(255)
hero.update()
pygame.display.update() # 更新屏幕内容
for event in pygame.event.get(): # 循环获取事件
if event.type == pygame.QUIT: # 若检测到事件类型为退出,则退出系统
start = False
if event.type == pygame.KEYDOWN:
# 具体是哪一个按键的处理
if event.key == pygame.K_0:
hero.changeState(0)
elif event.key == pygame.K_1:
hero.changeState(1)
elif event.key == pygame.K_2:
hero.changeState(2)
elif event.key == pygame.K_3:
hero.changeState(3)
问题解决