Pygame实战:传承四十年的封神之作—炸弹人学院游戏!「附源码」

导语
在现在这个浮躁的年代:小编每次登陆王者荣耀,还有每次登陆刺激战场!
看着里面的聊天界面,各种代打、各种的找cp。小小编觉得,我们已经失去了玩游戏的初心。
接下来,小台将带领你们走回童年时光,一起领略我们当初玩4399的单纯与天真!
??还记得小时候小台每到放学时刻,就会拉着只比我小半岁的小表妹,一块去亲戚家里玩电脑
每一次打开电脑做的第一件事情就是,打开浏览器,输入4399这四个数字,那个时候觉得hao123真是一个神奇的主页!
可以让我打开4399玩各种游戏qwq,尤其是Q版泡泡堂深得我心!
??那今天就带大家回忆一下童年也做一款经典的炸弹人的小游戏!
??
?正文
游戏规则还清楚哈,我就不多做介绍了不清楚玩法的可以百度下下!
首先准备好相应的素材:【部分如下】
?
?炸弹人主程序:
importsysimportcfgimportrandomimportpygamefrommodulesimport*‘’‘游戏主程序’‘’defmain(cfg):#初始化pygame.init()pygame.mixer.init()pygame.mixer.music.load(cfg.BGMPATH)pygame.mixer.music.play(-1,0.0)screen=pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.set_caption(‘炸弹人——源码基地:#959755565#’)#开始界面Interface(screen,cfg,mode=‘game_start’)#游戏主循环font=pygame.font.SysFont(‘Consolas’,15)forgamemap_pathincfg.GAMEMAPPATHS:#-地图map_parser=mapParser(gamemap_path,bg_paths=cfg.BACKGROUNDPATHS,wall_paths=cfg.WALLPATHS,blocksize=cfg.BLOCKSIZE)#-水果fruit_sprite_group=pygame.sprite.Group()used_spaces=[]foriinrange(5):coordinate=map_parser.randomGetSpace(used_spaces)used_spaces.append(coordinate)fruit_sprite_group.add(Fruit(random.choice(cfg.FRUITPATHS),coordinate=coordinate,blocksize=cfg.BLOCKSIZE))#-我方Herocoordinate=map_parser.randomGetSpace(used_spaces)used_spaces.append(coordinate)ourhero=Hero(imagepaths=cfg.HEROZELDAPATHS,coordinate=coordinate,blocksize=cfg.BLOCKSIZE,map_parser=map_parser,hero_name=‘ZELDA’)#-电脑Heroaihero_sprite_group=pygame.sprite.Group()coordinate=map_parser.randomGetSpace(used_spaces)aihero_sprite_group.add(Hero(imagepaths=cfg.HEROBATMANPATHS,coordinate=coordinate,blocksize=cfg.BLOCKSIZE,map_parser=map_parser,hero_name=‘BATMAN’))used_spaces.append(coordinate)coordinate=map_parser.randomGetSpace(used_spaces)aihero_sprite_group.add(Hero(imagepaths=cfg.HERODKPATHS,coordinate=coordinate,blocksize=cfg.BLOCKSIZE,map_parser=map_parser,hero_name=‘DK’))used_spaces.append(coordinate)#-炸弹bombbomb_sprite_group=pygame.sprite.Group()#-用于判断游戏胜利或者失败的flagis_win_flag=False#-主循环screen=pygame.display.set_mode(map_parser.screen_size)clock=pygame.time.Clock()whileTrue:dt=clock.tick(cfg.FPS)foreventinpygame.event.get():ifevent.type==pygame.QUIT:pygame.quit()sys.exit(-1)#–↑↓←→键控制上下左右,空格键丢炸弹elifevent.type==pygame.KEYDOWN:ifevent.key==pygame.K_UP:ourhero.move(‘up’)elifevent.key==pygame.K_DOWN:ourhero.move(‘down’)elifevent.key==pygame.K_LEFT:ourhero.move(‘left’)elifevent.key==pygame.K_RIGHT:ourhero.move(‘right’)elifevent.key==pygame.K_SPACE:ifourhero.bomb_cooling_count<=0:bomb_sprite_group.add(ourhero.generateBomb(imagepath=cfg.BOMBPATH,digitalcolor=cfg.YELLOW,explode_imagepath=cfg.FIREPATH))screen.fill(cfg.WHITE)#–电脑Hero随机行动forheroinaihero_sprite_group:action,flag=hero.randomAction(dt)ifflagandaction==‘dropbomb’:bomb_sprite_group.add(hero.generateBomb(imagepath=cfg.BOMBPATH,digitalcolor=cfg.YELLOW,explode_imagepath=cfg.FIREPATH))#–吃到水果加生命值(只要是Hero,都能加)ourhero.eatFruit(fruit_sprite_group)forheroinaihero_sprite_group:hero.eatFruit(fruit_sprite_group)#–游戏元素都绑定到屏幕上map_parser.draw(screen)forbombinbomb_sprite_group:ifnotbomb.is_being:bomb_sprite_group.remove(bomb)explode_area=bomb.draw(screen,dt,map_parser)ifexplode_area:#–爆炸火焰范围内的Hero生命值将持续下降ifourhero.coordinateinexplode_area:ourhero.health_value-=bomb.harm_valueforheroinaihero_sprite_group:ifhero.coordinateinexplode_area:hero.health_value-=bomb.harm_valuefruit_sprite_group.draw(screen)forheroinaihero_sprite_group:hero.draw(screen,dt)ourhero.draw(screen,dt)#–左上角显示生命值pos_x=showText(screen,font,text=ourhero.hero_name+‘(our):’+str(ourhero.health_value),color=cfg.YELLOW,position=[5,5])forheroinaihero_sprite_group:pos_x,pos_y=pos_x+15,5pos_x=showText(screen,font,text=hero.hero_name+‘(ai):’+str(hero.health_value),color=cfg.YELLOW,position=[pos_x,pos_y])#–我方玩家生命值小于等于0/电脑方玩家生命值均小于等于0则判断游戏结束ifourhero.health_value<=0:is_win_flag=Falsebreakforheroinaihero_sprite_group:ifhero.health_value<=0:aihero_sprite_group.remove(hero)iflen(aihero_sprite_group)==0:is_win_flag=Truebreakpygame.display.update()clock.tick(cfg.FPS)ifis_win_flag:Interface(screen,cfg,mode=‘game_switch’)else:breakInterface(screen,cfg,mode=‘game_end’)‘’‘run’‘’ifname==‘main’:whileTrue:main(cfg)
开始界面:
?
?定义地图类:
classmapParser(): definit(self,mapfilepath,bg_paths,wall_paths,blocksize,kwargs): self.instances_list=self.parse(mapfilepath) self.bg_paths=bg_paths self.wall_paths=wall_paths self.blocksize=blocksize self.height=len(self.instances_list) self.width=len(self.instances_list[0]) self.screen_size=(blocksize*self.width,blocksize*self.height) ‘’‘地图画到屏幕上’‘’ defdraw(self,screen): forjinrange(self.height): foriinrange(self.width): instance=self.instances_list[j][i] ifinstance==‘w’: elem=Wall(self.wall_paths[0],[i,j],self.blocksize) elifinstance==‘x’: elem=Wall(self.wall_paths[1],[i,j],self.blocksize) elifinstance==‘z’: elem=Wall(self.wall_paths[2],[i,j],self.blocksize) elifinstance==‘0’: elem=Background(self.bg_paths[0],[i,j],self.blocksize) elifinstance==‘1’: elem=Background(self.bg_paths[1],[i,j],self.blocksize) elifinstance==‘2’: elem=Background(self.bg_paths[2],[i,j],self.blocksize) else: raiseValueError(‘instanceparseerrorinmapParser.draw…’) elem.draw(screen) ‘’‘随机获取一个空地’‘’ defrandomGetSpace(self,used_spaces=None): whileTrue: i=random.randint(0,self.width-1) j=random.randint(0,self.height-1) coordinate=[i,j] ifused_spacesandcoordinateinused_spaces: continue instance=self.instances_list[j][i] ifinstancein[‘0’,‘1’,‘2’]: break returncoordinate ‘’‘根据坐标获取元素类型’‘’ defgetElemByCoordinate(self,coordinate): returnself.instances_list[coordinate[1]][coordinate[0]] ‘’‘解析.map文件’‘’ defparse(self,mapfilepath): instances_list=[] withopen(mapfilepath)asf: forlineinf.readlines(): instances_line_list=[] forcinline: ifcin[‘w’,‘x’,‘z’,‘0’,‘1’,‘2’]: instances_line_list.append© instances_list.append(instances_line_list) returninstances_list定义必要的一些精灵类:角色,水果等等。
‘’‘墙类’‘’classWall(pygame.sprite.Sprite): definit(self,imagepath,coordinate,blocksize,
kwargs): pygame.sprite.Sprite.init(self) self.image=pygame.image.load(imagepath) self.image=pygame.transform.scale(self.image,(blocksize,blocksize)) self.rect=self.image.get_rect() self.rect.left,self.rect.top=coordinate[0]*blocksize,coordinate[1]*blocksize self.coordinate=coordinate self.blocksize=blocksize ‘’‘画到屏幕上’‘’ defdraw(self,screen): screen.blit(self.image,self.rect) returnTrue‘’‘背景类’‘’classBackground(pygame.sprite.Sprite): definit(self,imagepath,coordinate,blocksize,kwargs): pygame.sprite.Sprite.init(self) self.image=pygame.image.load(imagepath) self.image=pygame.transform.scale(self.image,(blocksize,blocksize)) self.rect=self.image.get_rect() self.rect.left,self.rect.top=coordinate[0]*blocksize,coordinate[1]*blocksize self.coordinate=coordinate self.blocksize=blocksize ‘’‘画到屏幕上’‘’ defdraw(self,screen): screen.blit(self.image,self.rect) returnTrue‘’‘水果类’‘’classFruit(pygame.sprite.Sprite): definit(self,imagepath,coordinate,blocksize,kwargs): pygame.sprite.Sprite.init(self) self.kind=imagepath.split(‘/’)[-1].split(‘.’)[0] ifself.kind==‘banana’: self.value=5 elifself.kind==‘cherry’: self.value=10 else: raiseValueError(‘Unknowfruit%s…’%self.kind) self.image=pygame.image.load(imagepath) self.image=pygame.transform.scale(self.image,(blocksize,blocksize)) self.rect=self.image.get_rect() self.rect.left,self.rect.top=coordinate[0]*blocksize,coordinate[1]*blocksize self.coordinate=coordinate self.blocksize=blocksize ‘’‘画到屏幕上’‘’ defdraw(self,screen): screen.blit(self.image,self.rect) returnTrue‘’‘炸弹类’‘’classBomb(pygame.sprite.Sprite): definit(self,imagepath,coordinate,blocksize,digitalcolor,explode_imagepath,kwargs): pygame.sprite.Sprite.init(self) self.image=pygame.image.load(imagepath) self.image=pygame.transform.scale(self.image,(blocksize,blocksize)) self.explode_imagepath=explode_imagepath self.rect=self.image.get_rect() #像素位置 self.rect.left,self.rect.top=coordinate[0]*blocksize,coordinate[1]*blocksize #坐标(元素块为单位长度) self.coordinate=coordinate self.blocksize=blocksize #爆炸倒计时 self.explode_millisecond=6000*1-1 self.explode_second=int(self.explode_millisecond/1000) self.start_explode=False #爆炸持续时间 self.exploding_count=1000*1 #炸弹伤害能力 self.harm_value=1 #该炸弹是否还存在 self.is_being=True self.font=pygame.font.SysFont(‘Consolas’,20) self.digitalcolor=digitalcolor ‘’‘画到屏幕上’‘’ defdraw(self,screen,dt,map_parser): ifnotself.start_explode: #爆炸倒计时 self.explode_millisecond-=dt self.explode_second=int(self.explode_millisecond/1000) ifself.explode_millisecond<0: self.start_explode=True screen.blit(self.image,self.rect) text=self.font.render(str(self.explode_second),True,self.digitalcolor) rect=text.get_rect(center=(self.rect.centerx-5,self.rect.centery+5)) screen.blit(text,rect) returnFalse else: #爆炸持续倒计时 self.exploding_count-=dt ifself.exploding_count>0: returnself.explode(screen,map_parser) else: self.is_being=False returnFalse ‘’‘爆炸效果’‘’ defexplode(self,screen,map_parser): explode_area=self.calcExplodeArea(map_parser.instances_list) foreachinexplode_area: image=pygame.image.load(self.explode_imagepath) image=pygame.transform.scale(image,(self.blocksize,self.blocksize)) rect=image.get_rect() rect.left,rect.top=each[0]*self.blocksize,each[1]*self.blocksize screen.blit(image,rect) returnexplode_area ‘’‘计算爆炸区域’‘’ defcalcExplodeArea(self,instances_list): explode_area=[] #区域计算规则为墙可以阻止爆炸扩散,且爆炸范围仅在游戏地图范围内 forymininrange(self.coordinate[1],self.coordinate[1]-5,-1): ifymin<0orinstances_list[ymin][self.coordinate[0]]in[‘w’,‘x’,‘z’]: break explode_area.append([self.coordinate[0],ymin]) forymaxinrange(self.coordinate[1]+1,self.coordinate[1]+5): ifymax>=len(instances_list)orinstances_list[ymax][self.coordinate[0]]in[‘w’,‘x’,‘z’]: break explode_area.append([self.coordinate[0],ymax]) forxmininrange(self.coordinate[0],self.coordinate[0]-5,-1): ifxmin<0orinstances_list[self.coordinate[1]][xmin]in[‘w’,‘x’,‘z’]: break explode_area.append([xmin,self.coordinate[1]]) forxmaxinrange(self.coordinate[0]+1,self.coordinate[0]+5): ifxmax>=len(instances_list[0])orinstances_list[self.coordinate[1]][xmax]in[‘w’,‘x’,‘z’]: break explode_area.append([xmax,self.coordinate[1]]) returnexplode_area‘’‘角色类’‘’classHero(pygame.sprite.Sprite): definit(self,imagepaths,coordinate,blocksize,map_parser,kwargs): pygame.sprite.Sprite.init(self) self.imagepaths=imagepaths self.image=pygame.image.load(imagepaths[-1]) self.image=pygame.transform.scale(self.image,(blocksize,blocksize)) self.rect=self.image.get_rect() self.rect.left,self.rect.top=coordinate[0]*blocksize,coordinate[1]*blocksize self.coordinate=coordinate self.blocksize=blocksize self.map_parser=map_parser self.hero_name=kwargs.get(‘hero_name’) #生命值 self.health_value=50 #炸弹冷却时间 self.bomb_cooling_time=5000 self.bomb_cooling_count=0 #随机移动冷却时间(仅AI电脑用) self.randommove_cooling_time=100 self.randommove_cooling_count=0 ‘’‘角色移动’‘’ defmove(self,direction): self.updateImage(direction) ifdirection==‘left’: ifself.coordinate[0]-1<0orself.map_parser.getElemByCoordinate([self.coordinate[0]-1,self.coordinate[1]])in[‘w’,‘x’,‘z’]: returnFalse self.coordinate[0]=self.coordinate[0]-1 elifdirection==‘right’: ifself.coordinate[0]+1>=self.map_parser.widthorself.map_parser.getElemByCoordinate([self.coordinate[0]+1,self.coordinate[1]])in[‘w’,‘x’,‘z’]: returnFalse self.coordinate[0]=self.coordinate[0]+1 elifdirection==‘up’: ifself.coordinate[1]-1<0orself.map_parser.getElemByCoordinate([self.coordinate[0],self.coordinate[1]-1])in[‘w’,‘x’,‘z’]: returnFalse self.coordinate[1]=self.coordinate[1]-1 elifdirection==‘down’: ifself.coordinate[1]+1>=self.map_parser.heightorself.map_parser.getElemByCoordinate([self.coordinate[0],self.coordinate[1]+1])in[‘w’,‘x’,‘z’]: returnFalse self.coordinate[1]=self.coordinate[1]+1 else: raiseValueError(‘Unknowdirection%s…’%direction) self.rect.left,self.rect.top=self.coordinate[0]*self.blocksize,self.coordinate[1]*self.blocksize returnTrue ‘’‘随机行动(AI电脑用)’‘’ defrandomAction(self,dt): #冷却倒计时 ifself.randommove_cooling_count>0: self.randommove_cooling_count-=dt action=random.choice([‘left’,‘left’,‘right’,‘right’,‘up’,‘up’,‘down’,‘down’,‘dropbomb’]) flag=False ifactionin[‘left’,‘right’,‘up’,‘down’]: ifself.randommove_cooling_count<=0: flag=True self.move(action) self.randommove_cooling_count=self.randommove_cooling_time elifactionin[‘dropbomb’]: ifself.bomb_cooling_count<=0: flag=True self.bomb_cooling_count=self.bomb_cooling_time returnaction,flag ‘’‘生成炸弹’‘’ defgenerateBomb(self,imagepath,digitalcolor,explode_imagepath): returnBomb(imagepath=imagepath,coordinate=copy.deepcopy(self.coordinate),blocksize=self.blocksize,digitalcolor=digitalcolor,explode_imagepath=explode_imagepath) ‘’‘画到屏幕上’‘’ defdraw(self,screen,dt): #冷却倒计时 ifself.bomb_cooling_count>0: self.bomb_cooling_count-=dt screen.blit(self.image,self.rect) returnTrue ‘’‘吃水果’‘’ defeatFruit(self,fruit_sprite_group): eaten_fruit=pygame.sprite.spritecollide(self,fruit_sprite_group,True,None) forfruitineaten_fruit: self.health_value+=fruit.value ‘’‘更新角色朝向’‘’ defupdateImage(self,direction): directions=[‘left’,‘right’,‘up’,‘down’] idx=directions.index(direction) self.image=pygame.image.load(self.imagepaths[idx]) self.image=pygame.transform.scale(self.image,(self.blocksize,self.blocksize))
?效果如下:
?
这精致的画面还可以吧哈哈哈啊快夸我快夸我
总结
安啦!文章就写到这里,你们的支持是我最大的动力,记得三连哦木啊!
完整的源码+素材老规矩源码基地见:私信小编06——即可免费领取啦!
温馨提示:不要忘记点赞、关注、评论哦!看我手上的炸弹?
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。
用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。