这部分是关于在使用 Python 的 Pygame 模块开发的视频游戏总给你的玩家提供收集的宝物和经验值的内容。
这是正在进行的关于使用 Python 3 的 Pygame 模块创建视频游戏的系列文章的第十部分。以前的文章有:
如果你已经阅读了本系列的前几篇文章,那么你已经了解了编写游戏的所有基础知识。现在你可以在这些基础上,创造一个全功能的游戏。当你第一次学习时,遵循本系列代码示例,这样的“用例”是有帮助的,但是,用例也会约束你。现在是时候运用你学到的知识,以新的方式应用它们了。
如果说,说起来容易做起来难,这篇文章展示了一个如何将你已经了解的内容用于新目的的例子中。具体来说,就是它涵盖了如何使用你以前的课程中已经了解到的来实现奖励系统。
在大多数电子游戏中,你有机会在游戏世界中获得“奖励”或收集到宝物和其他物品。奖励通常会增加你的分数或者你的生命值,或者为你的下一次任务提供信息。
游戏中包含的奖励类似于编程平台。像平台一样,奖励没有用户控制,随着游戏世界的滚动进行,并且必须检查与玩家的碰撞。
创建奖励函数
奖励和平台非常相似,你甚至不需要一个奖励的类。你可以重用 Platform 类,并将结果称为“奖励”。
由于奖励类型和位置可能因关卡不同而不同,如果你还没有,请在你的 Level 中创建一个名为 loot 的新函数。因为奖励物品不是平台,你也必须创建一个新的 loot_list 组,然后添加奖励物品。与平台、地面和敌人一样,该组用于检查玩家碰撞:
defloot(lvl,lloc):
iflvl==1:
loot_list=pygame.sprite.Group()
loot=Platform(300,ty*7,tx,ty,'loot_1.png')
loot_list.add(loot)
iflvl==2:
print(lvl)
returnloot_list
你可以随意添加任意数量的奖励对象;记住把每一个都加到你的奖励清单上。Platform 类的参数是奖励图标的 X 位置、Y 位置、宽度和高度(通常让你的奖励精灵保持和所有其他方块一样的大小最为简单),以及你想要用作的奖励的图片。奖励的放置可以和贴图平台一样复杂,所以使用创建关卡时需要的关卡设计文档。
在脚本的设置部分调用新的奖励函数。在下面的代码中,前三行是上下文,所以只需添加第四行:
enemy_list=Level.bad(1,eloc)
ground_list=Level.ground(1,gloc,tx,ty)
plat_list=Level.platform(1,tx,ty)
loot_list=Level.loot(1,tx,ty)
正如你现在所知道的,除非你把它包含在你的主循环中,否则奖励不会被显示到屏幕上。将下面代码示例的最后一行添加到循环中:
enemy_list.draw(world)
ground_list.draw(world)
plat_list.draw(world)
loot_list.draw(world)
启动你的游戏看看会发生什么。
Loot in Python platformer
你的奖励将会显示出来,但是当你的玩家碰到它们时,它们不会做任何事情,当你的玩家经过它们时,它们也不会滚动。接下来解决这些问题。
滚动奖励
像平台一样,当玩家在游戏世界中移动时,奖励必须滚动。逻辑与平台滚动相同。要向前滚动奖励物品,添加最后两行:
foreinenemy_list:
e.rect.x-=scroll
forlinloot_list:
l.rect.x-=scroll
要向后滚动,请添加最后两行:
foreinenemy_list:
e.rect.x+=scroll
forlinloot_list:
l.rect.x+=scroll
再次启动你的游戏,看看你的奖励物品现在表现得像在游戏世界里一样了,而不是仅仅画在上面。
检测碰撞
就像平台和敌人一样,你可以检查奖励物品和玩家之间的碰撞。逻辑与其他碰撞相同,除了撞击不会(必然)影响重力或生命值。取而代之的是,命中会导致奖励物品会消失并增加玩家的分数。
当你的玩家触摸到一个奖励对象时,你可以从 loot_list 中移除该对象。这意味着当你的主循环在 loot_list 中重绘所有奖励物品时,它不会重绘那个特定的对象,所以看起来玩家已经获得了奖励物品。
在 Player 类的 update 函数中的平台碰撞检测之上添加以下代码(最后一行仅用于上下文):
loot_hit_list=pygame.sprite.spritecollide(self,loot_list,False)
forlootinloot_hit_list:
loot_list.remove(loot)
self.score+=1
print(self.score)
plat_hit_list=pygame.sprite.spritecollide(self,plat_list,False)
当碰撞发生时,你不仅要把奖励从它的组中移除,还要给你的玩家一个分数提升。你还没有创建分数变量,所以请将它添加到你的玩家属性中,该属性是在 Player 类的 __init__ 函数中创建的。在下面的代码中,前两行是上下文,所以只需添加分数变量:
self.frame=0
self.health=10
self.score=0
当在主循环中调用 update 函数时,需要包括 loot_list:
player.gravity()
player.update()
如你所见,你已经掌握了所有的基本知识。你现在要做的就是用新的方式使用你所知道的。
在下一篇文章中还有一些提示,但是与此同时,用你学到的知识来制作一些简单的单关卡游戏。限制你试图创造的东西的范围是很重要的,这样你就不会埋没自己。这也使得最终的成品看起来和感觉上更容易完成。
以下是迄今为止你为这个 Python 平台编写的所有代码:
#!/usr/bin/envpython3
#draw a world
#add a playerandplayer control
#add player movement
#add enemyandbasic collision
#add platform
#add gravity
#add jumping
#add scrolling
#GNUAll-PermissiveLicense
#Copyinganddistribution ofthisfile,withorwithout modification,
#are permittedinany medium without royalty provided the copyright
#noticeandthisnotice are preserved.Thisfileisofferedas-is,
#without any warranty.
importpygame
importsys
importos
'''
Objects
'''
classPlatform(pygame.sprite.Sprite):
#x location,y location,img width,img height,imgfile
def__init__(self,xloc,yloc,imgw,imgh,img):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.image.load(os.path.join('images',img)).convert()
self.image.convert_alpha()
self.rect=self.image.get_rect()
self.rect.y=yloc
self.rect.x=xloc
classPlayer(pygame.sprite.Sprite):
'''
Spawn a player
'''
def__init__(self):
pygame.sprite.Sprite.__init__(self)
self.movex=0
self.movey=0
self.frame=0
self.health=10
self.collide_delta=0
self.jump_delta=6
self.score=1
self.images=[]
foriinrange(1,9):
img=pygame.image.load(os.path.join('images','hero'+str(i)+'.png')).convert()
img.convert_alpha()
img.set_colorkey(ALPHA)
self.images.append(img)
self.image=self.images[0]
self.rect=self.image.get_rect()
defjump(self,platform_list):
self.jump_delta=0
defgravity(self):
self.movey+=3.2#how fast player falls
ifself.rect.y>worldyandself.movey>=0:
self.movey=0
self.rect.y=worldy-ty
defcontrol(self,x,y):
'''
control player movement
'''
self.movex+=x
self.movey+=y
defupdate(self):
'''
Update sprite position
'''
self.rect.x=self.rect.x+self.movex
self.rect.y=self.rect.y+self.movey
#moving left
ifself.movex<0:
self.frame+=1
ifself.frame>ani*3:
self.frame=0
self.image=self.images[self.frame//ani]
#moving right
ifself.movex>0:
self.frame+=1
ifself.frame>ani*3:
self.frame=0
self.image=self.images[(self.frame//ani)+4]
#collisions
enemy_hit_list=pygame.sprite.spritecollide(self,enemy_list,False)
forenemyinenemy_hit_list:
self.health-=1
#print(self.health)
loot_hit_list=pygame.sprite.spritecollide(self,loot_list,False)
forlootinloot_hit_list:
loot_list.remove(loot)
self.score+=1
print(self.score)
plat_hit_list=pygame.sprite.spritecollide(self,plat_list,False)
forpinplat_hit_list:
self.collide_delta=0#stop jumping
self.movey=0
ifself.rect.y>p.rect.y:
self.rect.y=p.rect.y+ty
else:
self.rect.y=p.rect.y-ty
ground_hit_list=pygame.sprite.spritecollide(self,ground_list,False)
forginground_hit_list:
self.movey=0
self.rect.y=worldy-ty-ty
self.collide_delta=0#stop jumping
ifself.rect.y>g.rect.y:
self.health-=1
print(self.health)
ifself.collide_delta<6andself.jump_delta<6:
self.jump_delta=6*2
self.movey-=33#how high to jump
self.collide_delta+=6
self.jump_delta+=6
classEnemy(pygame.sprite.Sprite):
'''
Spawn an enemy
'''
def__init__(self,x,y,img):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.image.load(os.path.join('images',img))
self.movey=0
#self.image.convert_alpha()
#self.image.set_colorkey(ALPHA)
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
self.counter=0
defmove(self):
'''
enemy movement
'''
distance=80
speed=8
self.movey+=3.2
ifself.counter>=0andself.counter<=distance:
self.rect.x+=speed
elifself.counter>=distanceandself.counter<=distance*2:
self.rect.x-=speed
else:
self.counter=0
self.counter+=1
ifnotself.rect.y>=worldy-ty-ty:
self.rect.y+=self.movey
plat_hit_list=pygame.sprite.spritecollide(self,plat_list,False)
forpinplat_hit_list:
self.movey=0
ifself.rect.y>p.rect.y:
self.rect.y=p.rect.y+ty
else:
self.rect.y=p.rect.y-ty
ground_hit_list=pygame.sprite.spritecollide(self,ground_list,False)
forginground_hit_list:
self.rect.y=worldy-ty-ty
classLevel():
defbad(lvl,eloc):
iflvl==1:
enemy=Enemy(eloc[0],eloc[1],'yeti.png')#spawn enemy
enemy_list=pygame.sprite.Group()#create enemy group
enemy_list.add(enemy)#add enemy to group
iflvl==2:
print("Level "+str(lvl))
returnenemy_list
defloot(lvl,tx,ty):
iflvl==1:
loot_list=pygame.sprite.Group()
loot=Platform(200,ty*7,tx,ty,'loot_1.png')
loot_list.add(loot)
iflvl==2:
print(lvl)
returnloot_list
defground(lvl,gloc,tx,ty):
ground_list=pygame.sprite.Group()
i=0
iflvl==1:
whilei
ground=Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
ground_list.add(ground)
i=i+1
iflvl==2:
print("Level "+str(lvl))
returnground_list
defplatform(lvl,tx,ty):
plat_list=pygame.sprite.Group()
ploc=[]
i=0
iflvl==1:
ploc.append((20,worldy-ty-128,3))
ploc.append((300,worldy-ty-256,3))
ploc.append((500,worldy-ty-128,4))
whilei
j=0
whilej<=ploc[i][2]:
plat=Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
plat_list.add(plat)
j=j+1
print('run'+str(i)+str(ploc[i]))
i=i+1
iflvl==2:
print("Level "+str(lvl))
returnplat_list
'''
Setup
'''
worldx=960
worldy=720
fps=40#frame rate
ani=4#animation cycles
clock=pygame.time.Clock()
pygame.init()
main=True
BLUE=(25,25,200)
BLACK=(23,23,23)
WHITE=(254,254,254)
ALPHA=(0,255,0)
world=pygame.display.set_mode([worldx,worldy])
backdrop=pygame.image.load(os.path.join('images','stage.png')).convert()
backdropbox=world.get_rect()
player=Player()#spawn player
player.rect.x=0
player.rect.y=0
player_list=pygame.sprite.Group()
player_list.add(player)
steps=10
forwardx=600
backwardx=230
eloc=[]
eloc=[200,20]
gloc=[]
#gloc=[0,630,64,630,128,630,192,630,256,630,320,630,384,630]
tx=64#tilesize
ty=64#tilesize
i=0
whilei<=(worldx/tx)+tx:
gloc.append(i*tx)
i=i+1
enemy_list=Level.bad(1,eloc)
ground_list=Level.ground(1,gloc,tx,ty)
plat_list=Level.platform(1,tx,ty)
loot_list=Level.loot(1,tx,ty)
'''
Main loop
'''
whilemain==True:
foreventinpygame.event.get():
ifevent.type==pygame.QUIT:
pygame.quit();sys.exit()
main=False
ifevent.type==pygame.KEYDOWN:
ifevent.key==pygame.K_LEFTorevent.key==ord('a'):
print("LEFT")
player.control(-steps,0)
ifevent.key==pygame.K_RIGHTorevent.key==ord('d'):
print("RIGHT")
player.control(steps,0)
ifevent.key==pygame.K_UPorevent.key==ord('w'):
print('jump')
ifevent.type==pygame.KEYUP:
ifevent.key==pygame.K_LEFTorevent.key==ord('a'):
player.control(steps,0)
ifevent.key==pygame.K_RIGHTorevent.key==ord('d'):
player.control(-steps,0)
ifevent.key==pygame.K_UPorevent.key==ord('w'):
player.jump(plat_list)
ifevent.key==ord('q'):
pygame.quit()
sys.exit()
main=False
#scroll the world forward
ifplayer.rect.x>=forwardx:
scroll=player.rect.x-forwardx
player.rect.x=forwardx
forpinplat_list:
p.rect.x-=scroll
foreinenemy_list:
e.rect.x-=scroll
forlinloot_list:
l.rect.x-=scroll
#scroll the world backward
ifplayer.rect.x<=backwardx:
scroll=backwardx-player.rect.x
player.rect.x=backwardx
forpinplat_list:
p.rect.x+=scroll
foreinenemy_list:
e.rect.x+=scroll
forlinloot_list:
l.rect.x+=scroll
world.blit(backdrop,backdropbox)
player.gravity()#check gravity
player.update()
player_list.draw(world)#refresh player position
enemy_list.draw(world)#refresh enemies
ground_list.draw(world)#refresh enemies
plat_list.draw(world)#refresh platforms
loot_list.draw(world)#refresh loot
foreinenemy_list:
e.move()
pygame.display.flip()
clock.tick(fps)
【责任编辑:庞桂玉 TEL:(010)68476606】
点赞 0