本帖最后由 木子呢 于 2021-11-9 16:48 编辑  
 
Mind+Python编程入门系列课程第八课——弹球小游戏  
 
 
 
 一、学习背景
经过上节课的学习,我们了解了面向对象的编程思想,也学习了python中与类相关的知识,同时,也学会了借助tkinter库创建窗口及按钮组件等。那么在这节课上,我们将深入学习python知识,结合tkinter库,设计一个小游戏,让我们拭目以待吧!    
 二、学习目标
本实践项目通过编写python程序来设计一个弹球小游戏。  
知识目标: 1、理解python中的逻辑运算符 2、理解列表的索引 3、掌握类的实例方法的创建  
 技能目标:1、掌握使用tkinter库实现键盘交互的方法  
   三、学习准备 
1、电脑 2、mind+编程软件 
四、学习实践 
在本项目中,我们将创建两个python程序,之后运行程序,通过按动键盘上的不同按钮,实现弹球小游戏的游戏效果。 
1.创建一个游戏界面 2.添加小球和球拍两个角色 3.设定游戏的机制和规则 
游戏玩法机制:游戏开始时,一个小球现身于窗口界面的中间,而在界面的底部是一个长方形球拍。游戏开始后,小球自动向上弹出,遇到界面的上边缘及左右两边则反弹回来。 之后我们通过键盘的左右两个方向键来控制球拍的移动,接住下落的小球。若成功接到,小球则再次向上反弹。倘若未能接住小球,使得小球与界面下边缘接触,则游戏结束,球拍和小球停止移动,并在窗口上显示“Game Over”。 
任务1:创建窗口程序设计 
在这个程序中,我们首先将创建一个游戏界面。通过它,我们可以回顾通过tkinter库创建并设置窗口属性的方法。为此,我们将分三步创建这个程序。首先是分析任务,之后进行程序的编写,最后运行程序并观察效果。  
 1、任务分析 
在这个任务中,我们首先需要创建一个窗口对象作为后续的游戏界面。 整体上我们按照顺序结构的方式编写程序,具体流程如下,  
 
2、程序编写 
在正式编写程序代码之前,我们首先要创建一个项目文件及python程序文件。 STEP1:创建与保存项目文件 启动Mind+,另存项目并命名为“弹球小游戏”。 
STEP2:创建与保存python文件 创建一个python程序文件“任务一.py”,双击打开。 
STEP3:编写程序 
			
			
			- import tkinter#引入GUI工具包turtle库
 - #创建一个界面和配置界面的一些基本属性
 - window = tkinter.Tk()#创建一个tk的窗口实例对象
 - window.title('Game')#设置窗口标题为game
 - window.resizable(0, 0)#通知窗口管理器调整布局大小,0,0表示不能被拉伸
 - window.wm_attributes('-topmost', 1)#窗口永远在前
 - #创建一个500x400的界面,背景色为浅绿色,边框为厚度为0
 - canvas = tkinter.Canvas(window, width=500, height=400, highlightthickness=0,bg='light green')
 - canvas.pack()#安置画布
 - 
 - #初始界面,画布上绘制文字
 - leftsigal=canvas.create_text(430,50,text='LEFT:LEFT',font=('Times',10),state='normal')
 - rightsigal=canvas.create_text(430,70,text='RIGHT:RIGHT',font=('Times',10),state='normal')
 - over=canvas.create_text(250,200,text='GAME OVER',font=('Times',30),state='hidden')
 - 
 - window.update()#更新界面
 - window.mainloop()#循环
 
  复制代码
  
3、程序运行 
运行程序,我们看到:弹出了一个标题为“Game”的绿色背景的游戏界面,在右上方写有左移和右移的键盘按钮操作标记。  
  
对象链接  |  create_text()方法 功能说明    .create_text()方法能在画布上书写文字 使用方法    画布对象.create_text(x坐标,y坐标,text=‘文字内容’,font=(‘字体’,字号),state='状态'),其中这里的状态可以是“hidden”表示隐藏文字,也可以是“normal”,表示正常显示文字。   举例说明    程序中, over=canvas.create_text(250,200,text='GAME OVER',font=('Times',30),state='hidden') 表示在画布的(250,200)坐标位书写文字,内容为“GAME OVER”,字体为“Times”,字号30,状态为隐藏不可见。 leftsigal=canvas.create_text(430,50,text='LEFT:LEFT',font=('Times',10),state='normal') rightsigal=canvas.create_text(430,70,text='RIGHT:RIGHT',font=('Times',10),state='normal') 表示在画布上书写左右转的文字标记后将内容显示出来。  |  
    
任务2:添加角色程序设计 
在这个程序中,我们将在刚才创建的界面上添加游戏的角色。通过它,我们可以回顾通过实例化类来创建球拍和小球对象的方法。为此,我们将分三步创建这个程序。首先是分析任务,之后进行程序的编写,最后运行程序并观察效果。  
 1、任务分析 
在这个游戏中,我们最主要的角色是小球和球拍,因此,我们接下来将分别创建小球对象和球拍对象。而为了实现弹球,小球和球拍都将具有移动的行为,也拥有大小、颜色等属性。因此,这里,我们通过先创建小球类和球拍类,再实例化类的方式来生成这两个对象。 
 整体上我们按照顺序结构的方式编写程序,具体流程如下,  
 
为了设置小球和球拍的属性和行为,编程时我们在各自的类中再创建一个init方法,在其中设置相应的属性及功能。  
 
其中,对于矩形球拍的创建我们通过确定两个坐标点位的方式来实现,并将两个坐标点位记录下来以便后续使用,  
 
2、程序编写 STEP1:创建与保存python文件 新建一个python程序文件“任务二.py”,双击打开。  
   STEP2:编写程序 - import tkinter  #引入GUI工具包turtle库
 - 
 - #创建一个界面和配置界面的一些基本属性
 - window = tkinter.Tk()#创建一个tk的窗口实例对象
 - window.title('Game')#设置窗口标题为game
 - window.resizable(0, 0)#通知窗口管理器调整布局大小,0,0表示不能被拉伸
 - window.wm_attributes('-topmost', 1)#窗口永远在前
 - #创建一个500x400的界面,背景色为浅绿色,边框为厚度为0
 - canvas = tkinter.Canvas(window, width=500, height=400, highlightthickness=0,bg='light green')
 - canvas.pack()#安置画布
 - 
 - #初始界面,画布上绘制文字
 - leftsigal=canvas.create_text(430,50,text='LEFT:LEFT',font=('Times',10),state='normal')
 - rightsigal=canvas.create_text(430,70,text='RIGHT:RIGHT',font=('Times',10),state='normal')
 - over=canvas.create_text(250,200,text='GAME OVER',font=('Times',30),state='hidden')
 - 
 - class Paddle:#创建球拍类
 -     def __init__(self,canvas,color):#创建init方法来初始化
 -         self.canvas=canvas #初始化canvas画布
 - #保存tkinter画球拍时返回的id,为后期移动屏幕上的球拍做准备,create_rectangle 画矩形,fill为球拍的颜色
 -         self.id=canvas.create_rectangle(0,0,150,10,fill=color)#画一个矩形并记录下它的id
 -         self.canvas.move(self.id,150,380)#将球拍移动至(150,380)初始位置
 -         self.canvas_width=self.canvas.winfo_width()#球拍的画布宽度铺满
 - 
 - class Ball():#创建球类
 -     '''创建Ball类,初始化对象,即创建对象设置属性,一个canvas也就是画图用来画一个球,一个是color,表示球的颜色
 -     init是在对象被创建的同时就设置属性的一种方法,Python会在创建新对象时自动调用。'''
 -     def __init__(self,canvas,paddle,color):#创建init方法来初始化
 -         self.canvas=canvas#初始化canvas
 -         self.paddle=paddle#初始化paddle
 -         '''保存tkinter画小球返回的id,为后期移动屏幕上的小球做准备,参数分别表示为:(10,10)
 -         表示左上角x,y坐标,(25,25)表示右下角x,y坐标,即创建一个直径为15的圆,fill为小球的填充色'''
 -         self.id=canvas.create_oval(10,10,25,25,fill=color)#画圆并记录下它的id
 -         self.canvas.move(self.id,245,100)#将小球移动到初始位置,初始位置可通过传参进行更改,有默认值
 - 
 - paddle = Paddle(canvas, 'blue')#创建球拍的实例
 - ball = Ball(canvas, paddle, 'red')#创建球的实例
 - 
 - window.update()#更新界面
 - window.mainloop()#循环
 
  复制代码
  
 
3、程序运行运行程序,我们看到:在游戏界面上新出现了一个红色的小球和一个蓝色球拍。  
  
  
任务3:设定机制程序设计  
 在这个程序中,我们将设定游戏的规则机制,实现完整的弹球小游戏功能。为此,我们依旧将分三步创建这个程序。首先是分析任务,之后进行程序的编写,最后运行程序并观察效果。  
   游戏玩法机制:游戏开始时,一个小球现身于窗口界面的中间,而在界面的底部是一个长方形球拍。游戏开始后,小球自动向上弹出,界面的上边缘及左右两边则反弹回来。  
 之后我们通过键盘的左右两个方向键来控制球拍的移动,接住下落的小球。若成功接到,小球则再次向上反弹。倘若未能接住小球,使得小球与界面下边缘接触,则游戏结束,球拍和小球停止移动,并在窗口上显示“Game Over”。    
 1、任务分析小球和球拍我们已经成功建成了,接下来,对于球拍,为了能通过键盘按键来控制它的移动,在球拍类中我们再创建两个实现左移和右移的实例方法,并在“__init__”方法中绑定鼠标的“左移”和“右移”两个键位且分别调用相应的实例方法,同时设定它初始时静止,移速为0。  
 
在绑定好键盘事件后,为了避免球拍在窗口上随处移动,我们可使球拍的纵坐标固定下来,仅能左右移动,同时,我们也需设定其左右移动的范围,避免跑出游戏界面。这里,我们通过添加一个draw()方法来实现。  
 
其中,由于球拍只能左右移动,因此在与边界判别时我们只需要用其左上角和右下角的x坐标与画布的两边宽作比较,而之前我们将(x1,y1),(x2,y2)两个坐标点位记录了下来,这里判别时我们只需要再次读取x1,x2即可,  
 
而对于边界进行判别,我们通过条件判断语句来实现,具体流程如下,  
  
 
综上,对于球拍类,我们总计创建了四个实例方法来设定它的属性及功能。  
 
在设定完球拍后,我们同样需要创建实例方法来对小球进行设定。首先,我们需要设置小球的初始移动,为了使小球在游戏开始时往上方任意位置移动,我们需要将小球初始的横向移速随机化,并设定固定的向上移速,同时,为了避免一开始游戏就结束,我们需要通过一个变量来存储小球是否碰撞到画布底部的结果。  
  
 接着,对于小球,为了使其能在碰到左侧、右侧以及上侧边缘后反弹,我们需要设定其能横向和纵向移动,活动范围为整个游戏界面,并且和球拍一样,在设定小球碰撞画布四周的情况前我们需要先读取画布上小球的坐标列表,这里我们通过draw()方法来实现。  
  
 
对于小球与各界面的碰撞检测,编程时我们通过条件判断语句来实现,具体流程如下,  
 
最后,我们还需对球拍是否成功接住小球进行判别,这里我们通过hit_paddle()实例方法来实现,具体内容及流程如下,  
 
综上,对于小球类,我们总计创建了三个实例方法来设定它的属性及功能。  
 
在程序的最后,由于游戏的规则在游戏开始后永久有效,因此,对于游戏的规则及界面的设定我们以永久循环的方式编写,具体流程如下,  
 
2、程序编写STEP1:创建与保存python文件 新建一个python程序文件“任务三.py”,双击打开。  
   STEP2:编写程序  
 - import tkinter  #引入GUI工具包turtle库
 - import random   #引入随机函数
 - import time     #引入时间库
 - 
 - #创建一个界面和配置界面的一些基本属性
 - window = tkinter.Tk()#创建一个tk的窗口实例对象
 - window.title('Game')#设置窗口标题为game
 - window.resizable(0, 0)#通知窗口管理器调整布局大小,0,0表示不能被拉伸
 - window.wm_attributes('-topmost', 1)#窗口永远在前
 - #创建一个500x400的界面,背景色为浅绿色,边框为厚度为0
 - canvas = tkinter.Canvas(window, width=500, height=400, highlightthickness=0,bg='light green')
 - canvas.pack()#安置画布
 - 
 - #初始界面,画布上绘制文字
 - leftsigal=canvas.create_text(430,50,text='LEFT:LEFT',font=('Times',10),state='normal')
 - rightsigal=canvas.create_text(430,70,text='RIGHT:RIGHT',font=('Times',10),state='normal')
 - over=canvas.create_text(250,200,text='GAME OVER',font=('Times',30),state='hidden')
 - 
 - class Paddle:#创建球拍类
 -     def __init__(self,canvas,color):#创建init方法来初始化
 -         self.canvas=canvas #初始化canvas画布
 -         # 保存tkinter画球拍时返回的id,为后期移动屏幕上的球拍做准备,create_rectangle 画矩形,fill为球拍的颜色
 -         self.id=canvas.create_rectangle(0,0,150,10,fill=color)#画一个矩形并记录下它的id
 -         self.canvas.move(self.id,150,380)# 将球拍移动至初始位置
 -         self.canvas_width=self.canvas.winfo_width()#球拍的画布宽度铺满
 -         self.x=0# 设置对象变量x,初始值为0.也就是球拍先不移动
 -         #在Paddle的初始化函数里面绑定两个键盘事件:
 -         self.canvas.bind_all("<KeyPress-Left>",self.turn_left)
 -         self.canvas.bind_all("<KeyPress-Right>",self.turn_right)
 - 
 -     #创建实例方法,是指在类中定义的函数。
 -     def turn_left(self,evt): #左移,evt是向系统注册的事件
 -         self.x=-4#左移速度为4
 - 
 -     def turn_right(self,evt):#右移
 -         self.x=4#右移速度为4
 - 
 -     def draw(self):
 -         self.canvas.move(self.id,self.x,0)#纵坐标固定,横坐标可移动
 -         paddle_pos=self.canvas.coords(self.id)# 获取球拍的位置坐标
 -         if paddle_pos[0]<=0:# 如果球拍左上角x坐标小于等于0,则停止移动
 -             self.x=0
 -         if paddle_pos[2]>=500:# 如果球拍右下角x坐标大于等于500,则停止移动
 -             self.x=0
 - 
 - class Ball():#创建球类
 -     '''创建Ball类,初始化对象,即创建对象设置属性,一个canvas也就是画图用来画一个球,一个是color,表示球的颜色
 -     init函数是在对象被创建的同时就设置属性的一种方法,Python会在创建新对象时自动调用这个函数。'''
 -     def __init__(self,canvas,paddle,color):#类的初始化的函数
 -         self.canvas=canvas#初始化canvas
 -         self.paddle=paddle#初始化paddle
 -         '''保存tkinter画小球返回的id,为后期移动屏幕上的小球做准备,参数分别表示为:(10,10)
 -         表示左上角x,y坐标,(25,25)表示右下角x,y坐标,即创建一个直径为15的圆,fill为小球的填充色'''
 -         self.id=canvas.create_oval(10,10,25,25,fill=color)#画圆并记录下它的id
 -         self.canvas.move(self.id,245,100)# 将小球移动到初始位置,初始位置可通过传参进行更改,有默认值
 -         starts=[-3,-2,-1,1,2,3]# 给一串x分量的起始值(x和y代表横坐标和纵坐标的分量)
 -         random.shuffle(starts)# shuffle()方法将序列的所有元素随机排序
 -         self.x=starts[0]# 随机混排序,赋值给对象变量x,让它起始的时候获得随机分量值,横向速度不同,引起球每次起始角度都不同
 -         self.y=-7 #向上移动 
 -         self.hit_bottom = False# 小球是否碰触到画布底部,初始值为False,即没有碰到
 - 
 -     def draw(self):#让球出现在主界面上
 -         self.canvas.move(self.id, self.x, self.y)# 让小球可以水平和垂直运动
 -         pos = self.canvas.coords(self.id)# coords函数通过id返回画布球的坐标列表
 -         # 判断小球是否撞到画布顶部或者底部,保证小球反弹回去,不消失
 -         if pos[3]>= 400:# 如果小球的右下角y坐标大于画布宽度,则表示小球碰到了画布底部,游戏结束
 -             self.hit_bottom=True
 -         if pos[2] >= 500:#如果小球的右下角x坐标 大于等于画布宽度,则向左移速为5
 -             self.x=-5
 -         if pos[0]<=0:#如果小球的左上角x坐标 小于等于0,则向右移速为5
 -             self.x=5
 -         if pos[1]<=0:#如果小球的左上角y坐标小于0,则向下移速为5
 -             self.y=5
 - 
 -         if self.hit_paddle(pos)==True:# 判断 球 是否碰到了 球拍,如果碰到了则使小球回弹
 -             self.y=-5#向上移速为5
 - 
 -     #该函数用于判断 球 是否碰到了 球拍,如果碰到了则使小球回弹,否则游戏结束
 -     def hit_paddle(self,pos):
 -         paddle_pos=self.canvas.coords(self.paddle.id)# 获取球拍在画布的坐标
 -         # 如果小球的右下角x坐标 大于等于 球拍左上角x坐标,且小球左上角x坐标 小于等于 球拍右下角x坐标
 -         if pos[2]>=paddle_pos[0] and pos[0]<=paddle_pos[2]:
 -             # 如果小球右下角y坐标 大于等于 球拍左上角y坐标,且小球右下角y坐标 小于等于 球拍右下角y坐标
 -             if pos[3]>=paddle_pos[1] and pos[3]<=paddle_pos[3]:
 -                 return True#返回值为真
 -         else:
 -             return False#返回值为假
 - 
 - paddle = Paddle(canvas, 'blue')#创建球拍的实例
 - ball = Ball(canvas, paddle, 'red')#创建球的实例
 - while True:
 -     if ball.hit_bottom == False:# 如果小球没有碰到底部
 -         ball.draw()#调用球的draw方法
 -         paddle.draw()#调用球拍的draw方法
 -     else:
 -         canvas.itemconfig(over, state='normal')#修改组件属性
 -     window.update()#更新屏幕
 -     time.sleep(0.01)#程序推迟执行0.01秒
 
  复制代码
  
3、程序运行STEP1:点击运行,弹出一个标题为“Game”的浅绿色窗口。  
   STEP2:观察窗口,一个红色的小球向上弹出,遇到界面上边缘后下落,而一个蓝色的长方形球拍停在窗口的下方。  
   STEP3:通过键盘上的左右两个方向键移动球拍,接住下落的小球后,小球反弹,小球撞击窗口左右两边缘后再次反弹。  
   STEP4:接球失败后,弹出“Game Over”文本。 
  
  
  五、巩固提高 
项目回顾本节课我们利用tkinter库中的Tk()函数创建了窗口对象,并结合画布组件,创建了小球和球拍对象,之后设定规则,实现了完整的弹球小游戏。  
 知识小结 
项目拓展        让我们尝试改变小球移动的速度来增加游戏难度吧!   
 |