弹球实例2.0

前一阵子,我带着大家做了一个简单的弹球实例,现在我们来对弹球游戏进行优化加强,让游戏的功能变得更好玩吧

弹球游戏2.0展示效果

实现流程

1.主循环,游戏画布

2.创建ball类,增加几个动作(让小球移动、让小球来回反弹,改变小球的起始方向)

3.创建Paddle类,加上球拍,使球拍左右移动(循环移动)

4.创建Score类增加输赢因素(加入3次游戏机会)

导入模块、包

import tkinter as tkinter
import tkinter.messagebox as mb
import random
import time

导入tkinterrandom、time

tkinter实现画布弹窗,random实现随机出现,time负责等待sleep()

主循环

def main():
    tk = tkinter.Tk()

    def callback():
        if mb.askokcancel("退出", "你想退出吗?"):
            tk.destroy()

    tk.protocol("WM_DELETE_WINDOW", callback)
    canvas_width = 500
    canvas_hight = 500
    tk.title("弹球游戏")
    tk.resizable(0, 0)
    tk.wm_attributes("-topmost", 1)
    canvas = tkinter.Canvas(tk, width=canvas_width, height=canvas_hight, bd=0, highlightthickness=0, bg='#00ffff')
    canvas.pack()
    tk.update()
    score = Score(canvas, 'red')
    paddle = Paddle(canvas, "red")
    ball = Ball(canvas, paddle, score, "grey")

    game_over_text = canvas.create_text(canvas_width / 2, canvas_hight / 2, text='游戏结束', state='hidden', fill='red',
                                        font=(None, 18, "bold"))
    introduce = '欢迎来到弹球游戏\n  按任意键开始\n'
    game_start_text = canvas.create_text(canvas_width / 2, canvas_hight / 2, text=introduce, state='normal',
                                         fill='magenta', font=(None, 18, "bold"))
    while True:
        if (ball.hit_bottom == False) and ball.paddle.started:
            canvas.itemconfig(game_start_text, state='hidden')
            ball.draw()
            paddle.draw()
        if ball.hit_bottom == True:
            time.sleep(0.1)
            canvas.itemconfig(game_over_text, state='normal')
        tk.update_idletasks()
        tk.update()
        time.sleep(0.01)


if __name__ == '__main__':
    main()

tkinter.Tk()类创建一个tk对象,它就是一个基本窗口,可以在其上增加其他东西

该函数用于,当点击窗口关闭按钮时,展示一个消息提示框,询问是否要关闭,点击是,则退出窗口

protocol:主要用于窗体关闭监听,通过这个协议可以在窗体关闭前提示是否真的要关闭,这样可以防止用户误触导致数据的丢失

我们需要增加一个动画循环 “主循环”是程序的中心部分,一般来讲它控制程序中大部分的行为。

我们的主循环目前只是让tkinter 重画屏幕。这个循环一直运行下去,不停地让tkinter重画屏幕,然后休息百分之一秒。

如果小球没有碰到了底部,且游戏尚未开始

如果小球碰到了底部,则游戏结束

创建ball类

class Ball():
    def __init__(self, canvas, paddle, score, color, init_x=100, init_y=100):
        self.canvas = canvas
        self.paddle = paddle
        self.score = score
        self.color = color
        self.id = canvas.create_oval(10, 10, 30, 30, fill=self.color)
        self.canvas.move(self.id, init_x, init_y)
        starts = [-3, -2, -1, 1, 2, 3]
        random.shuffle(starts)
        self.x = starts[0]
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.hit_bottom = False

    def draw(self):
        self.canvas.move(self.id, self.x, self.y)
        position = self.canvas.coords(self.id)
        if position[1] <= 0:
            self.y = 3
        if position[3] >= self.canvas_height:
            self.hit_bottom = True
        if self.hit_paddle(position) == True:
            self.y = -3
        if position[0] <= 0:
            self.x = 3
        if position[2] >= self.canvas_width:
            self.x = -3
#该函数用于让小球水平和垂直运动,在运动的过程中,判断是否得分、游戏是否结束


    def hit_paddle(self, position):
        paddle_position = self.canvas.coords(self.paddle.id)
        print('paddle_position:', paddle_position[0], paddle_position[1], paddle_position[2], paddle_position[3])
        if position[2] >= paddle_position[0] and position[0] <= paddle_position[2]:
            if position[3] >= paddle_position[1] and position[3] <= paddle_position[3]:
                self.x += self.paddle.x
                colors = ['red', 'green']
                # shuffle() 方法将序列的所有元素随机排序,以便随机获得小球颜色
                random.shuffle(colors)
                self.color = colors[0]
                self.canvas.itemconfig(self.id, fill=colors[0])
                self.score.hit(ball_color=self.color)
                self.canvas.itemconfig(self.paddle.id, fill=self.color)
                self.adjust_paddle(paddle_position)
                return True
#该函数用于判断球是否碰到了球拍,如果碰到了则使小球回弹,否则游戏结束

shuffle() 方法将序列的所有元素随机排序,以便随机获得小球颜色

        return False

    def adjust_paddle(self, paddle_position):
        paddle_grow_length = 30
        paddle_width = paddle_position[2] - paddle_position[0]
        if self.color == 'red':
            if paddle_width > 30:
                if paddle_position[2] >= self.canvas_width:
                    paddle_position[2] = paddle_position[2] - paddle_grow_length
                else:
                    paddle_position[0] = paddle_position[0] + paddle_grow_length

        elif self.color == 'green':
            if paddle_width < 300:
                if paddle_position[2] >= self.canvas_width:
                    paddle_position[0] = paddle_position[0] - paddle_grow_length
                else:
                    paddle_position[2] = paddle_position[2] + paddle_grow_length

创建Ball类,初始化对象,即创建对象设置属性

init函数是在对象被创建的同时就设置属性的一种方法,Python会在创建新对象时自动调用这个函数

Ball类初始化属性

  canvas:画布

  paddle:球拍

  score:得分

  color:小球的颜色

  init_x:小球球的初始横坐标

  init_y:小球球的初始纵坐标

shuffle() 方法将序列的所有元素随机排序

winfo_height()函数来获取画布当前的高度,赋值给对象变量

小球是否碰触到画布底部,初始值为False,即没有碰到

创建Paddle类

class Paddle:
    def __init__(self, canvas, color):
        self.canvas = canvas
        self.canvas_width = self.canvas.winfo_width()
        self.canvas_height = self.canvas.winfo_height()
        self.id = canvas.create_rectangle(0, 0, 180, 15, fill=color)
        self.canvas.move(self.id, 200, self.canvas_height * 0.75)
        self.x = 0
        self.started = False
        self.continue_game = False
        self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
        self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        self.canvas.bind_all('<KeyPress-Enter>', self.continue_game)
        self.canvas.bind_all('<Button-1>', self.start_game)
        self.canvas.bind_all('<space>', self.pause_game)

    def turn_left(self, event):
        position = self.canvas.coords(self.id)
        if position[0] <= 0:
            self.x = 0
        else:
            self.x = -3

    def turn_right(self, event):
        position = self.canvas.coords(self.id)
        if position[2] >= self.canvas_width:
            self.x = 0
        else:
            self.x = 3
#该两个函数函数用于向左(右)移动时
获取球拍的位置坐标
如果球拍的左(右)上角x坐标 小于 0
则再次按向左(右)移动时,移动距离为0
每次向左(右)移动3个像素

    def start_game(self, evt):
        self.started = True

    def pause_game(self, evt):
        if self.started:
            self.started = False
        else:
            self.started = True

    def draw(self):
        self.canvas.move(self.id, self.x, 0)
        position = self.canvas.coords(self.id)
        if position[0] <= 0:
            self.x = 0
        elif position[2] >= self.canvas_width:
            self.x = 0
#该函数用于移动球拍,球拍类可以水平移动
获取球拍的位置坐标,
如果球拍左上角x坐标小于等于0,则停止移动
如果球拍右下角x坐标大于等于0,则停止移动


winfo_width()函数来获取画布当前的宽度,赋值给对象变量

是否继续游戏,默认值为 否

初始化时将事件‘按下左键'和函数向左移动绑定

初始化时将事件‘按下右键'和函数向右移动绑定

初始化时将事件‘按下Enter键'和函数继续游戏绑定

按任意键开始游戏

初始化时将事件‘按下space键'和函数暂停游戏绑定

创建Score类

class Score():
    def __init__(self, canvas, color):
        self.score = 0
        self.canvas = canvas
        self.canvas_width = self.canvas.winfo_width()
        self.canvas_height = self.canvas.winfo_height()
        self.id = canvas.create_text(self.canvas_width - 150, 10, text='score:0', fill=color, font=(None, 18, "bold"))
        self.note = canvas.create_text(self.canvas_width - 70, 10, text='--', fill='red', font=(None, 18, "bold"))

    def hit(self, ball_color='grey'):
        self.score += 1
        self.canvas.itemconfig(self.id, text='得分:{}'.format(self.score))
        if ball_color == 'red':
            self.canvas.itemconfig(self.note, text='{}-'.format('颜色'), fill='red')
        elif ball_color == 'green':
            self.canvas.itemconfig(self.note, text='{}+'.format('颜色'), fill='green')
        else:
            self.canvas.itemconfig(self.note, text='--', fill='grey')

得分类

canvas:画布 

color:得分文本的颜色

winfo_width()函数来获取画布当前的宽度,赋值给对象变量

创建文本控件,用户保存用户保存得分

用户保存游戏的关卡颜色

该函数用于将计算得分并展示,且同时将小球的颜色、关卡颜色同步

代码展示、可copy

import tkinter as tkinter
import tkinter.messagebox as mb
import random
import time


class Ball():
    def __init__(self, canvas, paddle, score, color, init_x=100, init_y=100):
        self.canvas = canvas
        self.paddle = paddle
        self.score = score
        self.color = color
        self.id = canvas.create_oval(10, 10, 30, 30, fill=self.color)
        self.canvas.move(self.id, init_x, init_y)
        starts = [-3, -2, -1, 1, 2, 3]
        random.shuffle(starts)
        self.x = starts[0]
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.hit_bottom = False

    def draw(self):
        self.canvas.move(self.id, self.x, self.y)
        position = self.canvas.coords(self.id)
        if position[1] <= 0:
            self.y = 3
        if position[3] >= self.canvas_height:
            self.hit_bottom = True
        if self.hit_paddle(position) == True:
            self.y = -3
        if position[0] <= 0:
            self.x = 3
        if position[2] >= self.canvas_width:
            self.x = -3

    def hit_paddle(self, position):
        paddle_position = self.canvas.coords(self.paddle.id)
        print('paddle_position:', paddle_position[0], paddle_position[1], paddle_position[2], paddle_position[3])
        if position[2] >= paddle_position[0] and position[0] <= paddle_position[2]:
            if position[3] >= paddle_position[1] and position[3] <= paddle_position[3]:
                self.x += self.paddle.x
                colors = ['red', 'green']
                # shuffle() 方法将序列的所有元素随机排序,以便随机获得小球颜色
                random.shuffle(colors)
                self.color = colors[0]
                self.canvas.itemconfig(self.id, fill=colors[0])
                self.score.hit(ball_color=self.color)
                self.canvas.itemconfig(self.paddle.id, fill=self.color)
                self.adjust_paddle(paddle_position)
                return True

        return False

    def adjust_paddle(self, paddle_position):
        paddle_grow_length = 30
        paddle_width = paddle_position[2] - paddle_position[0]
        if self.color == 'red':
            if paddle_width > 30:
                if paddle_position[2] >= self.canvas_width:
                    paddle_position[2] = paddle_position[2] - paddle_grow_length
                else:
                    paddle_position[0] = paddle_position[0] + paddle_grow_length

        elif self.color == 'green':
            if paddle_width < 300:
                if paddle_position[2] >= self.canvas_width:
                    paddle_position[0] = paddle_position[0] - paddle_grow_length
                else:
                    paddle_position[2] = paddle_position[2] + paddle_grow_length


class Paddle:
    def __init__(self, canvas, color):
        self.canvas = canvas
        self.canvas_width = self.canvas.winfo_width()
        self.canvas_height = self.canvas.winfo_height()
        self.id = canvas.create_rectangle(0, 0, 180, 15, fill=color)
        self.canvas.move(self.id, 200, self.canvas_height * 0.75)
        self.x = 0
        self.started = False
        self.continue_game = False
        self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
        self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        self.canvas.bind_all('<KeyPress-Enter>', self.continue_game)
        self.canvas.bind_all('<Button-1>', self.start_game)
        self.canvas.bind_all('<space>', self.pause_game)

    def turn_left(self, event):
        position = self.canvas.coords(self.id)
        if position[0] <= 0:
            self.x = 0
        else:
            self.x = -3

    def turn_right(self, event):
        position = self.canvas.coords(self.id)
        if position[2] >= self.canvas_width:
            self.x = 0
        else:
            self.x = 3

    def start_game(self, evt):
        self.started = True

    def pause_game(self, evt):
        if self.started:
            self.started = False
        else:
            self.started = True

    def draw(self):
        self.canvas.move(self.id, self.x, 0)
        position = self.canvas.coords(self.id)
        if position[0] <= 0:
            self.x = 0
        elif position[2] >= self.canvas_width:
            self.x = 0


class Score():
    def __init__(self, canvas, color):
        self.score = 0
        self.canvas = canvas
        self.canvas_width = self.canvas.winfo_width()
        self.canvas_height = self.canvas.winfo_height()
        self.id = canvas.create_text(self.canvas_width - 150, 10, text='score:0', fill=color, font=(None, 18, "bold"))
        self.note = canvas.create_text(self.canvas_width - 70, 10, text='--', fill='red', font=(None, 18, "bold"))

    def hit(self, ball_color='grey'):
        self.score += 1
        self.canvas.itemconfig(self.id, text='得分:{}'.format(self.score))
        if ball_color == 'red':
            self.canvas.itemconfig(self.note, text='{}-'.format('颜色'), fill='red')
        elif ball_color == 'green':
            self.canvas.itemconfig(self.note, text='{}+'.format('颜色'), fill='green')
        else:
            self.canvas.itemconfig(self.note, text='--', fill='grey')


def main():
    tk = tkinter.Tk()

    def callback():
        if mb.askokcancel("退出", "你想退出吗?"):
            tk.destroy()

    tk.protocol("WM_DELETE_WINDOW", callback)
    canvas_width = 500
    canvas_hight = 500
    tk.title("弹球游戏")
    tk.resizable(0, 0)
    tk.wm_attributes("-topmost", 1)
    canvas = tkinter.Canvas(tk, width=canvas_width, height=canvas_hight, bd=0, highlightthickness=0, bg='#00ffff')
    canvas.pack()
    tk.update()
    score = Score(canvas, 'red')
    paddle = Paddle(canvas, "red")
    ball = Ball(canvas, paddle, score, "grey")

    game_over_text = canvas.create_text(canvas_width / 2, canvas_hight / 2, text='游戏结束', state='hidden', fill='red',
                                        font=(None, 18, "bold"))
    introduce = '欢迎来到弹球游戏\n  按任意键开始\n'
    game_start_text = canvas.create_text(canvas_width / 2, canvas_hight / 2, text=introduce, state='normal',
                                         fill='magenta', font=(None, 18, "bold"))
    while True:
        if (ball.hit_bottom == False) and ball.paddle.started:
            canvas.itemconfig(game_start_text, state='hidden')
            ball.draw()
            paddle.draw()
        if ball.hit_bottom == True:
            time.sleep(0.1)
            canvas.itemconfig(game_over_text, state='normal')
        tk.update_idletasks()
        tk.update()
        time.sleep(0.01)


if __name__ == '__main__':
    main()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值