python游戏初探:拍子打小球

根据前面慢屏幕乱跑的小球,改编一个弹球游戏,下面加一个球拍,当球碰到拍子的时候弹回去

版本一

目前这个实现的功能是:加入了一拍子,可以用键盘来左右控制移动


#########################
#之前做的画面没有互动,这次加入一个球拍,使之能把下落的球给挡回去,目前功能加入了一拍子,可以用键盘来左右控制移动
######################
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()

继续进行功能扩展

加入如下功能:

  1. 点击球拍开始游戏
  2. 计分功能
  3. 加速功能
  4. 结束提醒功能
'''
#########################
#之前做的画面没有互动,这次加入一个球拍,使之能把下落的球给挡回去,同时较少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()

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贤时间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值