持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
面向对象
您可能以前听说过面向对象编程 (OOP) 这个术语。但是,如果您不熟悉它,请不要担心,因为这个概念非常简单。
那么,在OOP术语中,对象到底是什么呢?好吧,它实际上可以是任何东西。在游戏中,我们可能有一个粒子的物体,比如说,从一个
爆炸,或引起爆炸的悬停坦克。事实上,整个游戏世界都可以是一个对象。对象的目的是包含信息并给出
程序员利用这些信息做事的能力。
在构造对象时,通常最好从弄清楚什么开始
它包含的信息或属性。让我们想想在一个物体中会发现什么旨在代表未来主义的悬停坦克。它应包含以下属性的最低限度:
·位置:水箱在哪里?
方向:它面向哪个方向?
·速度:它的速度有多快?
装甲:它有多少装甲?
弹药:它有多少枚炮弹?
现在我们有了描述坦克及其正在做什么的信息,我们需要赋予它执行坦克在游戏中需要做的所有动作的能力。在OOP中,这些操作被称为方法。我可以想到坦克肯定需要的以下方法,但可能会有更多的方法:
·移动:向前移动坦克。
·转弯:向左/向右旋转油箱。
·火力:发射炮弹。
·命中:这是敌方炮弹击中坦克时的动作。
·爆炸:将坦克替换为爆炸动画。
您可以看到,这些方法通常会更改对象的属性。当使用Move方法时,它将更新坦克的位置。同样,当使用Fire方法时,弹药的值将被更新(当然,除非没有弹药剩余,否则Fire不会做任何事情!
使用类
类是Python定义对象的方式。您以前实际使用过类;列表,字典,甚至字符串都是类,但您也可以创建自己的类。将类视为对象的模板,因为您只需定义一次类,即可根据需要创建任意数量的对象。让我们编写一个简单的 Tank 类(参见清单 2-4),稍后我们将使用它来创建一个简单的游戏。
当Python遇到类坦克(对象)时,它会创建一个名为坦克的类,
它派生自名为 object 的基类。从类派生意味着基于它所做的事情进行构建。我们可以首先创建一个名为Cary的类,它可以处理移动和转弯,然后通过从中派生并添加发射武器的能力来创建坦克。这种方法的优点是可以重复使用Carve,以使其他游戏实体能够旋转和移动。对于此示例,我们没有另一个类可以构建,因此我们的基类将是 object,它是一个内置于 Python 本身的简单类。
注意 我可能给你的印象是对象做不了多少,但实际上它在使用类时在幕后做了很多有用的事情 - 你只是不直接使用它。
类语句后面的缩进代码块中的所有内容都是类
定义。在这里,我们设置了用于描述对象的属性,并提供了它需要的所有方法。在Python中,属性只是存储在对象中的变量,方法是处理对象的函数。在我们的 Tank 类中,有一个奇怪命名的方法called__init__,它对 Python 具有特殊意义。创建对象时,Python 会自动调用此方法。Python 程序员通常使用它来为对象分配属性,但您可以执行首次创建对象时可能需要的任何其他操作。
__init__
方法采用两个参数:自身和名称。因为方法可能用于许多对象,我们需要某种方法来知道我们正在使用哪个对象。这就是 self 的用武之地 - 它是对 Python 自动提供给所有方法调用的当前对象的引用。第二个参数(name)是我们用来区分一个坦克和另一个坦克的字符串,因为会有多个坦克。
__init__
中的代码首先将name参数复制到属性中,以便我们稍后可以检索它;然后,它会分配一些我们需要的其他属性。在我计划的游戏中,我们不需要为坦克提供大量信息;我们只需要知道坦克是否活着(自我活着),它有多少弹药(包括弹药),以及它还剩下多少装甲(自我装甲)。
注意 您不必调用第一个参数 sel f。你可以随心所欲地命名它,但坚持自我是个好主意,这样当你阅读你的代码时,你就会确切地知道它是什么。Python程序员倾向于坚持这个约定,所以在交换代码时不会混淆。
创建对象
现在我们有了坦克定义,我们可以通过调用 Tank 来创建一个新的坦克,我们用一个字符串提供该坦克。让我们看一个例子:
这将创建一个名为Bob的新坦克并调用__init__
然后分配给变量 my_tank,该变量称为 Tank 类的实例。现在,我们可以将my_tank视为单个对象 - 将其传递到函数中,将其存储在列表中,依此类推,或者我们可以单独访问属性。例如,打印my_tank.name 将显示 Bob。
加入我们的类
只有一种方法,Tank 类就无法做任何有趣的事情。让我们用清单 2-5 中的更多方法充实它。
清单 2-5 中的第一种方法是另一种特殊方法。任何在前面和末尾有两个下划线的名称对Python都有特殊的含义。
str_is返回描述该对象的字符串;当您尝试将对象转换为具有str的字符串时,将调用它,这将在您打印它时发生。因此,如果我们要打印my_tank,它应该显示一个字符串,其中包含有关Bob坦克的一些有用信息。清单 2-5 The_str_in根据坦克是活的还是死的返回了不同的字符串。如果坦克是活的,那么这条线将运行:
返回 “%s (%i 装甲, %i 炮弹)” 。(self.name,自我装甲,自我弹药)
做了一些你以前可能没有见过的事情。字符串“응s(%i装甲,òi 炮弹)”与元组(self.name,自装甲,
自我。弹药),使用 &运算符。这称为字符串格式设置,这是创建复杂字符串而无需大惊小怪的好方法。字符串中的前两个字符是 òs,这告诉 Python 用元组中的第一项替换它们,元组是一个包含坦克名称的字符串。稍后在字符串中,Python 达到 % i,该值被元组中的第二个项目(整数)替换,依此类推,直到元组中不再有项目。字符串插值通常比将许多小字符串相加更简单。此行执行相同的操作,但使用简单的字符串串联:
这有点复杂,我相信你会同意的!字符串格式设置可以通过多种方式设置整数、浮点数和字符串的格式。有关详细信息,请参阅 Python 文档(docs.python.org/3.4/library… Tank类中的第二种方法,fire_at,是事情变得有趣的地方。它采用参数敌人,即我们要射击的坦克对象。首先,它检查还剩下多少弹药。如果至少有一个壳,它就会减少自我。弹药由 1
(因为我们刚刚发射了一枚炮弹)并调用敌方坦克的命中方法。在敌方坦克的命中方法中,它会减少自我。装甲20。如果没有剩余的装甲,那么敌人已经死亡,所以我们称之为爆炸方法,将坦克标记为死亡。
如果这是我们正在开发的图形游戏,这些方法将创建一些视觉效果。fire_at将创建一个外壳图像或3D模型并设置其轨迹,爆炸可能会显示某种令人印象深刻的爆炸动画。但是对于这个小型测试游戏,我们将仅使用一些打印语句来描述当前正在发生的事情。
清单 2-6 显示了整个 Tank 类;将其保存为坦克。.py。如果运行此脚本,它将不执行任何操作,因为它只定义了 Tank 类。我们将使用游戏代码的其余部分创建另一个Python脚本。