Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)

很多萌新在学习Godot Engine和GDScript之前并没有接触过面向对象编程,所以看《手把手带你Godot游戏开发 第一弹》时遇到“继承”这个概念,感到很困惑,什么场景下使用继承呢?而且有小伙伴反映,翻了教科书和网络上的一些文章,反而有越看越迷糊的趋势。
老王也是从萌新一路走来,所以对这种困惑很理解,问题并不在于教科书和网文,而是由于萌新缺乏编程的实践,导致阅读一些抽象的叙述时,脑海中没有足够的情景来唤起共鸣。此类困惑的根本解决方案只有一个,那就是 “硬着头皮死磕” ,多实践,多碰钉子,多积累。最终能够让你豁然开朗的,并不是某一个答案,而恰恰是你积累的问题。

今天老王也用Godot的GDScript提供一个使用继承机制的情景。

文章目录

      • 情景
      • 如果没有继承
        • 游戏策划案第一版
        • 游戏策划案第二版
        • 游戏策划案第三版
      • 当萌新学会了继承
        • 游戏策划案第一版
        • 游戏策划案第二版
        • 游戏策划案第三版
      • 小结

情景

这是一个Godot游戏小萌新的故事。。。
Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第1张图片

如果没有继承

游戏策划案第一版

游戏策划对萌新说:“要在游戏中实现三种小怪物,小怪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的魔法技能")

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第2张图片

耶!看起起来还不错!

游戏策划案第二版

还没来得及高兴,策划带来了策划案的第二版。

“我们希望增加更多种类的小怪,嗯…大约有100种吧。它们和小怪A、B、C的关系相似。都具有相同的属性,也有各自不同的方法 ”策划说。

“啊?。。。好吧”萌新小伙伴,皱了皱眉,又开工了。。。

过程略… 这次耗时有点长,期间由于手抖眼花,还弄出了不少Bug…

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第3张图片

游戏策划案第三版

刚打算收工,策划又来了:“ 这次要去掉所有小怪中的 loyalty属性,增加一个共同的“咆哮”技能”。

萌新:“……&*%……&¥%……#))——”

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第4张图片

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第5张图片

当萌新学会了继承

游戏策划案第一版

#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的魔法技能")

多定义了一个基类,少写了几行重复的代码。

游戏策划案第二版

过程略。。。少了重复的代码,出错的概率小了些,不过没看出什么太神奇的地方。

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第6张图片

游戏策划案第三版

#MonsterBase.gd
extends Node
class_name MonsterBase #从Godot3.1开始可以给类起名字了
var level = 1
var hp = 5
#var loyalty = 10
func roar():
	print("路见不平一声吼,该出手时就出手")

什么?!!H(&(……%&%…………,这么简单就实现了?!!!

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第7张图片

曾经让萌新和策划决裂的问题不再是问题,从此他们幸福地生活在一起…

Q&A:通过一个情景理解GDScript中的继承机制(Godot游戏引擎萌新向)_第8张图片

小结

言归正传,从上文两种情况的对比我们不难发现,继承机制说白了就是把派生类的共同特征放到(抽象到)基类,当存在大量具有共同特征的类,而且共同特征可能发生改变时,使用继承会大大提高代码的可维护性。

你可能感兴趣的:(#,Godot,基础,Godot笔记)