swift – 以编程方式创建SKScene子类,没有大小信息?
|
我正在尝试学习如何制作一个GameManager类型的类,并为我的每个GameScenes制作单独的类……可能是错误的做法,但为了这个问题,请接受这个作为做事的方式.
我的GameManager看起来像这样,有一个对每个场景的引用,这是静态的: import SpriteKit
class GM {
static let scene2 = SecondScene()
static let scene3 = ThirdScene()
static let home = SKScene(fileNamed: "GameScene")
}
如何以编程方式创建SKScene,没有大小信息,因为它们位于SKScene的子类中,并且不知道视图大小是什么,我不希望他们需要担心这个: 我这样做,但在方便时获得EXC_BAD_Access覆盖init() class SecondScene: SKScene {
override init(size: CGSize){
super.init(size: size)
}
convenience override init(){
self.init()
self.backgroundColor = SKColor.red
self.anchorPoint = CGPoint(x: 0.5,y: 0.5)
}
}
解决方法
正如我所提到的,你的问题有点模糊,但让我们举一些关于GameManager类的例子.
在开始之前,让我们区分调用它 let scene = StartScene(size: ...) 还有这个 let scene = SKScene(fileNamed: "StartScene") 第一种方法,大小,是在代码中创建场景时,并且您没有使用xCode可视级别编辑器. 第二种方法是在使用Xcode级别编辑器时,因此您需要创建一个StartScene.sks文件.它在fileNamed中查找的.sks文件. 现在对于一些游戏经理的例子,让我们首先想象我们有3个SKScenes. class StartScene: SKScene {
override func didMove(to view: SKView) { ... }
}
class GameScene: SKScene {
override func didMove(to view: SKView) { ... }
}
class GameOverScene: SKScene {
override func didMove(to view: SKView) { ... }
}
假设您想要从StartScene过渡到GameScene,您可以在StartScene中将此代码添加到正确的位置,例如按下播放按钮时.这是从SKScene本身直接从SKScene转移到下一个SKScene的最简单方法. // Code only,no xCode level editor
let gameScene = GameScene(size: CGSize(...))
let transition = SKTransition...
gameScene.scaleMode = .aspectFill
view?.presentScene(gameScene,transition: transition)
// With xCode level editor (returns an optional so needs if let
// This will need the GameScene.sks file with the correct custom class set up in the inspector
// Returns optional
if let gameScene = SKScene(fileNamed: "GameScene") {
let transition = SKTransition...
gameScene.scaleMode = .aspectFill
view?.presentScene(gameScene,transition: transition)
}
现在有一些GameManagers的实际例子,我相信你已经知道了其中的一些. 例1 让我们说我们想要一个场景加载管理器.使用静态方法的方法不起作用,因为当你转换为一个时,需要创建一个新的SKScene实例,否则像敌人这样的东西不会重置.使用静态方法的方法意味着每次都使用相同的实例,这是不好的. 我个人使用协议扩展. enum SceneIdentifier: String {
case start = "StartScene"
case game = "GameScene"
case gameOver = "GameOverScene"
}
private let sceneSize = CGSize(width: ...,height: ...)
protocol SceneManager { }
extension SceneManager where Self: SKScene {
// No xCode level editor
func loadScene(withIdentifier identifier: SceneIdentifier) {
let scene: SKScene
switch identifier {
case .start:
scene = StartScene(size: sceneSize)
case .game:
scene = GameScene(size: sceneSize)
case .gameOver:
scene = GameOverScene(size: sceneSize)
}
let transition = SKTransition...
scene.scaleMode = .aspectFill
view?.presentScene(scene,transition: transition)
}
// With xCode level editor
func loadScene(withIdentifier identifier: SceneIdentifier) {
guard let scene = SKScene(fileNamed: identifier.rawValue) else { return }
scene.scaleMode = .aspectFill
let transition = SKTransition...
view?.presentScene(scene,transition: transition)
}
}
现在在3个场景中符合协议 class StartScene: SKScene,SceneManager { ... }
并使用3个枚举案例中的1个作为场景标识符来调用这样的加载方法. loadScene(withIdentifier: .game) 例2 让我们使用Singleton方法为游戏数据制作游戏经理课程. class GameData {
static let shared = GameData()
private init() { } // Private singleton init
var highscore = 0
func updateHighscore(forScore score: Int) {
guard score > highscore else { return }
highscore = score
save()
}
func save() {
// Some code to save the highscore property e.g UserDefaults or by archiving the whole GameData class
}
}
现在你可以说项目的任何地方 GameData.shared.updateHighscore(forScore: SOMESCORE) 您倾向于将Singleton用于只需要1个类实例的事物. Singleton类的一个很好的用法示例是诸如Game Center的助手类,InAppPurchases,GameData等. 例3 用于存储所有场景中可能需要的某些值的通用助手.这使用类似于您尝试的静态方法方法.我喜欢将它用于诸如游戏设置之类的东西,以便将它们放在一个很好的集中位置. class GameHelper {
static let enemySpawnTime: TimeInterval = 5
static let enemyBossHealth = 5
static let playerSpeed = ...
}
在场景中使用它们就像这样 ... = GameHelper.playerSpeed 例4 管理SKSpriteNodes的类,例如敌人 class Enemy: SKSpriteNode {
var health = 5
init(imageNamed: String) {
let texture = SKTexture(imageNamed: imageNamed)
super.init(texture: texture,color: SKColor.clear,size: texture.size())
}
func reduceHealth(by amount: Int) {
health -= amount
}
}
在场景中,您可以使用此助手类创建敌人并调用其上的方法和属性.通过这种方式,您可以轻松添加10个敌人并单独管理他们的健康状况等 let enemy1 = Enemy(imageNamed: "Enemy1") let enemy2 = Enemy(imageNamed: "Enemy2") enemy1.reduceHealth(by: 3) enemy2.reduceHealth(by: 1) 这是一个巨大的答案,但我希望这有帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
