想问一下,类中的方法难道不也是函数吗?为什么函数play()和函数ah()调用的方式不一样,而且输出的结果也不一样。什么叫作在实例中并不能直接访问到成员变量的私有属性?
play()是实例方法,意思是创建一个类的实例才能够访问的方法。你的代码里有一个类dog, 所以当你用
dog = Dog("旺财") 这行代码创建了一个Dog类的实例,并将这个实例赋值给dog。这个时候才能通过dog.play()调用play()方法。
ah()是一个普通方法,可以直接调回,无需任何实例;而且实例只能调用class中有的实例方法。ah方法已经在类外,所以无法被实例访问。
另外,python的实例方法中有一个默认的参数,也就是self, 它表示实例本身,可以通过self来调用实例方法,已经属性。
你的代码在有一个错误,就是在ah(self)方法中,ah是普通方法,无法使用self关键字。你可以改成:
def ah(name):
print('我的名字是', name)
所以你现在首先要学会区分不同的方法类型,比如,普通方法,实例方法,类方法,静态方法。
在本节中, 我们将添加一个Play按钮, 它在游戏开始前出现, 并在游戏结束后再次出现, 让玩家能够开始新游戏。
当前, 这个游戏在玩家运行alien_invasion.py时就开始了。 下面让游戏一开始处于非活动状态, 并提示玩家单击Play按钮来开始游戏。
3.1.1 创建Button类
由于Pygame没有内置创建按钮的方法, 我们创建一个Button 类, 用于创建带标签的实心矩形。 你可以在游戏中使用这些代码来创建任何按钮。
3.1.2 在屏幕上绘制按钮
我们将使用Button 类来创建一个Play按钮。 鉴于只需要一个Play按钮, 我们直接在alien_invasion.py中创建它。
接下来, 修改update_screen() , 以便在游戏处于非活动状态时显示Play按钮。
3.1.3 开始游戏
为在玩家单击Play按钮时开始新游戏, 需在game_functions.py中添加如下代码, 以监视与这个按钮相关的鼠标事件
至此, 你应该能够开始这个游戏了。 游戏结束时, game_active 应为False , 并重新显示Play按钮。
3.1.4 重置游戏
前面编写的代码只处理了玩家第一次单击Play按钮的情况, 而没有处理游戏结束的情况, 因为没有重置导致游戏结束的条件。
为在玩家每次单击Play按钮时都重置游戏, 需要重置统计信息、 删除现有的外星人和子弹、 创建一群新的外星人, 并让飞船居中
3.1.5 将Play按钮切换到非活动状态
当前, Play按钮存在一个问题, 那就是即便Play按钮不可见, 玩家单击其原来所在的区域时, 游戏依然会作出响应。 游戏开始后, 如果玩家不小心单击了Play按钮原来所处的区域, 游戏将重新开始!为修复这个问题, 可让游戏仅在game_active 为False 时才开始。
3.1.6 隐藏光标
为让玩家能够开始游戏, 我们要让光标可见, 但游戏开始后, 光标只会添乱。 为修复这种问题, 我们在游戏处于活动状态时让光标不可见。
通过向set_visible() 传递False , 让Pygame在光标位于游戏窗口内时将其隐藏起来。
游戏结束后, 我们将重新显示光标, 让玩家能够单击Play按钮来开始新游戏。
在ship_hit() 中, 我们在游戏进入非活动状态后, 立即让光标可见。 关注这样的细节让游戏显得更专业, 也让玩家能够专注于玩游戏而不是费力搞明白用户界面
3.2 提高等级
每当玩家将屏幕上的外星人都消灭干净后, 加快游戏的节奏, 让游戏玩起来更难。
3.2.1 修改速度设置
我们首先重新组织Settings 类, 将游戏设置划分成静态的和动态的两组。 对于随着游戏进行而变化的设置, 我们还确保它们在开始新游戏时被重置。
通过修改速度设置ship_speed_factor 、 alien_speed_factor 和bullet_speed_factor 的值, 足以加快整个游戏的节奏!
3.2.2 重置速度
每当玩家开始新游戏时, 我们都需要将发生了变化的设置重置为初始值, 否则新游戏开始时, 速度设置将是前一次游戏增加了的值。
3.3 记分
下面来实现一个记分系统, 以实时地跟踪玩家的得分, 并显示最高得分、 当前等级和余下的飞船数。
得分是游戏的一项统计信息, 因此我们在GameStats 中添加一个score 属性。
3.3.1 显示得分
为在屏幕上显示得分, 我们首先创建一个新类Scoreboard 。 就当前而言, 这个类只显示当前得分, 但后面我们也将使用它来显示最高得分、 等级和余下的飞船数。 下面是这个类的前半部分, 它被保存为文件scoreboard.py
最后, 我们创建方法show_score() , 用于显示渲染好的得分图像
3.3.2 创建记分牌
为显示得分, 我们在alien_invasion.py中创建一个Scoreboard 实例
为显示得分, 修改update_screen()
3.3.3 在外星人被消灭时更新得分
为在屏幕上实时地显示得分, 每当有外星人被击中时, 我们都更新stats.score 的值, 再调用prep_score() 更新得分图像。 但在此之前, 我们需要指定玩家每击落一个外星人都将得到多少个点。
随着游戏的进行, 我们将提高每个外星人值的点数。 为确保每次开始新游戏时这个值都会被重置, 我们在initialize_dynamic_settings() 中设置它。在check_bullet_alien_collisions() 中, 每当有外星人被击落时, 都更新得分。
我们需要修改update_bullets() , 确保在函数之间传递合适的实参。
还需要修改主while 循环中调用update_bullets() 的代码。
3.3.4 将消灭的每个外星人的点数都计入得分
当前, 我们的代码可能遗漏了一些被消灭的外星人。 例如, 如果在一次循环中有两颗子弹射中了外星人, 或者因子弹更宽而同时击中了多个外星人, 玩家将只能得到一个被消灭的外星人的点数。 为修复这种问题, 我们来调整检测子弹和外星人碰撞的方式。
在check_bullet_alien_collisions() 中, 与外星人碰撞的子弹都是字典collisions 中的一个键; 而与每颗子弹相关的值都是一个列表, 其中包含该子弹撞到的外星人。 我们遍历字典collisions , 确保将消灭的每个外星人的点数都记入得分。
3.3.5 提高点数
玩家每提高一个等级, 游戏都变得更难, 因此处于较高的等级时, 外星人的点数应更高。
3.3.6 将得分圆整
大多数街机风格的射击游戏都将得分显示为10的整数倍, 下面让我们的记分系统遵循这个原则。 我们还将设置得分的格式, 在大数字中添加用逗号表示的千位分隔符。 在Scoreboard 中执行这种修改。
函数round() 通常让小数精确到小数点后多少位, 其中小数位数是由第二个实参指定的。 然而, 如果将第二个实参指定为负数, round() 将圆整到最近的10、 100、 1000等整数倍。
注意 在Python 2.7中, round() 总是返回一个小数值, 因此我们使用int() 来确保报告的得分为整数。 如果你使用的是Python 3, 可省略对int() 的调用。
3.3.7 最高得分
每个玩家都想超过游戏的最高得分记录。 下面来跟踪并显示最高得分, 给玩家提供要超越的目标。 我们将最高得分存储在GameStats 中
3.3.8 显示等级
为在游戏中显示玩家的等级, 首先需要在GameStats 中添加一个表示当前等级的属性。 为确保每次开始新游戏时都重置等级, 在reset_stats() 中初始化它。
3.3.9 显示余下的飞船数
最后, 我们来显示玩家还有多少艘飞船, 但使用图形而不是数字。 为此, 我们在屏幕左上角绘制飞船图像来指出还余下多少艘飞船。
问题解答:
根据您的问题,您想了解在Python中使用抽象类(Abstract Class)来实现接口类的功能。接口类是一种定义了一组方法的类,并要求其他类去实现这些方法。在Python中,由于支持多继承,我们可以使用抽象类来实现接口类的功能。
下面是一个示例代码,演示了如何使用抽象类来实现接口类的功能:
import abc
# 定义接口类,使用抽象类实现
class InterfaceClass(metaclass=abc.ABCMeta):
@abc.abstractmethod
def method1(self):
pass
@abc.abstractmethod
def method2(self):
pass
# 实现接口类的子类
class ImplementClass(InterfaceClass):
def method1(self):
print("ImplementClass method1")
def method2(self):
print("ImplementClass method2")
# 测试代码
implement_obj = ImplementClass()
implement_obj.method1()
implement_obj.method2()
在上面的代码中,我们定义了一个接口类InterfaceClass
,其中包含两个抽象方法method1
和method2
。子类ImplementClass
继承接口类,并实现了这两个抽象方法。在测试代码中,我们创建了ImplementClass
的实例,并调用了method1
和method2
。
这样就实现了Python中的接口类功能。通过抽象类和抽象方法的使用,我们可以定义一组方法,并要求其他类去实现这些方法,从而实现接口类的效果。
希望以上解答能够帮助您理解抽象类和接口类的概念以及在Python中的使用方法。如果还有其他问题,请随时提问。