我试图用Swift做一个简单的游戏。游戏有不同的级别,每个级别都要求游戏的行为方式略有不同。我决定为每个级别使用不同的类,所有类都继承自基类级别。
这是基础:
import SpriteKit
class LevelBase {
var scene: GameScene! // Seems very dodgy
var blocks = [SKSpriteNode]()
init(scene: GameScene) { // Should this be required init?
self.scene = scene
}
func filterBlock(_ block: SKSpriteNode) {
blocks = blocks.filter() { $0 !== block } // Looks really dodgy to me
}
func update(time: TimeInterval) {
// For override
}
func levelUp() {
// For override
}
func postGenerate() {
// For override
}
}
然而,对我来说,这堂课似乎写得非常糟糕。我无法找到任何在类中创建的函数的例子,只是为了被覆盖,这让我觉得我做错了。我应该为这样的可选功能使用扩展或协议吗?我不太明白它们是如何工作的,所以到目前为止我还没有使用它。
第二个问题是这个类需要用游戏场景变量初始化,因为某些级别需要它来添加或删除精灵。考虑到这个类是在游戏场景的文件中创建的,这看起来特别狡猾。
肯定有更好的方法吗?
答案 0 :(得分:3)
我没有SpriteKit的经验,但从一般的角度来看,你应该考虑"Favour composition over Inheritance"。
您将拥有一个不用于子类化的Level类,但可以使用具有不同实现的对象或值进行实例化。
此外,您应该使用协议来定义这些协议,并且可以将默认实现添加为协议扩展。
final class Level {
init(levelImplementation: LevelImplementationType) {
self.levelImplementation = levelImplementation
}
let levelImplementation: LevelImplementationType
func navigate() {
levelImplementation.navigate()
}
func update(timeInterval: TimeInterval) {
levelImplementation.update(timeInterval: timeInterval)
}
}
Level将使用符合LevelImplementationType
protocol LevelImplementationType {
func navigate()
func update(timeInterval: TimeInterval)
}
默认实施可以通过扩展来完成。
extension LevelImplementationType {
func navigate() {
}
func update(timeInterval: TimeInterval) {
}
}
LevelImpelmenation需要符合LevelImplementationType
,但不会有任何进一步的限制。即他们可以有非常不同的初始化者。
struct LevelImplementation1: LevelImplementationType {
// useses default implementation of `navigate` and `update` from extension
}
struct LevelImplementation2: LevelImplementationType {
// useses default implementation of `update` from extension
func navigate() {
}
}
struct LevelFileImplementation: LevelImplementationType {
init(with path: String) {
// read variables from file at path
}
func navigate() {
// navigate as given in file
}
}
级别实例可以像
一样创建let level1 = Level(levelImplementation: LevelImplementation1())
let level2 = Level(levelImplementation: LevelImplementation2())
let level3 = Level(levelImplementation: LevelFileImplementation(with: "path/to/file"))