Python Pygame怎么实现塔防游戏

Python Pygame怎么实现塔防游戏

这篇文章主要讲解了“PythonPygame怎么实现塔防游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PythonPygame怎么实现塔防游戏”吧!

    一、环境要求

    windows系统,python3.6+

    安装模块

    pipinstallpyqt5pipinstallpygame

    二、游戏介绍

    1、游戏目标

    按照关卡,设计不同的塔防地图(博主只设计了三关,有兴趣的同学,学会之后,可以自己画地图),设置三种炮台,每种炮台发射不同的炮弹,每种炮弹对敌人杀伤力不一样,每种

    炮台的价格也不一样。玩家通过钱币购买炮台,并设有剪出炮台的操作(有点类似植物大战僵尸里的铲子)。敌人成功抵达塔楼,游戏结束。

    2、先上游戏效果图

    三、完整开发流程

    1、项目主结构

    首先,先整理一下项目的主结构,其实看一下主结构,基本就清晰了

    2、详细配置

    config.py

    配置文件中,需要引入os模块,并且配置打开游戏的屏幕大小,并将资源中引用到的图片、音频插入到合适的位置。

    因为我们的迷宫游戏,需要划开模块。

    '''配置文件'''importos'''屏幕大小'''SCREENSIZE=(800,600)'''图片路径'''IMAGEPATHS={'choice':{'load_game':os.path.join(os.getcwd(),'resources/images/choice/load_game.png'),'map1':os.path.join(os.getcwd(),'resources/images/choice/map1.png'),'map1_black':os.path.join(os.getcwd(),'resources/images/choice/map1_black.png'),'map1_red':os.path.join(os.getcwd(),'resources/images/choice/map1_red.png'),'map2':os.path.join(os.getcwd(),'resources/images/choice/map2.png'),'map2_black':os.path.join(os.getcwd(),'resources/images/choice/map2_black.png'),'map2_red':os.path.join(os.getcwd(),'resources/images/choice/map2_red.png'),'map3':os.path.join(os.getcwd(),'resources/images/choice/map3.png'),'map3_black':os.path.join(os.getcwd(),'resources/images/choice/map3_black.png'),'map3_red':os.path.join(os.getcwd(),'resources/images/choice/map3_red.png'),},'end':{'gameover':os.path.join(os.getcwd(),'resources/images/end/gameover.png'),'continue_red':os.path.join(os.getcwd(),'resources/images/end/continue_red.png'),'continue_black':os.path.join(os.getcwd(),'resources/images/end/continue_black.png'),},'game':{'arrow1':os.path.join(os.getcwd(),'resources/images/game/arrow1.png'),'arrow2':os.path.join(os.getcwd(),'resources/images/game/arrow2.png'),'arrow3':os.path.join(os.getcwd(),'resources/images/game/arrow3.png'),'basic_tower':os.path.join(os.getcwd(),'resources/images/game/basic_tower.png'),'boulder':os.path.join(os.getcwd(),'resources/images/game/boulder.png'),'bush':os.path.join(os.getcwd(),'resources/images/game/bush.png'),'cave':os.path.join(os.getcwd(),'resources/images/game/cave.png'),'dirt':os.path.join(os.getcwd(),'resources/images/game/dirt.png'),'enemy_blue':os.path.join(os.getcwd(),'resources/images/game/enemy_blue.png'),'enemy_pink':os.path.join(os.getcwd(),'resources/images/game/enemy_pink.png'),'enemy_red':os.path.join(os.getcwd(),'resources/images/game/enemy_red.png'),'enemy_yellow':os.path.join(os.getcwd(),'resources/images/game/enemy_yellow.png'),'godark':os.path.join(os.getcwd(),'resources/images/game/godark.png'),'golight':os.path.join(os.getcwd(),'resources/images/game/golight.png'),'grass':os.path.join(os.getcwd(),'resources/images/game/grass.png'),'healthfont':os.path.join(os.getcwd(),'resources/images/game/healthfont.png'),'heavy_tower':os.path.join(os.getcwd(),'resources/images/game/heavy_tower.png'),'med_tower':os.path.join(os.getcwd(),'resources/images/game/med_tower.png'),'nexus':os.path.join(os.getcwd(),'resources/images/game/nexus.png'),'othergrass':os.path.join(os.getcwd(),'resources/images/game/othergrass.png'),'path':os.path.join(os.getcwd(),'resources/images/game/path.png'),'rock':os.path.join(os.getcwd(),'resources/images/game/rock.png'),'tiles':os.path.join(os.getcwd(),'resources/images/game/tiles.png'),'unitfont':os.path.join(os.getcwd(),'resources/images/game/unitfont.png'),'water':os.path.join(os.getcwd(),'resources/images/game/water.png'),'x':os.path.join(os.getcwd(),'resources/images/game/x.png'),},'pause':{'gamepaused':os.path.join(os.getcwd(),'resources/images/pause/gamepaused.png'),'resume_black':os.path.join(os.getcwd(),'resources/images/pause/resume_black.png'),'resume_red':os.path.join(os.getcwd(),'resources/images/pause/resume_red.png'),},'start':{'play_black':os.path.join(os.getcwd(),'resources/images/start/play_black.png'),'play_red':os.path.join(os.getcwd(),'resources/images/start/play_red.png'),'quit_black':os.path.join(os.getcwd(),'resources/images/start/quit_black.png'),'quit_red':os.path.join(os.getcwd(),'resources/images/start/quit_red.png'),'start_interface':os.path.join(os.getcwd(),'resources/images/start/start_interface.png'),},}'''地图路径'''MAPPATHS={'1':os.path.join(os.getcwd(),'resources/maps/1.map'),'2':os.path.join(os.getcwd(),'resources/maps/2.map'),'3':os.path.join(os.getcwd(),'resources/maps/3.map'),}'''字体路径'''FONTPATHS={'Calibri':os.path.join(os.getcwd(),'resources/fonts/Calibri.ttf'),'m04':os.path.join(os.getcwd(),'resources/fonts/m04.ttf'),'MicrosoftSansSerif':os.path.join(os.getcwd(),'resources/fonts/MicrosoftSansSerif.ttf'),}'''不同难度的settings'''DIFFICULTYPATHS={'easy':os.path.join(os.getcwd(),'resources/difficulties/easy.json'),'hard':os.path.join(os.getcwd(),'resources/difficulties/hard.json'),'medium':os.path.join(os.getcwd(),'resources/difficulties/medium.json'),}'''音频路径'''AUDIOPATHS={'bgm':os.path.join(os.getcwd(),'resources/audios/bgm.mp3'),}

    3、定义敌人、塔楼、子弹的类

    turrent.py 以炮塔类为例

    炮塔首先需要初始化,即init函数,另外需要有射击属性、以及重置属性(即我们可以将已经建好的炮塔删除,然后重新添加)

    importpygamefrom.arrowimportArrow'''炮塔类'''classTurret(pygame.sprite.Sprite):def__init__(self,turret_type,cfg):assertturret_typeinrange(3)pygame.sprite.Sprite.__init__(self)self.cfg=cfgself.turret_type=turret_typeself.imagepaths=[cfg.IMAGEPATHS['game']['basic_tower'],cfg.IMAGEPATHS['game']['med_tower'],cfg.IMAGEPATHS['game']['heavy_tower']]self.image=pygame.image.load(self.imagepaths[turret_type])self.rect=self.image.get_rect()#箭self.arrow=Arrow(turret_type,cfg)#当前的位置self.coord=0,0self.position=0,0self.rect.left,self.rect.top=self.positionself.reset()'''射击'''defshot(self,position,angle=None):arrow=Noneifnotself.is_cooling:arrow=Arrow(self.turret_type,self.cfg)arrow.reset(position,angle)self.is_cooling=Trueifself.is_cooling:self.cool_time-=1ifself.cool_time==0:self.reset()returnarrow'''重置'''defreset(self):ifself.turret_type==0:#价格self.price=500#射箭的冷却时间self.cool_time=30#是否在冷却期self.is_cooling=Falseelifself.turret_type==1:self.price=1000self.cool_time=50self.is_cooling=Falseelifself.turret_type==2:self.price=1500self.cool_time=100self.is_cooling=False

    4、游戏开始:选择难度地图

    在这里我们把游戏主界面初始化,并把三个难度的地图列出来,让玩家选择。

    importsysimportpygame'''游戏选择主界面'''classMainInterface(pygame.sprite.Sprite):def__init__(self,cfg):pygame.sprite.Sprite.__init__(self)self.image=pygame.image.load(cfg.IMAGEPATHS['choice']['load_game']).convert()self.rect=self.image.get_rect()self.rect.topleft=(0,0)'''更新函数'''defupdate(self):pass'''地图1'''classMapButton1(pygame.sprite.Sprite):def__init__(self,cfg,position=(175,240)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['choice']['map1_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['choice']['map1_red']).convert()self.image_3=pygame.image.load(cfg.IMAGEPATHS['choice']['map1']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''地图2'''classMapButton2(pygame.sprite.Sprite):def__init__(self,cfg,position=(400,240)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['choice']['map2_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['choice']['map2_red']).convert()self.image_3=pygame.image.load(cfg.IMAGEPATHS['choice']['map2']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''地图3'''classMapButton3(pygame.sprite.Sprite):def__init__(self,cfg,position=(625,240)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['choice']['map3_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['choice']['map3_red']).convert()self.image_3=pygame.image.load(cfg.IMAGEPATHS['choice']['map3']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''信息显示框'''classInfoBox(pygame.sprite.Sprite):def__init__(self,position=(400,475)):pygame.sprite.Sprite.__init__(self)self.ori_image=pygame.Surface((625,200))self.ori_image.fill((255,255,255))self.ori_image_front=pygame.Surface((621,196))self.ori_image_front.fill((0,0,0))self.ori_image.blit(self.ori_image_front,(2,2))self.rect=self.ori_image.get_rect()self.rect.center=position'''更新函数'''defupdate(self,btns):self.image=self.ori_imagemouse_pos=pygame.mouse.get_pos()forbtninbtns:ifbtn.rect.collidepoint(mouse_pos):self.image.blit(btn.image_3,(225,25))break'''简单难度按钮'''classEasyButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(400,150)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.Surface((285,100))self.image_1_front=pygame.Surface((281,96))self.image_1.fill((255,255,255))self.image_1_front.fill((0,0,0))self.image_1.blit(self.image_1_front,(2,2))self.image_2=pygame.Surface((285,100))self.image_2_front=pygame.Surface((281,96))self.image_2.fill((255,255,255))self.image_2_front.fill((24,196,40))self.image_2.blit(self.image_2_front,(2,2))self.text='easy'self.font=pygame.font.Font(cfg.FONTPATHS['m04'],42)self.text_render=self.font.render(self.text,1,(255,255,255))self.image_1.blit(self.text_render,(60,29))self.image_2.blit(self.text_render,(60,29))self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''中等难度按钮'''classMediumButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(400,300)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.Surface((285,100))self.image_1_front=pygame.Surface((281,96))self.image_1.fill((255,255,255))self.image_1_front.fill((0,0,0))self.image_1.blit(self.image_1_front,(2,2))self.image_2=pygame.Surface((285,100))self.image_2_front=pygame.Surface((281,96))self.image_2.fill((255,255,255))self.image_2_front.fill((24,30,196))self.image_2.blit(self.image_2_front,(2,2))self.text='medium'self.font=pygame.font.Font(cfg.FONTPATHS['m04'],42)self.text_render=self.font.render(self.text,1,(255,255,255))self.image_1.blit(self.text_render,(15,29))self.image_2.blit(self.text_render,(15,29))self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''困难难度按钮'''classHardButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(400,450)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.Surface((285,100))self.image_1_front=pygame.Surface((281,96))self.image_1.fill((255,255,255))self.image_1_front.fill((0,0,0))self.image_1.blit(self.image_1_front,(2,2))self.image_2=pygame.Surface((285,100))self.image_2_front=pygame.Surface((281,96))self.image_2.fill((255,255,255))self.image_2_front.fill((196,24,24))self.image_2.blit(self.image_2_front,(2,2))self.text='hard'self.font=pygame.font.Font(cfg.FONTPATHS['m04'],42)self.text_render=self.font.render(self.text,1,(255,255,255))self.image_1.blit(self.text_render,(60,29))self.image_2.blit(self.text_render,(60,29))self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''游戏地图和困难选择界面'''classChoiceInterface():def__init__(self,cfg):#part1self.main_interface=MainInterface(cfg)self.map_btn1=MapButton1(cfg)self.map_btn2=MapButton2(cfg)self.map_btn3=MapButton3(cfg)self.info_box=InfoBox()#part2self.easy_btn=EasyButton(cfg)self.medium_btn=MediumButton(cfg)self.hard_btn=HardButton(cfg)'''外部调用'''defupdate(self,screen):clock=pygame.time.Clock()#part1self.map_btns=pygame.sprite.Group(self.map_btn1,self.map_btn2,self.map_btn3)map_choice,difficulty_choice=None,NonewhileTrue:clock.tick(60)self.main_interface.update()self.map_btns.update()self.info_box.update(self.map_btns)screen.blit(self.main_interface.image,self.main_interface.rect)self.map_btns.draw(screen)screen.blit(self.info_box.image,self.info_box.rect)pygame.display.flip()foreventinpygame.event.get():ifevent.type==pygame.QUIT:pygame.quit()sys.exit(0)ifevent.type==pygame.MOUSEBUTTONDOWN:ifevent.button==1:mouse_pos=pygame.mouse.get_pos()idx=0forbtninself.map_btns:idx+=1ifbtn.rect.collidepoint(mouse_pos):map_choice=idxifmap_choice:break#part2self.difficulty_btns=pygame.sprite.Group(self.easy_btn,self.medium_btn,self.hard_btn)whileTrue:clock.tick(60)screen.fill((0,0,0))self.difficulty_btns.update()self.difficulty_btns.draw(screen)pygame.display.flip()foreventinpygame.event.get():ifevent.type==pygame.QUIT:pygame.quit()sys.exit(0)ifevent.type==pygame.MOUSEBUTTONDOWN:ifevent.button==1:mouse_pos=pygame.mouse.get_pos()idx=0forbtninself.difficulty_btns:idx+=1ifbtn.rect.collidepoint(mouse_pos):difficulty_choice=btn.textifdifficulty_choice:breakreturnmap_choice,difficulty_choice

    5、游戏开始界面

    包括开始按钮,退出游戏等操作

    start.py

    importsysimportpygame'''游戏开始主界面'''classMainInterface(pygame.sprite.Sprite):def__init__(self,cfg):pygame.sprite.Sprite.__init__(self)self.image=pygame.image.load(cfg.IMAGEPATHS['start']['start_interface']).convert()self.rect=self.image.get_rect()self.rect.center=cfg.SCREENSIZE[0]/2,cfg.SCREENSIZE[1]/2'''更新函数'''defupdate(self):pass'''开始游戏按钮'''classPlayButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(220,415)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['start']['play_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['start']['play_red']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''结束游戏按钮'''classQuitButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(580,415)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['start']['quit_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['start']['quit_red']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''游戏开始界面'''classStartInterface():def__init__(self,cfg):self.main_interface=MainInterface(cfg)self.play_btn=PlayButton(cfg)self.quit_btn=QuitButton(cfg)self.components=pygame.sprite.LayeredUpdates(self.main_interface,self.play_btn,self.quit_btn)'''外部调用'''defupdate(self,screen):clock=pygame.time.Clock()whileTrue:clock.tick(60)self.components.update()self.components.draw(screen)pygame.display.flip()foreventinpygame.event.get():ifevent.type==pygame.QUIT:pygame.quit()sys.exit(0)elifevent.type==pygame.MOUSEBUTTONDOWN:ifevent.button==1:mouse_pos=pygame.mouse.get_pos()ifself.play_btn.rect.collidepoint(mouse_pos):returnTrueelifself.quit_btn.rect.collidepoint(mouse_pos):returnFalse

    6、游戏运行

    gaming.py

    importsysimportjsonimportmathimportrandomimportpygamefrom..spritesimportEnemyfrom..spritesimportTurretfrom.pauseimportPauseInterfacefromcollectionsimportnamedtuple'''游戏进行中界面'''classGamingInterface():def__init__(self,cfg):self.cfg=cfg#游戏地图大小map_w=self.cfg.SCREENSIZE[0]map_h=500#按钮大小和位置button_w=60button_h=60button_y=520#间隙gap=20#按钮放在工具栏,工具栏两端各有一个信息显示框toolbar_w=gap*7+button_w*6info_w=(self.cfg.SCREENSIZE[0]-toolbar_w)//2info_h=self.cfg.SCREENSIZE[1]-map_htoolbar_h=self.cfg.SCREENSIZE[1]-map_h#界面布置self.map_rect=pygame.Rect(0,0,map_w,map_h)self.map_surface=pygame.Surface((map_w,map_h))self.leftinfo_rect=pygame.Rect(0,map_h,info_w,info_h)self.rightinfo_rect=pygame.Rect(self.cfg.SCREENSIZE[0]-info_w,map_h,info_w,info_h)self.toolbar_rect=pygame.Rect(info_w,map_h,toolbar_w,toolbar_h)#草self.grass=pygame.image.load(cfg.IMAGEPATHS['game']['grass'])#岩石(铺路用的)self.rock=pygame.image.load(cfg.IMAGEPATHS['game']['rock'])#污垢self.dirt=pygame.image.load(cfg.IMAGEPATHS['game']['dirt'])#水self.water=pygame.image.load(cfg.IMAGEPATHS['game']['water'])#灌木self.bush=pygame.image.load(cfg.IMAGEPATHS['game']['bush'])#纽带self.nexus=pygame.image.load(cfg.IMAGEPATHS['game']['nexus'])#洞穴self.cave=pygame.image.load(cfg.IMAGEPATHS['game']['cave'])#获取地图元素的大小,请保证素材库里组成地图的元素图大小一致self.element_size=int(self.grass.get_rect().width)#一些字体self.info_font=pygame.font.Font(cfg.FONTPATHS['Calibri'],14)self.button_font=pygame.font.Font(cfg.FONTPATHS['Calibri'],20)#可以放炮塔的地方self.placeable={0:self.grass}#地图元素字典(数字对应.map文件中的数字)self.map_elements={0:self.grass,1:self.rock,2:self.dirt,3:self.water,4:self.bush,5:self.nexus,6:self.cave}#用于记录地图中的道路self.path_list=[]#当前的地图,将地图导入到这里面self.current_map=dict()#当前鼠标携带的图标(即选中道具)->[道具名,道具]self.mouse_carried=[]#在地图上建造好了的炮塔self.built_turret_group=pygame.sprite.Group()#所有的敌人self.enemies_group=pygame.sprite.Group()#所有射出的箭self.arrows_group=pygame.sprite.Group()#玩家操作用的按钮Button=namedtuple('Button',['rect','text','onClick'])self.buttons=[Button(pygame.Rect((info_w+gap),button_y,button_w,button_h),'T1',self.takeT1),Button(pygame.Rect((info_w+gap*2+button_w),button_y,button_w,button_h),'T2',self.takeT2),Button(pygame.Rect((info_w+gap*3+button_w*2),button_y,button_w,button_h),'T3',self.takeT3),Button(pygame.Rect((info_w+gap*4+button_w*3),button_y,button_w,button_h),'XXX',self.takeXXX),Button(pygame.Rect((info_w+gap*5+button_w*4),button_y,button_w,button_h),'Pause',self.pauseGame),Button(pygame.Rect((info_w+gap*6+button_w*5),button_y,button_w,button_h),'Quit',self.quitGame)]'''开始游戏'''defstart(self,screen,map_path=None,difficulty_path=None):#读取游戏难度对应的参数withopen(difficulty_path,'r')asf:difficulty_dict=json.load(f)self.money=difficulty_dict.get('money')self.health=difficulty_dict.get('health')self.max_health=difficulty_dict.get('health')difficulty_dict=difficulty_dict.get('enemy')#每60s生成一波敌人generate_enemies_event=pygame.constants.USEREVENT+0pygame.time.set_timer(generate_enemies_event,60000)#生成敌人的flag和当前已生成敌人的总次数generate_enemies_flag=Falsenum_generate_enemies=0#每0.5秒出一个敌人generate_enemy_event=pygame.constants.USEREVENT+1pygame.time.set_timer(generate_enemy_event,500)generate_enemy_flag=False#防止变量未定义enemy_range=Nonenum_enemy=None#是否手动操作箭塔射击manual_shot=Falsehas_control=False#游戏主循环whileTrue:ifself.health<=0:returnforeventinpygame.event.get():ifevent.type==pygame.QUIT:self.quitGame()ifevent.type==pygame.MOUSEBUTTONUP:#--左键选物品ifevent.button==1:#----鼠标点击在地图上ifself.map_rect.collidepoint(event.pos):ifself.mouse_carried:ifself.mouse_carried[0]=='turret':self.buildTurret(event.pos)elifself.mouse_carried[0]=='XXX':self.sellTurret(event.pos)#----鼠标点击在工具栏elifself.toolbar_rect.collidepoint(event.pos):forbuttoninself.buttons:ifbutton.rect.collidepoint(event.pos):ifbutton.text=='T1':button.onClick()elifbutton.text=='T2':button.onClick()elifbutton.text=='T3':button.onClick()elifbutton.text=='XXX':button.onClick()elifbutton.text=='Pause':button.onClick(screen)elifbutton.text=='Quit':button.onClick()break#--右键释放物品ifevent.button==3:self.mouse_carried=[]#--按中间键手动控制炮塔射箭方向一次,否则自由射箭ifevent.button==2:manual_shot=Trueifevent.type==generate_enemies_event:generate_enemies_flag=Trueifevent.type==generate_enemy_event:generate_enemy_flag=True#--生成敌人,生成的敌人随当前已生成敌人的总次数的增加而变强变多ifgenerate_enemies_flag:generate_enemies_flag=Falsenum_generate_enemies+=1idx=0forkey,valueindifficulty_dict.items():idx+=1ifidx==len(difficulty_dict.keys()):enemy_range=value['enemy_range']num_enemy=value['num_enemy']breakifnum_generate_enemies<=int(key):enemy_range=value['enemy_range']num_enemy=value['num_enemy']breakifgenerate_enemy_flagandnum_enemy:generate_enemy_flag=Falsenum_enemy-=1enemy=Enemy(random.choice(range(enemy_range)),self.cfg)self.enemies_group.add(enemy)#--射箭forturretinself.built_turret_group:ifnotmanual_shot:position=turret.position[0]+self.element_size//2,turret.position[1]arrow=turret.shot(position)else:position=turret.position[0]+self.element_size//2,turret.position[1]mouse_pos=pygame.mouse.get_pos()angle=math.atan((mouse_pos[1]-position[1])/(mouse_pos[0]-position[0]+1e-6))arrow=turret.shot(position,angle)has_control=Trueifarrow:self.arrows_group.add(arrow)else:has_control=Falseifhas_control:has_control=Falsemanual_shot=False#--移动箭和碰撞检测forarrowinself.arrows_group:arrow.move()points=[(arrow.rect.left,arrow.rect.top),(arrow.rect.left,arrow.rect.bottom),(arrow.rect.right,arrow.rect.top),(arrow.rect.right,arrow.rect.bottom)]if(notself.map_rect.collidepoint(points[0]))and(notself.map_rect.collidepoint(points[1]))and\(notself.map_rect.collidepoint(points[2]))and(notself.map_rect.collidepoint(points[3])):self.arrows_group.remove(arrow)delarrowcontinueforenemyinself.enemies_group:ifpygame.sprite.collide_rect(arrow,enemy):enemy.life_value-=arrow.attack_powerself.arrows_group.remove(arrow)delarrowbreakself.draw(screen,map_path)'''将场景画到游戏界面上'''defdraw(self,screen,map_path):self.drawToolbar(screen)self.loadMap(screen,map_path)self.drawMouseCarried(screen)self.drawBuiltTurret(screen)self.drawEnemies(screen)self.drawArrows(screen)pygame.display.flip()'''画出所有射出的箭'''defdrawArrows(self,screen):forarrowinself.arrows_group:screen.blit(arrow.image,arrow.rect)'''画敌人'''defdrawEnemies(self,screen):forenemyinself.enemies_group:ifenemy.life_value<=0:self.money+=enemy.rewardself.enemies_group.remove(enemy)delenemycontinueres=enemy.move(self.element_size)ifres:coord=self.find_next_path(enemy)ifcoord:enemy.reached_path.append(enemy.coord)enemy.coord=coordenemy.position=self.coord2pos(coord)enemy.rect.left,enemy.rect.top=enemy.positionelse:self.health-=enemy.damageself.enemies_group.remove(enemy)delenemycontinue#画血条green_len=max(0,enemy.life_value/enemy.max_life_value)*self.element_sizeifgreen_len>0:pygame.draw.line(screen,(0,255,0),(enemy.position),(enemy.position[0]+green_len,enemy.position[1]),1)ifgreen_len<self.element_size:pygame.draw.line(screen,(255,0,0),(enemy.position[0]+green_len,enemy.position[1]),(enemy.position[0]+self.element_size,enemy.position[1]),1)screen.blit(enemy.image,enemy.rect)'''画已经建造好的炮塔'''defdrawBuiltTurret(self,screen):forturretinself.built_turret_group:screen.blit(turret.image,turret.rect)'''画鼠标携带物'''defdrawMouseCarried(self,screen):ifself.mouse_carried:position=pygame.mouse.get_pos()coord=self.pos2coord(position)position=self.coord2pos(coord)#在地图里再画ifself.map_rect.collidepoint(position):ifself.mouse_carried[0]=='turret':screen.blit(self.mouse_carried[1].image,position)self.mouse_carried[1].coord=coordself.mouse_carried[1].position=positionself.mouse_carried[1].rect.left,self.mouse_carried[1].rect.top=positionelse:screen.blit(self.mouse_carried[1],position)'''画工具栏'''defdrawToolbar(self,screen):#信息显示框info_color=(120,20,50)#--左pygame.draw.rect(screen,info_color,self.leftinfo_rect)left_title=self.info_font.render('Playerinfo:',True,(255,255,255))money_info=self.info_font.render('Money:'+str(self.money),True,(255,255,255))health_info=self.info_font.render('Health:'+str(self.health),True,(255,255,255))screen.blit(left_title,(self.leftinfo_rect.left+5,self.leftinfo_rect.top+5))screen.blit(money_info,(self.leftinfo_rect.left+5,self.leftinfo_rect.top+35))screen.blit(health_info,(self.leftinfo_rect.left+5,self.leftinfo_rect.top+55))#--右pygame.draw.rect(screen,info_color,self.rightinfo_rect)right_title=self.info_font.render('Selectedinfo:',True,(255,255,255))screen.blit(right_title,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+5))#中间部分pygame.draw.rect(screen,(127,127,127),self.toolbar_rect)forbuttoninself.buttons:mouse_pos=pygame.mouse.get_pos()ifbutton.rect.collidepoint(mouse_pos):self.showSelectedInfo(screen,button)button_color=(0,200,0)else:button_color=(0,100,0)pygame.draw.rect(screen,button_color,button.rect)button_text=self.button_font.render(button.text,True,(255,255,255))button_text_rect=button_text.get_rect()button_text_rect.center=(button.rect.centerx,button.rect.centery)screen.blit(button_text,button_text_rect)'''显示被鼠标选中按钮的作用信息'''defshowSelectedInfo(self,screen,button):ifbutton.textin['T1','T2','T3']:turret=Turret({'T1':0,'T2':1,'T3':2}[button.text],self.cfg)selected_info1=self.info_font.render('Cost:'+str(turret.price),True,(255,255,255))selected_info2=self.info_font.render('Damage:'+str(turret.arrow.attack_power),True,(255,255,255))selected_info3=self.info_font.render('Affordable:'+str(self.money>=turret.price),True,(255,255,255))screen.blit(selected_info1,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+35))screen.blit(selected_info2,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+55))screen.blit(selected_info3,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+75))elifbutton.text=='XXX':selected_info=self.info_font.render('Sellaturret',True,(255,255,255))screen.blit(selected_info,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+35))elifbutton.text=='Pause':selected_info=self.info_font.render('Pausegame',True,(255,255,255))screen.blit(selected_info,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+35))elifbutton.text=='Quit':selected_info=self.info_font.render('Quitgame',True,(255,255,255))screen.blit(selected_info,(self.rightinfo_rect.left+5,self.rightinfo_rect.top+35))'''出售炮塔(半价)'''defsellTurret(self,position):coord=self.pos2coord(position)forturretinself.built_turret_group:ifcoord==turret.coord:self.built_turret_group.remove(turret)self.money+=int(turret.price*0.5)delturretbreak'''建造炮塔'''defbuildTurret(self,position):turret=self.mouse_carried[1]coord=self.pos2coord(position)position=self.coord2pos(coord)turret.position=positionturret.coord=coordturret.rect.left,turret.rect.top=positionifself.money-turret.price>=0:ifself.current_map.get(turret.coord)inself.placeable.keys():self.money-=turret.priceself.built_turret_group.add(turret)ifself.mouse_carried[1].turret_type==0:self.mouse_carried=[]self.takeT1()elifself.mouse_carried[1].turret_type==1:self.mouse_carried=[]self.takeT2()elifself.mouse_carried[1].turret_type==2:self.mouse_carried=[]self.takeT3()'''拿炮塔1'''deftakeT1(self):T1=Turret(0,self.cfg)ifself.money>=T1.price:self.mouse_carried=['turret',T1]'''拿炮塔2'''deftakeT2(self):T2=Turret(1,self.cfg)ifself.money>=T2.price:self.mouse_carried=['turret',T2]'''拿炮塔3'''deftakeT3(self):T3=Turret(2,self.cfg)ifself.money>=T3.price:self.mouse_carried=['turret',T3]'''出售炮塔'''deftakeXXX(self):XXX=pygame.image.load(self.cfg.IMAGEPATHS['game']['x'])self.mouse_carried=['XXX',XXX]'''找下一个路径单元'''deffind_next_path(self,enemy):x,y=enemy.coord#优先级:下右左上neighbours=[(x,y+1),(x+1,y),(x-1,y),(x,y-1)]forneighbourinneighbours:if(neighbourinself.path_list)and(neighbournotinenemy.reached_path):returnneighbourreturnNone'''将真实坐标转为地图坐标,20个单位长度的真实坐标=地图坐标'''defpos2coord(self,position):return(position[0]//self.element_size,position[1]//self.element_size)'''将地图坐标转为真实坐标,20个单位长度的真实坐标=地图坐标'''defcoord2pos(self,coord):return(coord[0]*self.element_size,coord[1]*self.element_size)'''导入地图'''defloadMap(self,screen,map_path):map_file=open(map_path,'r')idx_j=-1forlineinmap_file.readlines():line=line.strip()ifnotline:continueidx_j+=1idx_i=-1forcolinline:try:element_type=int(col)element_img=self.map_elements.get(element_type)element_rect=element_img.get_rect()idx_i+=1element_rect.left,element_rect.top=self.element_size*idx_i,self.element_size*idx_jself.map_surface.blit(element_img,element_rect)self.current_map[idx_i,idx_j]=element_type#把道路记下来ifelement_type==1:self.path_list.append((idx_i,idx_j))except:continue#放洞穴和大本营self.map_surface.blit(self.cave,(0,0))self.map_surface.blit(self.nexus,(740,400))#大本营的血条nexus_width=self.nexus.get_rect().widthgreen_len=max(0,self.health/self.max_health)*nexus_widthifgreen_len>0:pygame.draw.line(self.map_surface,(0,255,0),(740,400),(740+green_len,400),3)ifgreen_len<nexus_width:pygame.draw.line(self.map_surface,(255,0,0),(740+green_len,400),(740+nexus_width,400),3)screen.blit(self.map_surface,(0,0))map_file.close()'''暂停游戏'''defpauseGame(self,screen):pause_interface=PauseInterface(self.cfg)pause_interface.update(screen)'''退出游戏'''defquitGame(self):pygame.quit()sys.exit(0)

    7、游戏暂停

    importsysimportpygame'''游戏暂停主界面'''classMainInterface(pygame.sprite.Sprite):def__init__(self,cfg):pygame.sprite.Sprite.__init__(self)self.image=pygame.image.load(cfg.IMAGEPATHS['pause']['gamepaused']).convert()self.rect=self.image.get_rect()self.rect.center=cfg.SCREENSIZE[0]/2,cfg.SCREENSIZE[1]/2'''更新函数'''defupdate(self):pass'''恢复游戏按钮'''classResumeButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(391,380)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['pause']['resume_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['pause']['resume_red']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''游戏暂停界面'''classPauseInterface():def__init__(self,cfg):self.main_interface=MainInterface(cfg)self.resume_btn=ResumeButton(cfg)self.components=pygame.sprite.LayeredUpdates(self.main_interface,self.resume_btn)'''外部调用'''defupdate(self,screen):clock=pygame.time.Clock()background=pygame.Surface(screen.get_size())count=0flag=TruewhileTrue:count+=1clock.tick(60)self.components.clear(screen,background)self.components.update()ifcount%10==0:count=0flag=notflagifflag:self.components.draw(screen)else:screen.blit(self.main_interface.image,self.main_interface.rect)pygame.display.flip()foreventinpygame.event.get():ifevent.type==pygame.QUIT:pygame.quit()sys.exit(0)elifevent.type==pygame.MOUSEBUTTONDOWN:ifevent.button==1:mouse_pos=pygame.mouse.get_pos()ifself.resume_btn.rect.collidepoint(mouse_pos):returnTrue

    8、游戏结束及分数

    importsysimportpygame'''游戏结束主界面'''classMainInterface(pygame.sprite.Sprite):def__init__(self,cfg):pygame.sprite.Sprite.__init__(self)self.image=pygame.image.load(cfg.IMAGEPATHS['end']['gameover']).convert()self.rect=self.image.get_rect()self.rect.center=cfg.SCREENSIZE[0]/2,cfg.SCREENSIZE[1]/2'''更新函数'''defupdate(self):pass'''继续游戏按钮'''classContinueButton(pygame.sprite.Sprite):def__init__(self,cfg,position=(400,409)):pygame.sprite.Sprite.__init__(self)self.image_1=pygame.image.load(cfg.IMAGEPATHS['end']['continue_black']).convert()self.image_2=pygame.image.load(cfg.IMAGEPATHS['end']['continue_red']).convert()self.image=self.image_1self.rect=self.image.get_rect()self.rect.center=position'''更新函数:不断地更新检测鼠标是否在按钮上'''defupdate(self):mouse_pos=pygame.mouse.get_pos()ifself.rect.collidepoint(mouse_pos):self.image=self.image_2else:self.image=self.image_1'''游戏结束类'''classEndInterface():def__init__(self,cfg):self.main_interface=MainInterface(cfg)self.continue_btn=ContinueButton(cfg)self.components=pygame.sprite.LayeredUpdates(self.main_interface,self.continue_btn)'''外部调用'''defupdate(self,screen):clock=pygame.time.Clock()background=pygame.Surface(screen.get_size())count=0flag=TruewhileTrue:count+=1clock.tick(60)self.components.clear(screen,background)self.components.update()ifcount%10==0:count=0flag=notflagifflag:self.components.draw(screen)else:screen.blit(self.main_interface.image,self.main_interface.rect)pygame.display.flip()foreventinpygame.event.get():ifevent.type==pygame.QUIT:pygame.quit()sys.exit(0)elifevent.type==pygame.MOUSEBUTTONDOWN:ifevent.button==1:mouse_pos=pygame.mouse.get_pos()ifself.continue_btn.rect.collidepoint(mouse_pos):returnTrue

    9、引入音频、图片、地图、难度json

    启动游戏主程序

    tower.py

    importcfgimportpygamefrommodulesimport*'''主函数'''defmain():pygame.init()pygame.mixer.init()pygame.mixer.music.load(cfg.AUDIOPATHS['bgm'])pygame.mixer.music.play(-1,0.0)pygame.mixer.music.set_volume(0.25)screen=pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.set_caption("塔防游戏——hacklex")#调用游戏开始界面start_interface=StartInterface(cfg)is_play=start_interface.update(screen)ifnotis_play:return#调用游戏界面whileTrue:choice_interface=ChoiceInterface(cfg)map_choice,difficulty_choice=choice_interface.update(screen)game_interface=GamingInterface(cfg)game_interface.start(screen,map_path=cfg.MAPPATHS[str(map_choice)],difficulty_path=cfg.DIFFICULTYPATHS[str(difficulty_choice)])end_interface=EndInterface(cfg)end_interface.update(screen)'''run'''if__name__=='__main__':main()

    四、游戏启动方法

    1、开发工具启动

    如果你配置了开发工具的环境VScode、sublimeText、notepad+、pycharm什么的,可以直接在工具中,运行游戏。

    如果没配置,可以使用命令启动。

    2、命令行启动 gif

    进入代码根目录,按住shift+鼠标右键,选择 此处运行powershell,然后执行代码:python tower.py

    即可 运行。

    感谢各位的阅读,以上就是“PythonPygame怎么实现塔防游戏”的内容了,经过本文的学习后,相信大家对PythonPygame怎么实现塔防游戏这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是恰卡编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

    发布于 2022-03-17 21:18:27
    收藏
    分享
    海报
    0 条评论
    27
    上一篇:PyTorch中的torch.cat怎么用 下一篇:SpringBoot2.x如何设置Session失效时间及失效跳转
    目录

      推荐阅读

      0 条评论

      本站已关闭游客评论,请登录或者注册后再评论吧~

      忘记密码?

      图形验证码