import pygame, sys, time, os, copy
from pygame.locals import *
forest = pygame.image.load('C:/Python32/PygameImages/forest.png')
rstill = pygame.image.load('C:/Python32/PygameImages/rstill.bmp')
lstill = pygame.image.load('C:/Python32/PygameImages/lstill.bmp')
bstill = pygame.image.load('C:/Python32/PygameImages/bstill.bmp')
fstill = pygame.image.load('C:/Python32/PygameImages/fstill.bmp')
lwalk1 = pygame.image.load('C:/Python32/PygameImages/lwalk1.bmp')
lwalk2 = pygame.image.load('C:/Python32/PygameImages/lwalk2.bmp')
rwalk1 = pygame.image.load('C:/Python32/PygameImages/rwalk1.bmp')
rwalk2 = pygame.image.load('C:/Python32/PygameImages/rwalk2.bmp')
fwalk1 = pygame.image.load('C:/Python32/PygameImages/fwalk1.bmp')
fwalk2 = pygame.image.load('C:/Python32/PygameImages/fwalk2.bmp')
bwalk1 = pygame.image.load('C:/Python32/PygameImages/bwalk1.bmp')
bwalk2 = pygame.image.load('C:/Python32/PygameImages/bwalk2.bmp')
class character():
def __init__(self, walk1, still, walk2):
self.sprite = sprite
self.walk1 = walk1
self.still = still
self.walk2 = walk2
def move(self, walk1, still, walk2, sprite):
timer = clock.tick()
if timer > 9:
if sprite == walk1:
self.sprite = still
elif sprite == still:
self.sprite = walk2
elif sprite == walk2:
self.sprite = walk1
pygame.init()
screen = pygame.display.set_mode((492,360))
background = forest
sprite = bstill
spritex = 240
spritey = 300
clock = pygame.time.Clock()
walk1 = fwalk1
walk2 = fwalk2
still = fstill
Character = character(walk1,still,walk2)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if (event.key == K_LEFT):
spritex-=1
walk1 = copy.deepcopy(lwalk1)
walk2 = copy.deepcopy(lwalk2)
still = copy.deepcopy(lstill)
elif (event.key == K_RIGHT):
spritex+=1
walk1 = copy.deepcopy(rwalk1)
walk2 = copy.deepcopy(rwalk2)
still = copy.deepcopy(rstill)
elif (event.key == K_UP):
spritey-=1
walk1 = copy.deepcopy(fwalk1)
walk2 = copy.deepcopy(fwalk2)
still = copy.deepcopy(fstill)
elif (event.key == K_DOWN):
spritey+=1
walk1 = copy.deepcopy(bwalk1)
walk2 = copy.deepcopy(bwalk2)
still = copy.deepcopy(bstill)
Character.move(walk1, still, walk2, sprite)
screen.blit(background, (0,0))
screen.blit(Character.sprite, (spritex, spritey))
pygame.display.update()
我的程序从不运行 character.move 中的三个 if 语句中的任何一个(它确实运行定时器一)。我是 pygame 和类(class)的新手,有人知道我是否错过了什么大事吗? Sprite 将随着箭头键移动,但不会改变图像。 谢谢!
最佳答案
除了您与事件 Sprite 和图像对象的比较不符合 True
之外,我还没有确定您的问题。
但我想给你一些提示,这些提示会导致评论过长,并且需要结构和代码突出显示 - 所以这里有一些在处理图形和类时的一般提示。
图片是资源,不是 Sprite ,永远不应该改变。
例如,一张图片通常只加载一次。
加载后,它应该放在那里,通常您不会将其作为要针对 检查的参数传递(要么是因为要比较的数据很多,要么可能会给您带来倾斜的结果,具体取决于对象正在比较)。
考虑以下修改:
class character():
def __init__(self, direction):
self.rstill = pygame.image.load('C:/Python32/PygameImages/rstill.bmp')
self.lstill = pygame.image.load('C:/Python32/PygameImages/lstill.bmp')
self.bstill = pygame.image.load('C:/Python32/PygameImages/bstill.bmp')
self.fstill = pygame.image.load('C:/Python32/PygameImages/fstill.bmp')
self.direction = direction
if self.direction == 'up':
self.sprite = self.fstill
elif ...
else ...
def move(self, direction):
if clock.tick() > 9: # No point in variable this unless you need to use it again.
if direction == self.direction:
self.sprite = self.fstill2
elif direction == 'down':
self.sprite = self.dstill
else ...
在需要它们的类中加载图像资源,并保留更小的指针,例如它们移动的方向。
它会更容易调试并使您更容易进行比较,有时甚至对 Python 也是如此。
不确定你想做什么:
walk1 = copy.deepcopy(lwalk1)
walk2 = copy.deepcopy(lwalk2)
...
我认为这是一个 XY Problem您认为自己有解决方案的地方 - 它并不完全有效 - 所以现在您要根据该解决方案提出问题。
我猜你以为你会复制一个 Sprite 的精确副本,这样你就可以比较它们了?
如果是这样,请放弃那个想法,因为那不是你的问题所在。
相反,在您的 Sprite /角色中保留静态图像,将您现在需要显示的资源加载到 self.sprite
中,但与 self.direction
进行比较。
处理动画
我还将对如何加载每个帧添加一个小的更改,因为我猜这就是 fwalk1
和 fwalk2
的例子,两个帧应该模拟动画吗?
您可以这样做,并将它们转换为“有用”的东西,方法是将它们放在列表中并循环遍历它,并基于多个图像资源创建手动动画序列。
self.lwalk = [ret_bitmap('lwalk1.bmp'), ret_bitmap('lwalk2.bmp')]
self.rwalk = [ret_bitmap('rwalk1.bmp'), ret_bitmap('rwalk2.bmp')]
self.animation_frame = 0
理想情况下,您希望将移动、更新用户看到的内容和更改图像分开。这是三个不同的任务,尽管它们通常同时组合在一起。
def move(x, y):
# Should be in charge of moving the character and changing sprite
def update(direction):
# Should be in charge of animation updates etc.
def get_image():
# should return the current active frame/image (since you're working with animations)
如果您将所有这些结合起来,并调整我们在这里修改和经历的事情。
您的类和代码应如下所示:
import pygame, sys, time, os, copy
from pygame.locals import *
def ret_bitmap(fname):
return pygame.image.load('C:/Python32/PygameImages/' + rstill.bmp)
class character():
def __init__(self, x=0, y=0, direction='up'):
self.rstill = [ret_bitmap('rstill.bmp')]
self.lstill = [ret_bitmap('lstill.bmp')]
self.bstill = [ret_bitmap('bstill.bmp')]
self.fstill = [ret_bitmap('fstill.bmp')]
self.lwalk = [ret_bitmap('lwalk1.bmp'), ret_bitmap('lwalk2.bmp')]
self.rwalk = [ret_bitmap('rwalk1.bmp'), ret_bitmap('rwalk2.bmp')]
self.fwalk = [ret_bitmap('fwalk1.bmp'), ret_bitmap('fwalk2.bmp')]
self.bwalk = [ret_bitmap('bwalk1.bmp'), ret_bitmap('bwalk2.bmp')]
self.direction = direction
self.animation_frame = 0
self.x, self.y = x, y
## == Load the first frame to show the user
## Note: We don't load the image, we load the list.
if self.direction == 'up':
self.sprite = self.fwalk
elif self.direction == 'down':
self.sprite = self.bwalk
elif self.direction == 'left':
self.sprite = self.lwalk
else:
self.sprite = self.rwalk
def move(self, direction):
self.direction = direction
if direction == 'left':
self.x -= 1
self.sprite = self.lwalk
elif direction == 'right':
self.x += 1
self.sprite = self.rwalk
elif direction == 'up':
self.y += 1
self.sprite = self.fwalk
else: # Down
self.y -= 1
self.sprite = self.bwalk
def update(self, direction):
if clock.tick() > 9:
self.animation_frame += 1
if self.animation_frame > len(self.sprite):
self.animation_frame = 0
def get_image(self):
return self.sprite[self.animation_frame]
pygame.init()
screen = pygame.display.set_mode((492,360))
clock = pygame.time.Clock()
Character = character(x=240, y=300, direction='down')
background = ret_bitmap('forest.png')
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if (event.key == K_LEFT):
Character.move('left')
elif (event.key == K_RIGHT):
Character.move('right')
elif (event.key == K_UP):
Character.move('up')
elif (event.key == K_DOWN):
Character.move('down')
Character.update() # Just updates the animation frame, if the time is right
screen.blit(background, (0,0))
screen.blit(Character.get_image(), (Character.x, Character.y))
pygame.display.update()
请记住,我没有安装 Pygame。
我可能已经包括了你原来的问题,我认为 DCA-
指出的与计时器有关。
我不太确定计时器在 Pygame 中是如何工作的,因为我自己使用 Pyglet,我通常通过 import time 自己跟踪计时;时间.时间()
。尽管如此,您还是可以将正确答案合并到此代码中。
或者开箱即用?谁知道:)
添加动画
有一种方法可以为相同的动画序列使用相同的位图。
这可能被称为花哨的东西,我称之为“图像动画区域”。
考虑下图。
您只需为每帧分配一个特定区域,并在每次调用 def update()
时裁剪图像。
您可以通过以下方式实现此目的:
x = pygame.image.load(filename)
x.get_rect(x, y, width, height)
本质上是重复使用同一张图片,只是向用户展示该图片的不同区域。它的性能通常比必须在图形上下文中更改某些内容(即更改事件图像)要高得多。
因此,为了将来,考虑在处理动画时实现这一点。
祝你的项目好运,我希望它成功! :)
关于python - 我无法让我的类(class)在 pygame 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37681848/