根据前面慢屏幕乱跑的小球,改编一个弹球游戏,下面加一个球拍,当球碰到拍子的时候弹回去
版本一
目前这个实现的功能是:加入了一拍子,可以用键盘来左右控制移动
#########################
#之前做的画面没有互动,这次加入一个球拍,使之能把下落的球给挡回去,目前功能加入了一拍子,可以用键盘来左右控制移动
######################
from tkinter import *
import random
import time
#
#创建一个类,这个类含有两个参数,一个是画布,一个是球的颜色
#
class Ball:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#来回反弹
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函数来获取画布当前的高度,赋值给对象变量
self.canvas_height = self.canvas.winfo_height()
#获取X轴坐标
self.canvas_width = self.canvas.winfo_width()
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#获取某个对象在画布的坐标,返回一个数组(两个坐标,左上角的坐标和右下角的两个坐标)
pos = self.canvas.coords(self.id)
#打印获取的坐标
print(pos)
#如果最上面的纵轴坐标在顶上,则往下移动一个像素
if pos[1] <= 0:
self.y = 1
#如果最下面的纵轴坐标在底上,则向上移动
if pos[3] > self.canvas_height:
self.y = -1
#宽度控制#
#如果在左边框了,那么向右边移动3像素
if pos[0] <= 0:
self.x = 3
#如果到右边框了,左移动3像素
if pos[2] > self.canvas_width:
self.x = -3
#
#创建一个球拍类,这个类含有两个参数,一个是画布,一个是球的颜色
#
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
#这个函数绑定一个事件,来实现小球用键盘来控制左右移动,当移动到边界的时候要停止移动
def draw(self,event):
pos = self.canvas.coords(self.id)
if event.keysym == 'Left':
if pos[0] <= 0:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,-100,0)
if event.keysym == 'Right':
if pos[2] >= self.canvas_width:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,100,0)
#创建画布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 画布之外没有边框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
#创建对象
ball = Ball(canvas,'red')
paddle = Paddle(canvas,'blue')
#一直保持循环
while 1:
ball.draw()
#给球拍绑定事件
canvas.bind_all('<KeyPress-Left>',paddle.draw)
canvas.bind_all('<KeyPress-Right>',paddle.draw)
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.01)
版本2
这个可用用键盘来回移动球拍,并且如果球碰到球拍会给它弹回去
#########################
#之前做的画面没有互动,这次加入一个球拍,使之能把下落的球给挡回去
######################
from tkinter import *
import random
import time
#
#创建一个类,这个类含有两个参数,一个是画布,一个是球的颜色
#
class Ball:
#这个地方要获取paddle的数据,所以要把paddle对象作为一个参数传递进来
def __init__(self,canvas,paddle,color):
self.canvas = canvas
self.paddle = paddle
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#来回反弹
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函数来获取画布当前的高度,赋值给对象变量
self.canvas_height = self.canvas.winfo_height()
#获取X轴坐标
self.canvas_width = self.canvas.winfo_width()
#fun:判断是否击中球拍的函数,击中返回True,不然返回false
#函数的擦数要获取球拍的位置,然后和小球的位置来判断
def hit_paddle(self,pos):
paddle_pos = canvas.coords(self.paddle.id)
#这个地方来讲一下判断规则,现在我们获取了两个球和拍子两个对象在画布中的坐标,通过对坐标来判断是否撞拍
#先判断横坐标:如果小球的最左边pos[0]的值大于等于拍子最左边的值,且球最右边的坐标的值pos[2]小于拍子最右边的值,那么横向是命中的
if pos[0] >= paddle_pos[0] and pos[2] <= paddle_pos[2]:
#纵向判断:小球的最下边的值位于球拍的pos[3]上底和下底之间,则纵向命中
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
else:
return False
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#获取某个对象在画布的坐标,返回一个数组(两个坐标,左上角的坐标和右下角的两个坐标)
pos = self.canvas.coords(self.id)
##纵轴控制##
#如果最上面的纵轴坐标在顶上,则往下移动一个像素
if pos[1] <= 0:
self.y = 1
#如果最下面的纵轴坐标在底上,则向上移动
if pos[3] > self.canvas_height:
self.y = -1
#这儿加入球拍的位置,如果到了球拍的底部也要弹回去,通过加入一个函数来判断,在draw之前
if self.hit_paddle(pos) == True:
self.y = -1
##宽度控制##
#如果在左边框了,那么向右边移动3像素
if pos[0] <= 0:
self.x = 3
#如果到右边框了,左移动3像素
if pos[2] > self.canvas_width:
self.x = -3
#
#创建一个球拍类,这个类含有两个参数,一个是画布,一个是球的颜色
#
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
#这个函数绑定一个事件,来实现小球用键盘来控制左右移动,当移动到边界的时候要停止移动
def draw(self,event):
pos = self.canvas.coords(self.id)
if event.keysym == 'Left':
if pos[0] <= 0:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,-100,0)
if event.keysym == 'Right':
if pos[2] >= self.canvas_width:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,100,0)
#创建画布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 画布之外没有边框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
#创建对象
paddle = Paddle(canvas,'blue')
ball = Ball(canvas,paddle,'red')
#一直保持循环
while 1:
ball.draw()
#给球拍绑定事件
canvas.bind_all('<KeyPress-Left>',paddle.draw)
canvas.bind_all('<KeyPress-Right>',paddle.draw)
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.01)
继续进行优化
加入计分功能和如果错过三次则自动停止功能
#########################
#之前做的画面没有互动,这次加入一个球拍,使之能把下落的球给挡回去
######################
from tkinter import *
import random
import time
#创建画布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 画布之外没有边框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
#
#创建一个类,这个类含有两个参数,一个是画布,一个是球的颜色
#
class Ball:
#这个地方要获取paddle的数据,所以要把paddle对象作为一个参数传递进来
def __init__(self,canvas,paddle,color):
self.canvas = canvas
self.paddle = paddle
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#来回反弹
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函数来获取画布当前的高度,赋值给对象变量
self.canvas_height = self.canvas.winfo_height()
#获取X轴坐标
self.canvas_width = self.canvas.winfo_width()
#刚开始没有接触到底部
self.hit_bottom_count = 0
#fun:判断是否击中球拍的函数,击中返回True,不然返回false
#函数的擦数要获取球拍的位置,然后和小球的位置来判断
def hit_paddle(self,pos):
paddle_pos = canvas.coords(self.paddle.id)
#这个地方来讲一下判断规则,现在我们获取了两个球和拍子两个对象在画布中的坐标,通过对坐标来判断是否撞拍
#先判断横坐标:如果小球的最左边pos[0]的值大于等于拍子最左边的值,且球最右边的坐标的值pos[2]小于拍子最右边的值,那么横向是命中的
if pos[0] >= paddle_pos[0] and pos[2] <= paddle_pos[2]:
#纵向判断:小球的最下边的值位于球拍的pos[3]上底和下底之间,则纵向命中
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
else:
return False
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#获取某个对象在画布的坐标,返回一个数组(两个坐标,左上角的坐标和右下角的两个坐标)
pos = self.canvas.coords(self.id)
##纵轴控制##
#如果最上面的纵轴坐标在顶上,则往下移动一个像素
if pos[1] <= 0:
self.y = 1
#如果最下面的纵轴坐标在底上,则向上移动
#if pos[3] > self.canvas_height:
#self.y = -1
if pos[3] >= self.canvas_height:
self.hit_bottom_count = self.hit_bottom_count + 1
self.y = -1
#这儿加入球拍的位置,如果到了球拍的底部也要弹回去,通过加入一个函数来判断,在draw之前
if self.hit_paddle(pos) == True:
self.y = -1
##宽度控制##
#如果在左边框了,那么向右边移动3像素
if pos[0] <= 0:
self.x = 3
#如果到右边框了,左移动3像素
if pos[2] > self.canvas_width:
self.x = -3
#
#创建一个球拍类,这个类含有两个参数,一个是画布,一个是球的颜色
#
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
#这个函数绑定一个事件,来实现小球用键盘来控制左右移动,当移动到边界的时候要停止移动
def draw(self,event):
pos = self.canvas.coords(self.id)
if event.keysym == 'Left':
if pos[0] <= 0:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,-100,0)
if event.keysym == 'Right':
if pos[2] >= self.canvas_width:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,100,0)
print(event.keysym)
def main():
#创建对象
paddle = Paddle(canvas,'blue')
ball = Ball(canvas,paddle,'red')
#一直保持循环
while 1:
#用一个变量来判断是否曾接触过底部,默认没接触过
if True == True:
if ball.hit_bottom_count <= 1 :
#点击球拍开始
is_begin = True
ball.draw()
#给球拍绑定事件
canvas.bind_all('<KeyPress-Left>',paddle.draw)
canvas.bind_all('<KeyPress-Right>',paddle.draw)
else:
#游戏结束后,闪烁游戏结束提示
for i in range(1,20):
time.sleep(0.5)
endmsg=canvas.create_text(250,200,text = 'Game Over!',font =('Times',50),fill = 'red')
tk.update()
time.sleep(0.5)
canvas.itemconfig(endmsg,state = 'hidden')
tk.update()
tk.update_idletasks()
break
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.005)
if __name__ == "__main__":
main()
继续进行功能扩展
加入如下功能:
- 点击球拍开始游戏
- 计分功能
- 加速功能
- 结束提醒功能
'''
#########################
#之前做的画面没有互动,这次加入一个球拍,使之能把下落的球给挡回去,同时较少main处的代码,尽量都放到类中来实现,以符合高内聚低耦合原则
######################
'''
from tkinter import *
import random
import time
#创建画布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 画布之外没有边框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
'''
#
#创建一个类,这个类含有如下参数:画布,被击中的球拍paddle,球的颜色,击中次数score
#
'''
class Ball:
#这个地方要获取paddle的数据,所以要把paddle对象作为一个参数传递进来
def __init__(self,canvas,paddle,color,score):
self.canvas = canvas
self.paddle = paddle
self.score = score
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#来回反弹
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函数来获取画布当前的高度,赋值给对象变量
self.canvas_height = self.canvas.winfo_height()
#获取X轴坐标
self.canvas_width = self.canvas.winfo_width()
#刚开始没有接触到底部
self.hit_bottom_count = 0
#fun:判断是否击中球拍的函数,击中返回True,不然返回false
#函数的擦数要获取球拍的位置,然后和小球的位置来判断
def hit_paddle(self,pos):
paddle_pos = canvas.coords(self.paddle.id)
#这个地方来讲一下判断规则,现在我们获取了两个球和拍子两个对象在画布中的坐标,通过对坐标来判断是否撞拍
#先判断横坐标:如果小球的最左边pos[0]的值大于等于拍子最左边的值,且球最右边的坐标的值pos[2]小于拍子最右边的值,那么横向是命中的
if pos[0] >= paddle_pos[0] and pos[2] <= paddle_pos[2]:
#纵向判断:小球的最下边的值位于球拍的pos[3]上底和下底之间,则纵向命中
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
#此处调用的score类的getScore函数得分,把计算得分的功能让得分类来实现,通过对象引用获取某个对象的得分,就相当于球这个对象有了分的属性
self.score.getScore()
return True
else:
return False
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#获取某个对象在画布的坐标,返回一个数组(两个坐标,左上角的坐标和右下角的两个坐标)
pos = self.canvas.coords(self.id)
##纵轴控制##
#如果最上面的纵轴坐标在顶上,则往下移动一个像素
if pos[1] <= 0:
self.y = 1
#如果最下面的纵轴坐标在底上,则向上移动
#if pos[3] > self.canvas_height:
#self.y = -1
if pos[3] >= self.canvas_height:
self.hit_bottom_count = self.hit_bottom_count + 1
self.y = -1
#这儿加入球拍的位置,如果到了球拍的底部也要弹回去,通过加入一个函数来判断,在draw之前
if self.hit_paddle(pos) == True:
self.y = -1
##宽度控制##
#如果在左边框了,那么向右边移动3像素
if pos[0] <= 0:
self.x = 3
#如果到右边框了,左移动3像素
if pos[2] > self.canvas_width:
self.x = -3
'''
#
#创建一个球拍类,这个类含有两个参数,一个是画布,一个是球的颜色
#
'''
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.is_start = False
self.canvas_width = self.canvas.winfo_width()
self.canvas.bind_all('<KeyPress-Left>',self.turn_left)
self.canvas.bind_all('<KeyPress-Right>',self.turn_right)
self.canvas.bind_all('<Button-1>',self.start_game)
#这个函数绑定一个事件,来实现小球用键盘来控制左右移动,当移动到边界的时候要停止移动
#应该把检测是否过线的判断放在这个地方,因为只有按键的时候才触发判断,
def draw(self):
self.canvas.move(self.id,self.x,0)
pos = self.canvas.coords(self.id)
if pos[0] <= 0 :
self.x = 0
elif pos[2] >= self.canvas_width:
self.x = 0
def turn_left(self,evt):
self.x = -3
return self.x
def turn_right(self,evt):
self.x = 3
return self.x
def start_game(self,evt):
self.is_start = True
return self.is_start
'''
#
##得分类,有2个属性,画布和颜色;一个方法,得分方法
#
'''
class Score:
def __init__(self,canvas,color):
self.score = 0
self.canvas = canvas
self.id = canvas.create_text(450,10,fill = color,text= self.score,)
def getScore(self):
self.score += 1
#改变得分
self.canvas.itemconfig(self.id,text = self.score)
def main():
#创建对象
score = Score(canvas,'green')
paddle = Paddle(canvas,'blue')
ball = Ball(canvas,paddle,'red',score)
endmsg=canvas.create_text(250,200,text = 'Game Over!',font =('Times',50),fill = 'red',state = 'hidden')
#ball2 = Ball(canvas,paddle,'green')
#一直保持循环
while 1:
#用一个变量来判断是否曾接触过底部,默认没接触过
if ball.hit_bottom_count <= 4 and paddle.is_start == True:
#点击球拍开始
#is_begin = True
ball.draw()
#ball2.draw()
paddle.draw()
if ball.hit_bottom_count > 4:
canvas.itemconfig(endmsg,state='normal')
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.005)
if __name__ == "__main__":
main()