很多萌新在学习Godot Engine和GDScript之前并没有接触过面向对象编程,所以看《手把手带你Godot游戏开发 第一弹》时遇到“继承”这个概念,感到很困惑,什么场景下使用继承呢?而且有小伙伴反映,翻了教科书和网络上的一些文章,反而有越看越迷糊的趋势。
老王也是从萌新一路走来,所以对这种困惑很理解,问题并不在于教科书和网文,而是由于萌新缺乏编程的实践,导致阅读一些抽象的叙述时,脑海中没有足够的情景来唤起共鸣。此类困惑的根本解决方案只有一个,那就是 “硬着头皮死磕” ,多实践,多碰钉子,多积累。最终能够让你豁然开朗的,并不是某一个答案,而恰恰是你积累的问题。
今天老王也用Godot的GDScript提供一个使用继承机制的情景。
游戏策划对萌新说:“要在游戏中实现三种小怪物,小怪A、小怪B和小怪C”。
小怪A是治愈系的,它的概念设计如下:
成员 | 说明 |
---|---|
level |
等级 |
hp |
体力 |
loyalty |
忠诚度 |
cure() |
调用它就可以释放治愈技能 |
小怪B是攻击系的,它的概念设计如下:
成员 | 说明 |
---|---|
level |
等级 |
hp |
体力 |
loyalty |
忠诚度 |
attack() |
调用它就可以释放攻击技能 |
小怪C是魔法系的,它的概念设计如下:
成员 | 说明 |
---|---|
level |
等级 |
hp |
体力 |
loyalty |
忠诚度 |
magic() |
调用它就可以释放魔法技能 |
看起来并不难实现,于是萌新开工了:
#MonsterA.gd
extends Node
var level = 1
var hp = 5
var loyalty = 10
func cure():
"""具体逻辑略"""
print("MonsterA的治愈技能")
然后Ctrl + C
/Ctrl + V
删掉func cure()
改成func attack()
实现逻辑…
#MonsterB.gd
extends Node
var level = 1
var hp = 5
var loyalty = 10
func attack():
"""具体逻辑略"""
print("MonsterB的攻击技能")
继续Ctrl + C
/Ctrl + V
删掉func attack()
改成func magic()
实现逻辑…
#MonsterC.gd
extends Node
var level = 1
var hp = 5
var loyalty = 10
func magic():
"""具体逻辑略"""
print("MonsterC的魔法技能")
耶!看起起来还不错!
还没来得及高兴,策划带来了策划案的第二版。
“我们希望增加更多种类的小怪,嗯…大约有100种吧。它们和小怪A、B、C的关系相似。都具有相同的属性,也有各自不同的方法 ”策划说。
“啊?。。。好吧”萌新小伙伴,皱了皱眉,又开工了。。。
过程略… 这次耗时有点长,期间由于手抖眼花,还弄出了不少Bug…
刚打算收工,策划又来了:“ 这次要去掉所有小怪中的 loyalty
属性,增加一个共同的“咆哮”技能”。
萌新:“……&*%……&¥%……#))——”
#MonsterBase.gd
extends Node
class_name MonsterBase #从Godot3.1开始可以给类起名字了
var level = 1
var hp = 5
var loyalty = 10
#MonsterA.gd
extends MonsterBase #继承MonsterBase
func cure():
"""具体逻辑略"""
print("MonsterA的治愈技能")
#MonsterB.gd
extends MonsterBase #继承MonsterBase
func attack():
"""具体逻辑略"""
print("MonsterB的攻击技能")
#MonsterC.gd
extends MonsterBase #继承MonsterBase
func magic():
"""具体逻辑略"""
print("MonsterC的魔法技能")
多定义了一个基类,少写了几行重复的代码。
过程略。。。少了重复的代码,出错的概率小了些,不过没看出什么太神奇的地方。
#MonsterBase.gd
extends Node
class_name MonsterBase #从Godot3.1开始可以给类起名字了
var level = 1
var hp = 5
#var loyalty = 10
func roar():
print("路见不平一声吼,该出手时就出手")
什么?!!H(&(……%&%…………,这么简单就实现了?!!!
曾经让萌新和策划决裂的问题不再是问题,从此他们幸福地生活在一起…
言归正传,从上文两种情况的对比我们不难发现,继承机制说白了就是把派生类的共同特征放到(抽象到)基类,当存在大量具有共同特征的类,而且共同特征可能发生改变时,使用继承会大大提高代码的可维护性。