Python Pygame:试图理解Sprite类
我在上找到了一个名为Python Pygame:试图理解Sprite类,python,pygame,Python,Pygame,我在上找到了一个名为Sprite的类。我读了解释,但我不明白这门课是用来做什么的 我知道我们用它来继承构造函数中的其他类,但仅此而已 如果有人清楚地解释了该课程的有用性,以及如何使用它,我很感兴趣。对,所以移动鼠标光标。那是雪碧 这是一个方形位图,具有一定的透明度。但是只有可见的部分才有意义——例如,你不在乎透明部分是否移动到了某个屏幕元素上 在PyGame中,它们是相似的 在过去;)大多数街机游戏使用精灵类型的动画。想想(大约1980年);那是一张黄色的大嘴巴。它被实现为一个精灵。让我们做一个
Sprite
的类。我读了解释,但我不明白这门课是用来做什么的
我知道我们用它来继承构造函数中的其他类,但仅此而已
如果有人清楚地解释了该课程的有用性,以及如何使用它,我很感兴趣。对,所以移动鼠标光标。那是雪碧 这是一个方形位图,具有一定的透明度。但是只有可见的部分才有意义——例如,你不在乎透明部分是否移动到了某个屏幕元素上 在PyGame中,它们是相似的 在过去;)大多数街机游戏使用精灵类型的动画。想想(大约1980年);那是一张黄色的大嘴巴。它被实现为一个精灵。让我们做一个: 现在这个东西必须在屏幕上移动,透明的像素(浅灰色和深灰色)需要显示背景。重要的是,对于PacMan来说并不是如此,但对于更多的锯齿图像,任何透明的东西都不应该成为碰撞检测的一部分。这是精灵的另一个重要方面 假设《吃豆人》中的敌人鬼魂发射了子弹(哇,这是一个可怕的想法!),如果子弹穿过吃豆人精灵的透明角落,你会非常不安,但这仍然被认为是“击中”。为了正确地实现这一点,使用了一种新的方法。这基本上是另一个逻辑位图,说明哪些像素将被视为冲突精灵的一部分,哪些不被视为冲突精灵的一部分 还有将位图绘制到屏幕上所需的代码。现在,这方面的CPU使用率只是一个小问题。一台装有PyGame的普通PC可以以60帧/秒的速度在屏幕上轻松绘制1000个精灵。但在以前,这需要大量的处理时间,并且有希望在某种硬件协助下完成。甚至在20世纪90年代,一些视频卡的广告中也有“硬件鼠标光标”支持[需要引用]。PyGame的代码非常高效,可以将位图绘制到屏幕上 总之,为什么要使用精灵:
- 易于实现
- 透明度和遮罩
- 快速碰撞检测
- 20世纪80年代的硬件甚至不能梦想硬件3D
- 他们已经写好了
- 它们速度快、效率高、无bug
- 他们可以使用面具
- 他们已经有了高效的碰撞检测代码
- 支持是非常有用的
class Pacman( pygame.sprite.Sprite ): # parent class is Sprite
def __init__( self, x, y, pacman_bitmap ): # New PacMan at (x,y)
pygame.sprite.Sprite.__init__( self ) # Init the parent obj too
self.image = pacman_bitmap # it MUST be self.image for sprites
self.rect = self.image.get_rect() # it MUST be self.rect for sprites
self.rect.center = ( x, y ) # move the sprite
self.move_dir_x = 0
self.move_dir_y = 0 # This pacman never stops
# Semi-optional Part
def update( self ): # called to somehow effect the sprite.
# Move pacman # MUST be named "update"
x, y = self.rect.center
x += self.move_dir_x
y += self.move_dir_y
self.rect.center = ( x, y ) # move the sprite
# Optional Part
def setDirection( self, dir ): # Called when user sends
if ( dir == 'up' ): # input to change direction
self.move_dir_x = 0
self.move_dir_y = -1
elif ( dir == 'right' ):
self.move_dir_x = 1
self.move_dir_y = 0
#elif ... TODO - rest of direction changes
就这样。基本Sprite对象期望子类“覆盖”image
和rect
成员变量。精灵组使用update()
函数以某种方式修改精灵。这一个只是朝着设置好的任何方向移动(根据用户输入的不同而变化)
所以我们可以这样使用:
pacman_image = pygame.image.load( 'pacman.png' ).convert()
pacman_sprite = Pacman( 100, 100, pacman_image )
player1_sprite = pygame.sprite.GroupSingle() # Just 1 player for now
player_sprites.add( pacman_sprite )
# Imagine a similar sprite class for ghosts
ghost_image = pygame.image.load( 'blue_ghost.png' ).convert()
...
ghost_sprites = pygame.sprite.Group()
for i in range( 4 ):
ghost_sprites.add( Ghost( 10, 50, ghost_image ) )
然后在主循环中:
game_over = False
while not game_over:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
game_over = True
# Movement keys too (not event driven)
keys = pygame.key.get_pressed()
if ( keys[pygame.K_UP] ):
player_sprite.setDirection( 'up' )
elif ( keys[pygame.K_RIGHT] ):
player_sprite.setDirection( 'right' )
#elif TODO - rest of keys
# re-position all the players and ghosts
player_sprites.update()
ghost_sprites.update()
# Paint the background
paintPacmanEnvironment( window )
# Paint all the sprites
player_sprites.draw( window )
ghost_sprites.draw( window )
# Did the player hit a ghost?
# spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
if ( pygame.sprite.spritecollide( player_sprite, ghost_sprites, False ) ):
# TODO: handle hitting a ghost
是的,最初设置精灵有点复杂。但看看那个主回路!只需几次函数调用,您就可以获得几乎免费的绘制和碰撞,再加上一点设置(大约1行),您还可以获得位图掩码。这就是为什么你应该使用PyGame精灵
编辑:Sprite.update()上的快速注释
update()
函数不仅是处理运动的好地方,也是处理动画的好地方。显然,我们需要多帧动画来让吃豆人的嘴动起来。为了实现这一点,Pacman.update()
将查看当前时钟时间,并使用它前进到动画的下一帧。因此,我们可以使用图像列表来创建Pacman,而不是仅使用单个位图创建Pacman。然后,Pacman.image
将被设置为.udpate()中的正确图像。它工作得非常好。非常感谢您提供了这个有用的答案!还有一个问题:为什么要使用self.rect=self.image.get_rect()
和self.rect.center=(x,y)
?@Tangax将pygame精灵视为一个容器,它将一个曲面与在屏幕上绘制该曲面的位置相结合。因此,精灵必须具有的最小属性是图像
属性(包含曲面)和rect
属性(包含图像的大小和位置)。在这里使用Rect而不是例如x,y
元组可以轻松更改精灵的位置。如您所见,我们可以通过使用rect的center
属性轻松地将图像的中心设置为特定位置,并且rect类为我们处理所有数学运算。再次感谢,它对我非常有用!