以编程方式实例化子类

问题描述 投票:0回答:1

如何将一个场景实例定义为子类,其中超类的

.tscn
将在所有子类之间共享?

对于纸牌战斗项目,我试图通过类使我的代码库更具可扩展性。我有一个定义类

EnemyBase
的脚本,其中有针对
EnemyTypeA
EnemyTypeB
等的单独脚本。我想象一种情况,我只需要一个
.tscn
文件,并且我可以以某种方式将正确的类分配给获取其逻辑的场景。我希望这样,理论上我可以创建尽可能多的敌人类型,并且维护代码库也同样容易,因为公共函数只需要编写一次(在超类中)。

目前,我发现唯一有效的方法是(A)为每个子类创建一个单独的

.tscn
文件,以及(B)使用“伪”类,而不是根本有子类,通过在类中使用枚举变量def 保存各种“子类”的名称,并在所有函数中使用
match
语句来为不同的“类”定义不同的功能。我相信这些都不是解决方案,因为 (A) 本质上有许多完全独立定义的场景,而 (B) 使一个脚本非常长且难以阅读(但似乎是两者中更好的一个)。

这似乎是一个非常明显/常见的需求,所以我想有一种巧妙的方法可以做到这一点。如果除了类/子类之外还有另一种组织场景的方法,我也很想听听。谢谢。

design-patterns godot
1个回答
0
投票

对于未来想知道的人,我已经找到了这个问题的可接受的解决方案(在 Godot 4.+ 中工作)。

该解决方案取决于这样一个事实:场景的脚本是一个可以通过编程方式更改的参数。因此,可以使用所有子类将包含的任何节点创建“共享”场景。例如,在敌人变化的情况下,我可以让场景

baseEnemy.tscn
包含诸如包含其名称的
Label
节点、
ProgressBar
健康指示器等内容。

这个场景会附加一个定义敌人实例的脚本。比如:

base

现在,我们已经准备好创建子类了。然后我们将定义许多子类,其风格如下:

# baseEnemy.gd class_name baseEnemy extends WhateverNodeTypeYouWantToExtend @export var enemy_name : String = "Placeholder Enemy!" @export var hp : int = 01 @export var hpMax : int = 01 func _ready(): $label.text = "%s" % enemy_name $healthBar.min_value = 0 $healthBar.max_value = hpMax $healthBar.value = hp func generic_behavior(): # Placeholder generic behavior. Something that is shared! # For example, a function like lower_health() might apply to every enemy type pass func specific_behavior(): # Placeholder specific behavior. Something that will be overridden! # For example, a function like decide_next_action() might be different for every class pass

但是我们仍然存在实际实例化子类的问题。

假设我们有一些场景,希望其中存在

# enemyA.gd class_name enemyA extends baseEnemy enemy_name = "Enemy A!" hpMax = 100 func _ready(): # This time, whatever paramters we want will be changed for enemies of this class. # for example, changing the name, hp, etc. # This next line means to call _ready as defined by its superclass, which is baseEnemy super._ready() func specific_behavior(): # Now we would define this function, and this code will only be run for enemies of this type! pass

。我们会这样做:

enemyA

现在,该对象生成的名称为“Enemy A”,正确的生命值,并使用指定版本的 Specific_behavior()。

© www.soinside.com 2019 - 2024. All rights reserved.