Kivy :开源跨平台的Python 框架

好久没有写游戏系列教程了,今天恰好浏览到了 kivy 这个开源跨平台的python 框架,它能用于开发多点触控的用户界面程序,允许快速简单的交互设计,非常方便,于是有了制作本教程的想法。
本教程将教你如何使用 kivy 编写一款乒乓球游戏。我们将从一个基本的应用程序开始,描述创建这个游戏的每个步骤。
kivy 是用 python 和 cython 编写的,基于 opengl es 2,支持各种输入设备并拥有丰富的部件库。使用相同的代码,你可直接实现多平台应用,包括 windows、macos、linux、android 和 ios。所有 kivy 部件都支持多点触控。
1.准备
开始之前,你要确保python和pip已经成功安装在电脑上,如果没有,可以访问这篇文章:超详细python安装指南 进行安装。
**(可选1) **如果你用python的目的是数据分析,可以直接安装anaconda:python数据分析与挖掘好帮手—anaconda,它内置了python和pip.
**(可选2) **此外,推荐大家用vscode编辑器,它有许多的优点:python 编程的最好搭档—vscode 详细指南。
请选择以下任一种方式输入命令安装依赖 :
windows 环境 打开 cmd (开始-运行-cmd)。macos 环境 打开 terminal (command+空格输入terminal)。如果你用的是 vscode编辑器 或 pycharm,可以直接使用界面下方的terminal.pip install kivy[base] kivy_examples2.简单使用 kivy
这一节将简单介绍kivy的基本使用,首先为我们游戏创建一个目录和一个名为main.py的文件:
# main.pyfrom kivy.app import appfrom kivy.uix.widget import widgetclass ponggame(widget): passclass pongapp(app): def build(self): return ponggame()if __name__ == '__main__': pongapp().run()在命令行中输入 python main.py 运行该应用程序。它应该只显示一个黑色的窗口。所以我们所做的只是创建一个非常简单的kivy应用程序,它创建了一个 ponggame widget 类的实例,并将其作为应用程序用户界面的根元素返回。
在这一点上你应该把它想象成一个 widget 的分层树。kivy 将这个 widget 放在默认的窗口中。在下一步,我们将通过定义 ponggame 小部件的外观来绘制pong的背景和游戏分数。
3.kivy - 添加简单图形
我们将使用一个 .kv 文件来定义 ponggame 类的外观。由于我们的应用程序类被称为 pongapp,我们可以简单地在同一目录下创建一个名为 pong.kv 的文件,当应用程序运行时将会自动加载。
因此,为了定义游戏的外观,我们创建一个名为 pong.kv 的新文件并添加以下内容:
#:kivy 1.0.9: canvas: rectangle: pos: self.center_x - 5, 0 size: 10, self.height label: font_size: 70 center_x: root.width / 4 top: root.top - 50 text: 0 label: font_size: 70 center_x: root.width * 3 / 4 top: root.top - 50 text: 0注意一个常见错误:kv文件的名称,例如 pong.kv,必须与应用程序的名称一致,例如 pongapp(app结尾之前的部分)。
如果你现在运行这个应用程序,你应该看到中间有一个竖条,还有两个零,那里将显示玩家的分数,如下所示:
可以看到,在第一行,我们有:
#:kivy 1.0.9每个 kv 文件都需要第一行。它应该以 #:kivy 及一个空格开头,然后是它要使用的 kivy 版本(因此 kivy 可以确保您至少拥有所需的版本,或者稍后处理向后兼容性)。
再往下看 kv 文件里定义了三个元素,一个 canvas 和两个 label。
先说说两个label,他们代表的是左右两个数字,设定了 font_size(字体大小), center_x(中心位置), top(离顶部距离), text(文本),此外可以看到 root.width 和 root.top 的使用,这样写的好处是能跟跟随窗口宽度和高度的变化而变化。
另一个元素 canvas,它的下面定义了 rectangle 参数,意思是我们向画布添加一个矩形。将矩形的 pos 设置为小部件水平中心左侧 5 个像素,y 设置为 0,这就定义了矩形的显示位置。
矩形的大小 size 设置为宽度为 10 像素,高度为小部件的高度。像这样定义图形的好处是,当值表达式中使用的任何小部件的属性发生变化时,渲染的矩形将自动更新。
4. kivy - 增加乒乓球球体
好了,我们有一个基本的乒乓球场(虽然很简陋),但我们仍然需要球拍和一个球来打球。让我们从球开始。我们将添加一个新的 pongball 类来创建一个小部件,它将成为我们的球并使它弹跳起来。
pongball 类:
class pongball(widget): # velocity of the ball on x and y axis velocity_x = numericproperty(0) velocity_y = numericproperty(0) # referencelist property so we can use ball.velocity as # a shorthand, just like e.g. w.pos for w.x and w.y velocity = referencelistproperty(velocity_x, velocity_y) # ``move`` function will move the ball one step. this # will be called in equal intervals to animate the ball def move(self): self.pos = vector(*self.velocity) + self.pos白球的 kv 配置如下:
: size: 50, 50 canvas: ellipse: pos: self.pos size: self.size为了使这一切顺利进行,你还必须为球体增加所用的property属性类。下面是这一步更新后的python代码和kv文件。
from kivy.app import appfrom kivy.uix.widget import widgetfrom kivy.properties import numericproperty, referencelistpropertyfrom kivy.vector import vectorclass pongball(widget): velocity_x = numericproperty(0) velocity_y = numericproperty(0) velocity = referencelistproperty(velocity_x, velocity_y) def move(self): self.pos = vector(*self.velocity) + self.posclass ponggame(widget): passclass pongapp(app): def build(self): return ponggame()if __name__ == '__main__': pongapp().run()kv文件如下:
#:kivy 1.0.9: size: 50, 50 canvas: ellipse: pos: self.pos size: self.size: canvas: rectangle: pos: self.center_x - 5, 0 size: 10, self.height label: font_size: 70 center_x: root.width / 4 top: root.top - 50 text: 0 label: font_size: 70 center_x: root.width * 3 / 4 top: root.top - 50 text: 0 pongball: center: self.parent.center5. kivy - 增加乒乓球体运动
现在我们的目的是让这个球动起来,因此必须定期调用 move 函数让他动起来。使用 kivy 提供的 clock 函数可以轻易地做到这一点:
clock.schedule_interval(game.update, 1.0/60.0)这一行将导致游戏对象的更新函数每秒被调用60次。
不过我们还有一个问题。我们想确保pongball的移动函数被定期调用,但是在我们的代码中没有任何对球对象的引用,因为我们只是通过 kv 文件在 ponggame 类的 kv 规则中添加了它。
由于我们要做的不仅仅是移动球(比如把球从墙上弹下来,然后再弹到球员的球拍上),我们可能需要为我们的ponggame类建立一个更新方法。
class ponggame(widget): def update(self, dt): # call ball.move and other stuff passclass pongapp(app): def build(self): game = ponggame() clock.schedule_interval(game.update, 1.0/60.0) return game然而,这仍然不能改变我们没有对kv规则所创建的 pongball 进行操作的这一事实。为了解决这个问题,我们可以给ponggame类添加一个objectproperty,并将其与kv规则中创建的widget挂钩。
一旦这样做了,我们就可以很容易地在更新方法中引用球的属性,甚至可以让它从边缘弹起。
class ponggame(widget): ball = objectproperty(none) def update(self, dt): self.ball.move() # bounce off top and bottom if (self.ball.y self.height): self.ball.velocity_y *= -1 # bounce off left and right if (self.ball.x self.width): self.ball.velocity_x *= -1在kv文件中将其与代码中设定的 id: ball 映射起来:
: ball: pong_ball # ... (canvas and labels) pongball: id: pong_ball center: self.parent.center6. kivy - 球拍移动事件
现在,我们的球正在弹来弹去。唯一缺少的是可移动的球拍和对分数的跟踪。我们不会再去讨论创建类和kv规则的所有细节,因为这些概念已经在前面的步骤中涵盖了。
相反,让我们把重点放在如何响应用户的输入而移动球拍上。你可以在python实用宝典公众号后台回复:乒乓球 获得全部代码和kv规则。
在kivy中,小部件可以通过实现 on_touch_down、on_touch_move和on_touch_up 方法对输入做出反应。默认情况下,widget类实现这些方法时,只是在其子部件上调用相应的方法来传递事件,直到其中一个子部件返回true。
乒乓运动是非常简单的。球拍只需要向上和向下移动。事实上,它是如此简单,我们甚至不需要让球员小部件自己处理事件。我们只需为ponggame类实现on_touch_move函数:
def on_touch_move(self, touch): if touch.x self.width - self.width/3: self.player2.center_y = touch.y我们将在numericproperty中保留每个球员的分数。ponggame的分数标签通过改变 numericproperty score来保持更新,这反过来又会更新ponggame的子标签文本属性。
这是如何实现的?因为kivy属性会自动绑定到其对应的kv文件中的任何引用。当球从两侧逃出时,我们将通过ponggame类中的更新方法来更新分数并再次发球。
pongpaddle类也实现了一个 bounce_ball 方法,这样球就会根据它击中球拍的位置而产生不同方向的弹跳,非常有意思。下面是pongpaddle类的代码:
class pongpaddle(widget): score = numericproperty(0) def bounce_ball(self, ball): if self.collide_widget(ball): speedup = 1.1 offset = 0.02 * vector(0, ball.center_y-self.center_y) ball.velocity = speedup * (offset - ball.velocity)
到这一步我们基本就完成了整个游戏的制作,如何,你心动了吗?

拓扑结构,拓扑结构有哪些类型?
【技术交流】关于DC/DC降压芯片应用和选型参考
雨水情在线监测预警物联网系统解决方案
诺基亚10真机曝光 五个后置摄像头让人头皮发麻
计算机可以通过简单的指令对其进行编程后进行自我训练
Kivy :开源跨平台的Python 框架
雷蛇推出手机游戏手柄,可为大屏手机或游戏手机进行适配
使用RX微控制器的无线连接解决方​​案简化物联网开发
如何建造一个太阳能驱动的筏鸟推进器
德州仪器为eCall系统设计提供模拟及嵌入式IC
谷歌高管自爆安卓8.0 这命名你知道吗
荷兰拍卖新的5G频谱,沃达丰、T-Mobile和荷兰电信均获得频谱分配
开关电容稳压器提供电流增益
泛在电力物联网建设的基础和关键是什么?
ADAS要如何运用深度学习?
硫化氢气体检测仪的应用特点及如何选择
电源模块导热灌封胶、采购员在灌封胶选购时需注意哪些事项?
世界杯上的中国家电企业,能否开出国际市场
jtag与jlink有什么区别
Hello 5G赋能未来,5G预商用的挑战与思考