在正式编写程序代码之前,我们首先要创建一个项目文件及python程序文件。
STEP1:创建与保存项目文件
启动Mind+,另存项目并命名为“弹球小游戏积分版”。
STEP2:创建与保存python文件
创建一个python程序文件“任务一.py”,双击打开。
STEP3:编写程序
- 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()#安置画布
-
- #初始界面,画布上绘制文字
- startsigal=canvas.create_text(430,10,text='DOWN:START',font=('Times',10),state='normal')
- endsigal=canvas.create_text(430,30,text='UP:END',font=('Times',10),state='normal')
- 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')
- start=canvas.create_text(430,110,text='GAME START',font=('Times',10),state='normal')
- score=canvas.create_text(430,90,text='SCORE:',font=('Times',10),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.started=False#球拍是否开始移动,True表示开始运行
- self.x=0#设置对象变量x,初始值为0.也就是球拍先不移动
- self.canvas_width=self.canvas.winfo_width()#球拍的画布宽度铺满
- #在Paddle的初始化函数里面绑定四个键盘事件:
- self.canvas.bind_all("<KeyPress-Left>",self.turn_left)
- self.canvas.bind_all("<KeyPress-Right>",self.turn_right)
- self.canvas.bind_all("<KeyPress-Down>", self.game_start)#向下键开始
- self.canvas.bind_all("<KeyPress-Up>", self.game_stop)#向上键停止
-
- #创建实例方法,是指在类中定义的函数。
- def turn_left(self,evt):#左移,evt是向系统注册的事件
- self.x=-4#左移速度为4
- def turn_right(self,evt):#右移
- self.x=4#右移速度为4
- def game_start(self,evt):#开始
- self.started=True
- def game_stop(self,evt):#停止
- self.started = False
-
- def draw(self):#创建draw()方法
- 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):#创建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)#将小球移动到初始位置,初始位置可通过传参进行更改,有默认值
- 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#向上移动三像素
- score.addscore()#调用计分函数
-
- #该函数用于判断 球 是否碰到了 球拍,如果碰到了则使小球回弹,否则游戏结束
- 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#返回值为假
-
- #得分计算
- class Score:#创建得分类
-
- def __init__(self,canvas,color):
- self.score=0#初始化得分为0
- self.canvas=canvas# 把参数canvas赋值给对象变量canvas
- canvas.itemconfig(score, state='normal')#修改组件属性,将得分展示在文本控件中
- self.id=canvas.create_text(470,90,text=self.score,fill=color)#创建文本控件,用户保存得分
-
- def addscore(self):#计算得分
- self.score+=1#自增一分
- self.canvas.itemconfig(self.id,text=self.score)
-
- paddle = Paddle(canvas, 'blue')#创建木板的实例
- ball = Ball(canvas, paddle, 'red')#创建球的实例
- score=Score(canvas,'black')#创建得分实例
- while True:
-
- if paddle.started==True :
- if ball.hit_bottom==False:#游戏开始且小球未触底
- ball.draw()#调用球的draw函数
- paddle.draw()#调用木板的draw函数
- else:
- canvas.itemconfig(start, state='hidden')#修改组件属性
- canvas.itemconfig(over, state='normal')#修改组件属性
-
- window.update()#更新屏幕
- time.sleep(0.01)#程序推迟执行0.01秒
复制代码
3、程序运行运行程序,我们看到:弹出了一个标题为“Game”的绿色背景的游戏界面,界面的右上方有四个按键操作方式的文字提示,以及得分显示,每接住一次小球,得分都会自动加一。
知识积累 |
赋值运算符+= 功能说明 “+=”符号表示加赋值,把右边的值进行某些运算后再赋值给左边的变量。 使用方法 举例说明 程序中, self.score+=1#自增一分 表示得分在原来的基础上加1后再将结果值赋给自己。
|
常见的赋值运算符 功能说明 赋值运算符主要用来为变量等赋值。使用时,可以直接把基本赋值运算符“=”右边的值赋给左边的变量,也可以进行某些运算后再赋值给左边的变量。 使用方法 |
乐一乐 至此,弹球小游戏积分第一版我们就完成啦,赶紧来试一试吧,看看你最高能得多少分呢? |
任务2:变化移速程序设计这个程序中,我们将为游戏添加不同的难度,这里,我们依旧将分三步创建这个程序。首先是分析任务,之后进行程序的编写,最后运行程序并观察效果。
1、任务分析在任务一的程序中,我们已经成功实现了计分功能,接下来,为了增加游戏的趣味度,我们将为游戏增加一定的难度。
这里,我们通过变化小球的移动速度来实现,整体上,编程的方式不变,只需做几点调整。
首先,我们需要在一开始定义一个全局变量speed,之后,在小球的draw方法内,我们将原来固定的移速,更换成speed,并且,对于speed这个变量,我们设置其在不同得分段下不同的数值,并且得分越高,移速越快。这里,我们通过多分支结构来实现,具体流程如下,
同时,我们也为游戏设置得分上限,当达到最高得分时,则判定获胜。这里,我们在一开始的画布界面上设置获胜信息并隐藏,之后通过在得分类的addscore方法内添加条件判断语句来实现。
2、程序编写STEP1:创建与保存python文件
新建一个python程序文件“任务二.py”,双击打开。
STEP2:编写程序
- import tkinter#导入tkinter库
- #创建一个界面和配置界面的一些基本属性
- import tkinter#引入GUI工具包turtle库
- import random#引入随机函数
- import time#引入时间库
-
- global speed#创建全局变量speed
-
- #创建一个界面和配置界面的一些基本属性
- 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()#安置画布
-
- #初始界面,画布上绘制文字
- startsigal=canvas.create_text(430,10,text='DOWN:START',font=('Times',10),state='normal')
- endsigal=canvas.create_text(430,30,text='UP:END',font=('Times',10),state='normal')
- 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')
- start=canvas.create_text(430,110,text='GAME START',font=('Times',10),state='normal')
- score=canvas.create_text(430,90,text='SCORE:',font=('Times',10),state='hidden')
- victory=canvas.create_text(250,200,text='Victory',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.started=False#球拍是否开始移动,True表示开始运行
- self.x=0# 设置对象变量x,初始值为0.也就是球拍先不移动
- self.canvas_width=self.canvas.winfo_width()#球拍的画布宽度铺满
- #在Paddle的初始化函数里面绑定两个键盘事件:
- self.canvas.bind_all("<KeyPress-Left>",self.turn_left)
- self.canvas.bind_all("<KeyPress-Right>",self.turn_right)
- self.canvas.bind_all("<KeyPress-Down>", self.game_start)#向下键开始
- self.canvas.bind_all("<KeyPress-Up>", self.game_stop)#向上键停止
-
- #创建实例方法,是指在类中定义的函数。
- def turn_left(self,evt):#左移,evt是向系统注册的事件
- self.x=-4#左移速度为4
- def turn_right(self,evt):#右移
- self.x=4#右移速度为4
- def game_start(self,evt):#开始
- self.started=True
- def game_stop(self,evt):#停止
- self.started = False
-
- def draw(self):#创建draw()方法
- 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):#创建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)# 将小球移动到初始位置,初始位置可通过传参进行更改,有默认值
- starts=[-3,-2,-1,1,2,3]# 给一串x分量的起始值(x和y代表横坐标和纵坐标的分量)
- random.shuffle(starts)# shuffle()方法将序列的所有元素随机排序
- self.x=starts[0]# 随机混排序,赋值给对象变量x,让它起始的时候获得随机分量值,横向速度不同,引起球每次起始角度都不同
- self.y=-3 #向上移动
- 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 score.score >= 0and score.score<=2:#得分在0-2分内
- speed = 3#设置移速为3
- elif score.score >= 3and score.score<=5:#得分在3-5分内
- speed = 4
- elif score.score >= 6and score.score<=8:#得分在6-8分内
- speed = 5
- elif score.score >= 9and score.score<=15:#得分在9-15分内
- speed = 6
- else :#其他情况
- speed = 7
-
- # 判断小球是否撞到画布顶部或者底部,保证小球反弹回去,不消失
- if pos[3]>= 400:# 如果小球的右下角y坐标大于画布宽度,则表示小球碰到了画布底部,游戏结束
- self.hit_bottom=True
- if pos[2] >= 500:#如果小球的右下角x坐标 大于等于画布宽度,则向左移速为
- self.x=-speed
- if pos[0]<=0:#如果小球的左上角x坐标 小于等于0,则向右移速为
- self.x=speed
- if pos[1]<=0:#如果小球的左上角y坐标小于0,则向下移速为
- self.y=speed
-
- if self.hit_paddle(pos)==True:# 判断 球 是否碰到了 球拍,如果碰到了则使小球回弹
- self.y=-speed #向上移动三像素
- score.addscore()#调用计分函数
-
- #该函数用于判断 球 是否碰到了 球拍,如果碰到了则使小球回弹,否则游戏结束
- 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#返回值为假
-
- #得分计算
- class Score:#创建得分类
-
- def __init__(self,canvas,color):
- self.score=0#初始化得分为0
- self.canvas=canvas# 把参数canvas赋值给对象变量canvas
- canvas.itemconfig(score, state='normal')# 修改组件属性,将得分展示在文本控件中
- self.id=canvas.create_text(470,90,text=self.score,fill=color)#创建文本控件,用户保存得分
-
- def addscore(self):#计算得分
- self.score+=1#自增一分
- self.canvas.itemconfig(self.id,text=self.score)
- if self.score == 18:
- canvas.itemconfig(victory, state='normal')#修改组件属性
- canvas.itemconfig(over, state='hidden')#修改组件属性
- paddle.started = False
-
- paddle = Paddle(canvas, 'blue')#创建木板的实例
- ball = Ball(canvas, paddle, 'red')#创建球的实例
- score=Score(canvas,'black')#创建得分实例
- while True:
-
- if paddle.started==True :
- if ball.hit_bottom==False:#游戏开始且小球未触底
- ball.draw()#调用球的draw函数
- paddle.draw()#调用木板的draw函数
- else:
- canvas.itemconfig(start, state='hidden')#修改组件属性
- canvas.itemconfig(over, state='normal')#修改组件属性
- window.update()#强制更新屏幕
- time.sleep(0.01)#程序推迟执行0.01秒
复制代码
3、程序运行运行程序,我们看到:弹出了一个标题为“Game”的绿色背景的游戏界面,界面的右上方有四个按键操作方式的文字提示,以及得分显示,每接住一次小球,得分都会自动加一。而随着得分的增高,小球移动地越快。
乐一乐 至此,弹球小游戏积分第二版我们就完成啦,你需要多少次才能获胜呢? 之后,尝试改变移速进一步增加难度再试试吧! |
五、巩固提高
项目回顾本节课,我们在上节课弹球小游戏的基础上进行了优化,首先给游戏添加了计分功能并实现通过键盘按键控制游戏的启停。之后为了丰富游戏的趣味度,我们通过调整小球在不同得分段下的移动速度继而设置游戏的不同难度。
知识小结
项目拓展 想一想,除了加快小球的移动速度,我们还能如何控制游戏的难度呢?!(可参考方向:缩短球拍的长度,改变移速,球拍位置等)