赞
踩
【上期回顾:Tkinter模块GUI界面化编程实战(四)——随机点名小程序】
这篇博客介绍了如何用Python Tkinter模块编写一个界面化的大鱼吃小鱼游戏,在博客下面有完整的源码,源码中有超详细的注释,帮助大家理解代码(最后还有附件可以免费下载)
【注:下载文件100%可以运行,因为下载文件中包含打包了的Python程序(exe文件)!】
【玩家有3条生命,在右上角的红色方块显示】
【初始时,有一个帮助对话框(画出来的)】
【玩家是中间那个小黑鱼,白色的圆形是鱼眼(比较简陋,勿喷)】
——玩家:这鱼怎么这么丑,方方正正的,《我的世界》里的鱼都比这“玩意儿”好看!
——小鱼:你礼貌吗?
【新鱼刷新时间随机,颜色随机,大小随机,速度随机,位置随机,朝向随机,鱼眼大小随机】
【玩家扣血后会有1秒无敌时间】
【死亡界面,胜利界面就不展示了(我玩了半天也没胜利 ToT)】
【有胜利的伙伴们可以在评论区留言哟!】
程序实现功能清单
游戏任务:大鱼吃小鱼游戏
游戏规则:玩家3条命;扣血之后一秒无敌
分数增加:吃掉鱼的长宽之和
碰撞检测:产生碰撞时,比较玩家和碰撞鱼的面积大小,以此进行死亡和加分判断
【源码中几乎每行后都有详细注释,方便大家理解】
- from tkinter import *#引入界面化编程模块
- from random import *#引入随机数模块
-
- game = Tk()#创建窗口
- game.geometry('960x480+150+100')#设置窗口大小及位置
- game.resizable(0,0)#设置窗口大小为不可更改
-
- class Game0:#定义Game类,方便重置游戏
- def __init__(self):
- self.pw,self.ph,self.px,self.py=40,20,455,250#玩家的初始位置
- self.pf=15#玩家鱼眼大小
- self.count=0#死亡计数器
- self.god=False#无敌标识
- self.score=0#得分
- self.RGBcolorlist = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']#RGB码所有颜色字符
- self.Score=IntVar()#分数显示变量
- self.Score.set(self.score)#设置界面化中的分数为初始分数
-
- self.Game = Frame(game)#定义框架,方便删除
- self.Game.place(width=960,height=480)
- self.main = Frame(self.Game)#定义框架,方便删除
- self.main.place(width=960,height=480)
- self.player = Label(self.Game,bg='black',fg='white',font=('consolas',self.pf),text='O',anchor='w')#画出玩家(其实就是个黑色矩形)
- self.player.place(width=self.pw,height=self.ph,y=self.py,x=self.px)#放置玩家的位置
-
- Label(self.Game,bg='lightgreen',textvariable=self.Score,font=('华文新魏',20)).place(width=960,height=40)#背景
-
- for i in range(3):Label(self.Game,bg='red').place(width=30,height=30,y=5,x=925-35*i)#命数显示
-
- self.life = Label(self.Game,bg='lightgreen')
- self.life.place(height=40,x=845,width=0)
-
- Button(self.Game,bd=0,bg='orange',text='退出',font=('华文新魏',15),command=lambda:self.fishquit()).place(width=100,height=30,y=5,x=5)#退出按钮
- Button(self.Game,bd=0,bg='orange',text='重置',font=('华文新魏',15),command=lambda:self.fishagain()).place(width=100,height=30,y=5,x=110)#重置按钮
-
- self.Gamestart()#执行Gamestart函数
-
- game.mainloop()#窗口进入消息事件循环
-
- def Gamestart(self):
- Gamehelp = Frame(self.Game)#帮助对话框
- Gamehelp.place(width=600,height=360,y=60,x=180)
- Label(Gamehelp,text='帮助',bg='grey',font=('华文新魏',15)).place(width=600,height=30)#帮助对话框标题
- Label(Gamehelp,bg='lightgreen',font=('华文新魏',20),text='按‘w’、‘s’、‘a’和‘d’进行移动!\n4000分胜利!\n祝你好运!').place(width=600,height=300,y=30)#帮助对话框主体
- Label(Gamehelp,bg='grey').place(width=600,height=30,y=330)
- Button(Gamehelp,bg='lightgreen',text='确定',bd=0,font=('华文新魏',12),command=lambda:start()).place(width=80,height=20,y=335,x=510)#确定按钮
-
- def start():#游戏开始
- game.bind('<Any-KeyPress>',lambda event:self.playmove(event.char))#键盘关联
- self.randomfish()#开始随机产生鱼
- Gamehelp.destroy()#摧毁帮助对话框,释放内存
-
- def fishagain(self):#重置函数
- self.pw,self.ph,self.px,self.py=40,20,455,250#重设玩家位置
- self.pf=15#重设玩家鱼眼大小
- self.count=0#重设死亡计数器
- self.score=0#重设分数
- self.Game.destroy()#摧毁之前的界面,释放内存
- Game0()#重置游戏,重新实例化类
-
- def fishquit(self):game.quit()#退出游戏
-
- def victory(self):#胜利设定
- if self.score >= 4000:#4000分胜利
- Label(self.Game,bg='lightyellow',font=('华文新魏',100),text='- Victory -',fg='orange').place(width=960,height=440,y=40)#设置并显示胜利界面
- self.main.destroy()#摧毁被覆盖的界面,释放内存
-
- def death(self):#死亡设定
- self.count+=1#死亡次数加一
-
- if self.count <3:#死亡次数小于3
- self.god = True if self.god == False else False#切换无敌模式的开关
- self.life.place(height=40,x=845,width=self.count*40)
- else:#3条命都已用完
- self.life.place(height=40,x=845,width=120)
- self.main.destroy()#摧毁之前的界面,释放内存
- Label(self.Game,bg='lightyellow',font=('华文新魏',100),text='- You Dead -',fg='orange').place(width=960,height=440,y=40)
-
- if self.god == True:#打开无敌模式
- self.count-=1#死亡减一(与前面的死亡次数加一抵消)
- self.Game.after(1000,self.death)#1000ms后关闭无敌模式
-
- def eattest(self,fish,rw,rh,ry,rx):#碰撞检测
- if self.god == False:#没有无敌模式的时候进行碰撞检测
- pxw = self.px+self.pw
- pyh = self.py+self.ph
- rxw = rx+rw
- ryh = ry+rh
- #判断是否有碰撞(矩形有重合部分)
- test = True if (self.px<rx<pxw or self.px<rxw<pxw or rx<self.px<rxw or rx<pxw<rxw) and (self.py<ry<pyh or self.py<ryh<pyh or ry<self.py<ryh or ry<pyh<ryh) else False
- if test == True:#发生碰撞
- if self.pw*self.ph > rw*rh:#玩家成功吃掉猎物
- fish.destroy()#将吃掉的鱼摧毁,释放内存
- self.score+=rw+rh#加分
- self.Score.set(self.score)#更新分数
- #玩家体积更新
- self.pw=self.score//40+40
- self.ph=self.score//80+20
- self.pf=self.score//100+15
- self.player.config(font=('consolas',self.pf))#玩家鱼眼大小更新
- self.victory()#执行胜利检测函数
- else:#玩家体积太小无法吃掉猎物,则扣血
- self.death()#执行死亡函数
-
- def fishmove(self,fish,speed,rway,rw,rh,ry,rx):#鱼的移动
- rx += speed if rway == 'e' else -1*speed#鱼每10ms的横坐标方向位移
- fish.place(width=rw,height=rh,y=ry,x=rx)#放置鱼
- self.eattest(fish,rw,rh,ry,rx)#碰撞检测
-
- if rx >960 or rx+rw <0:fish.destroy()#鱼游出了屏幕,摧毁它,释放内存
- else:self.main.after(10,self.fishmove,fish,speed,rway,rw,rh,ry,rx)#重复移动该鱼
-
- def randomfish(self,rcolor='#'):#随机刷新鱼
- for _ in range(6):rcolor+=choice(self.RGBcolorlist)#新鱼的颜色
-
- speed = randint(10,100+self.score//100)*0.01#新鱼的速度
- rway = choice(['w','e'])#新鱼的朝向
- rh = randint(self.ph//4,self.ph*2)#新鱼的高
-
- while 1:#新鱼的宽
- rw = randint(self.pw//4,self.pw*2)
- if rw > 1.2*rh:break
-
- rx = -1*rw if rway == 'e' else 960#新鱼的初始横坐标
- ry = randint(40,480-rh)#新鱼的初始纵坐标
- rf = rh//2#新鱼的鱼眼大小
- fish = Label(self.main,bg=rcolor,font=('consolas',rf),text='O',anchor=rway)#创建新鱼
- fish.place(width=rw,height=rh,y=ry,x=rx)#放置新鱼
-
- self.fishmove(fish,speed,rway,rw,rh,ry,rx)#让产生的新鱼移动
- self.main.after(randint(1000,3000),self.randomfish)#每1000ms到3000ms内随机产生一条新鱼
-
- def playmove(self,way):#玩家移动
- #计算玩家位置
- if way == 'w' and self.py>40:#按下w键
- self.py-=10
- elif way == 's' and self.py<=470-self.ph:#按下s键
- self.py+=10
- elif way == 'a' and self.px>0:#按下a键
- self.px-=10
- self.player.config(anchor='w')#设置鱼头朝向
- elif way == 'd' and self.px<=955-self.pw:#按下d键
- self.px+=10
- self.player.config(anchor='e')#设置鱼头朝向
-
- self.player.place(width=self.pw,height=self.ph,y=self.py,x=self.px)#移动玩家位置
-
- Game0()#实例化该类
其实是可以用一个类来实现鱼的随机产生的,但是我这里用的是函数,通过函数的传参来实现于类相似的功能,这里要注意的难点应该就是函数的传参了
说明:关于这个鱼的样式,我没有特别地去进行美化,大家可以用Label控件的image参数来给鱼贴上贴图美化它们,我这里只是写个框架,细节可以由大家自由发挥
【 原创不易,大家都看到这里了,点个赞,分个享,收个藏应该很简单呀!】
完整程序及源码下载链接【蓝奏云】:fish.zip【密码:9s4d】
【下期预告:Python Tkinter编写超级游戏盒子】【下期链接:超级游戏盒子】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。