先看下前面的文字,里面介绍了滚动背景的实现。但没有用到精灵类。
https://mp.csdn.net/postedit/88089379
前面的日记里,用精灵类实现了大部分的功能,除了滚动背景,大家可以下载下我编写的飞机大战的源代码,里面实现了滚动背景的效果。而且能自动切割图片,自动生成所需背景的列表。
因为在单个精灵类里,只能有一个image存在,滚动背景一般是两个图片image。要实现效果,只能建立两个精灵,在主函数里进行坐标传递,分别绘制两个精灵的图片。
偶然在国外的网站上,找到了很多示例,里面的例题让人受益匪浅。其中有Layer的运用加滚动背景的实现。
用一个allgroups来管理所有的层,而且能自动管理每个精灵的绘制,更新。代码精炼、轻松不少。
update()函数是关键,要多多理解一下。
class Background(pygame.sprite.Sprite):
"""
generate a Background sprite for the background,
to demonstrate vertical scrolling.background slide from top to bottom
parameter: vect_pos must use in pygame.math.Vector2D type
"""
def __init__(self, vect_pos):
self._layer = -1
self.groups = allgroup, backgroundgroup
pygame.sprite.Sprite.__init__(self, self.groups) # THE Line
self.image = pygame.image.load('data/bg.png').convert_alpha()
# self.image.convert_alpha()
self.rect = self.image.get_rect()
self.pos = vect_pos
self.rect.x = self.pos.x
self.rect.y = self.pos.y
self.parent = False
def update(self):
self.rect.y += 1
if self.rect.y > SCENEHEIGHT:
#kill了以后,还是能继续下面的print()的。
self.kill()
# create new background if necessary
# 下面这段代码真是精彩,背景图有两张,例如bg1,bg2,均默认parent= Flase
# bg1需要加第二张bg2时(self.rect.y>=0)时,第一张bg1的parent = Ture,此时还没达到bg1的kill的判定
# 能继续运行,但不能再产生新图。
# 新生成的背景图bg2,默认parent = False,代替了第一张bg1的功能,进行下面的代码的判定,条件满足时
# 能继续产生新背景图bg3,bg2的parent= True,产生bg3,bg2不能在产生新图,bg3的parent=Falses ……
# 可以用print(self.parent,self.rect.y)来查看运行状态,同时存在两个图片
# print(self.parent,self.rect.y)
if not self.parent:
if self.rect.y >= 0:
self.parent = True
Background(vect(0, -SCENEHEIGHT))
测试用的全部代码如下:
import pygame
import pygame
import os
import random
vect = pygame.math.Vector2
#define sprite groups. Do this before creating sprites
textgroup = pygame.sprite.Group()
backgroundgroup = pygame.sprite.Group()
menugroup =pygame.sprite.Group()
# only the allgroup draws the sprite, so i use LayeredUpdates() instead Group()
# more sophisticated, can draw sprites in layers
allgroup = pygame.sprite.LayeredUpdates()
SCENEWIDTH = 480
SCENEHEIGHT = 850
class Text(pygame.sprite.Sprite):
""" display a text"""
def __init__(self, msg):
self.groups = allgroup, textgroup
self._layer = 99
pygame.sprite.Sprite.__init__(self, self.groups)
self.newmsg(msg)
def write(self, msg="pygame is cool"):
"""write text into pygame surfaces"""
myfont = pygame.font.SysFont("None", 32)
mytext = myfont.render(msg, True, (0, 0, 0))
mytext = mytext.convert_alpha()
return mytext
def update(self):
pass
def newmsg(self, msg="i have nothing to say"):
self.image = self.write(msg)
self.rect = self.image.get_rect()
self.rect.center = (SCENEWIDTH // 2, 10)
class Background(pygame.sprite.Sprite):
"""
generate a Background sprite for the background,
to demonstrate vertical scrolling.background slide from top to bottom
parameter: vect_pos must use in pygame.math.Vector2D type
"""
def __init__(self, vect_pos):
self._layer = -1
self.groups = allgroup, backgroundgroup
pygame.sprite.Sprite.__init__(self, self.groups) # THE Line
self.image = pygame.image.load('data/bg.png').convert_alpha()
# self.image.convert_alpha()
self.rect = self.image.get_rect()
self.pos = vect_pos
self.rect.x = self.pos.x
self.rect.y = self.pos.y
self.parent = False
def update(self):
self.rect.y += 1
if self.rect.y > SCENEHEIGHT:
#kill了以后,还是能继续下面的print()的。
self.kill()
# create new background if necessary
# 下面这段代码真是精彩,背景图有两张,例如bg1,bg2,均默认parent= Flase
# bg1需要加第二张bg2时(self.rect.y>=0)时,第一张bg1的parent = Ture,此时还没达到bg1的kill的判定
# 能继续运行,但不能再产生新图。
# 新生成的背景图bg2,默认parent = False,代替了第一张bg1的功能,进行下面的代码的判定,条件满足时
# 能继续产生新背景图bg3,产生bg3后,bg2的parent= True,不能在产生新图,bg3的parent=Falses ……
# 可以用print(self.parent,self.rect.y)来查看运行状态,同时存在两个图片
# print(self.parent,self.rect.y)
if not self.parent:
if self.rect.y >= 0:
self.parent = True
Background(vect(0, -SCENEHEIGHT))
def game():
pygame.init()
screen = pygame.display.set_mode((480, 850))
clock = pygame.time.Clock() # create pygame clock object
mainloop = True
FPS = 60 # desired max. framerate in frames per second.
# create the first vertical scrolling background
bg = Background(vect(0, 0)) # from (0,0),lefttop coordinate
menu = Menu()
while mainloop: # ----------------- mainloop ----------------------
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False # pygame window closed by user
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mainloop = False # user pressed ESC
elif event.key == pygame.K_p: # print layer information in console
print("=========================")
print("-----Spritelist---------")
print("------------------------")
print("toplayer:", allgroup.get_top_layer())
print("bottomlayer:", allgroup.get_bottom_layer())
print("layers;", allgroup.layers())
print("=========================")
layer_info = Text('press key p to print layer INF')
# ----------- draw , update, flip -----------------
allgroup.update()
allgroup.draw(screen)
pygame.display.flip()
if __name__ == "__main__":
game()
else:
print("i was imported by", __name__)
可以看到,文字永远在最上层,因为文字的层设置成了99,比其他的层都高。背景轮流滚动。