关注「实验楼」,每天分享一个项目教程~
学python已经有两三周的时间了,看完两本书,基础知识都已基本掌握,按照书上的例子实践一下吧,虽然书上的例子bug一大堆。我猜是作者自己也没实验过吧( ̄▽ ̄)...
游戏功能设计
游戏需要的功能就以下几个小组件
一张画布
一个小球
一个返弹板
计分
控制
功能比较简单,挺没意思的,我觉得可以对接服务器,然后增加一个排行板啥的...
基于python3.5 来实现的,python2.x应该也不会差太多
窗口
制作一个大小长500px宽400px的窗口,当然我们需要导入tkinter库
from tkinter import * tk = Tk() tk.title("Python Game") tk.resizable(0, 0) tk.wm_attributes("-topmost", 1) tk.update() canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0) canvas.pack()
小球
生成小球:
这里我们创建一个Ball类,构造方法如下:
def __init__(self, canvas, paddle, color): """ 初始化球 :param canvas: Canvas :param paddle: Paddle :param color: string """ self.canvas = canvas self.paddle = paddle self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) 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
创建红色小球,并把它移动到接近中间偏上的位置,随机生成好球运动的方向。同时获取窗口大小赋给变量。
返弹板
创建返弹板:
创建一个Paddle类,构造方法如下:
def __init__(self, canvas, color): """ 初始化返弹板并绑定事件 :param canvas: :param color: """ self.canvas = canvas self.id = 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() self.canvas.bind_all(sequence='', func=self.turn_left) self.canvas.bind_all(sequence='', func=self.turn_right)
画好返弹板,并且把它移动到中间偏下的位置,获取窗口的宽度。
绑定事件,也就是监听键盘的左右键,当监听到后调用turn_left或turn_right方法,即移动反弹板。
初始化好相关模块后,咱们就得开始让各个组件动起来了...
思路就是,循环移动小球的位置自己增,当遇到窗口边界时,x或y轴自增或自减,如此循环。
当小球遇到返弹板的位置时x或y轴自己增或自减。
当小球的y轴等于0时,游戏结束。
返弹板控制
控制返弹板向左或向右:
def turn_left(self, event): """ 向左 :return: """ self.x = -2 def turn_right(self, event): """ 向右 :return: """ self.x = 2
在上面的Paddle初始化的时候有绑定这两个事件...
其他
我创建了一个“锁”,目前没有想到更好的方法,就先这么做吧,当鼠标点击窗口后,开始运行程序...
class Lock: lock = False def __init__(self): self.lock = False @classmethod def getLock(self): return self.lock @classmethod def setLock(self, lock): self.lock = lock return self
锁的作用就是当你多次点击的时候不会进行操作。
start_begin函数就是开始游戏,也就是开始让游戏动起来
使用while死循环,让程序不停的在画板上绘制出小球及画板的位置...
def start_begin(event): if Lock.getLock() == True: return Lock.setLock(True) paddle = Paddle(canvas=canvas, color="blue") ball = Ball(canvas=canvas, paddle=paddle, color='red') time.sleep(1) while True: if ball.hit_bottom == False: ball.draw() paddle.draw() tk.update_idletasks() tk.update() time.sleep(0.001)
time.sleep每0.001秒执行一次。
增加计分板
张当小球成功返弹一次 分数+1,当小球的x轴等于0时,游戏结束,显示相当信息
在Ball类的初始化函数增加文字信息:
def __init__(self, canvas, paddle, color): """ 初始化球 :param canvas: Canvas :param paddle: Paddle :param color: string """ self.fraction = 0 self.canvas_id = self.canvas.create_text(10, 10, anchor="nw") text = "得分: 0" self.canvas.itemconfig(self.canvas_id, fill="blue", text=text)
然后在控制球的返弹模块增加以下代码:
def hit_paddle(self, pos): """ 判断返弹板 :param pos: list :return: bool """ paddle_pos = self.canvas.coords(self.paddle.id) if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]: if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]: self.fraction += 1 self.canvas.delete(self.canvas_id) self.canvas_id = self.canvas.create_text(10, 10, anchor="nw") self.canvas.itemconfig(self.canvas_id, fill="blue", text="得分: ") self.canvas.insert(self.canvas_id, 12, self.fraction) return True return False
这样分数就是动态显示了...
完整代码
#!/usr/bin/env python3# encoding: utf-8from tkinter import *import randomimport timeclass Ball: def __init__(self, canvas, paddle, color): """ 初始化球 :param canvas: Canvas :param paddle: Paddle :param color: string """ self.canvas = canvas self.paddle = paddle self.id = canvas.create_oval(10, 10, 25, 25, fill=color) self.canvas.move(self.id, 245, 100) 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 self.fraction = 0 self.canvas_id = self.canvas.create_text(10, 10, anchor="nw") text = "得分: 0" self.canvas.itemconfig(self.canvas_id, fill="blue", text=text) def hit_paddle(self, pos): """ 判断返弹板 :param pos: list :return: bool """ paddle_pos = self.canvas.coords(self.paddle.id) if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]: if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]: self.fraction += 1 self.canvas.delete(self.canvas_id) self.canvas_id = self.canvas.create_text(10, 10, anchor="nw") self.canvas.itemconfig(self.canvas_id, fill="blue", text="得分: ") self.canvas.insert(self.canvas_id, 12, self.fraction) return True return False def draw(self): """ :return: """ self.canvas.move(self.id, self.x, self.y) pos = self.canvas.coords(self.id) if pos[1] <= 0: self.y = 3 if pos[3] >= self.canvas_height: self.hit_bottom = True self.canvas.create_text(100, 300, text=("游戏结束! 得分: %d") % self.fraction, fill="red") if self.hit_paddle(pos) == True: self.y = -3 if pos[0] <= 0: self.x = 3 if pos[2] >= self.canvas_width: self.x = -3class Paddle: def __init__(self, canvas, color): """ 初始化返弹板并绑定事件 :param canvas: :param color: """ self.canvas = canvas self.id = 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() self.canvas.bind_all(sequence='', func=self.turn_left) self.canvas.bind_all(sequence='', func=self.turn_right) def turn_left(self, event): """ 向左 :return: """ self.x = -2 def turn_right(self, event): """ 向右 :return: """ self.x = 2 def draw(self): """ :return: """ 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 = 0class Lock: lock = False def __init__(self): self.lock = False @classmethod def getLock(self): return self.lock @classmethod def setLock(self, lock): self.lock = lock return selfif "__main__" == __name__: tk = Tk() tk.title("Python Game") tk.resizable(0, 0) tk.wm_attributes("-topmost", 1) tk.update() canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0) canvas.pack() def start_begin(event): if Lock.getLock() == True: return Lock.setLock(True) paddle = Paddle(canvas=canvas, color="blue") ball = Ball(canvas=canvas, paddle=paddle, color='red') time.sleep(1) while True: if ball.hit_bottom == False: ball.draw() paddle.draw() tk.update_idletasks() tk.update() time.sleep(0.001) canvas.bind_all(sequence="", func=start_begin) tk.mainloop()
最终效果
转载自:latte cake
文章地址:http://lattecake.com/post/20091?utm_source=tuicool&utm_medium=referral
作者:不跑马拉松的摄影师不是好城续员
嗯~如果你觉得本文对你有所帮助,别忘了点赞和分享啊~
你也可以点击下方的“阅读原文”,查看更多计算机专业课程~
当然,点击菜单【技术教程】,可以随时随地看教程,涨技术~