致命错误:使用未实现的初始化程序'init(size:)'用于类

12

我在不同设备上测试我的应用程序时,发现精灵的移动非常不一致(在某些设备上比其他设备运行得更快)。我找到了这篇帖子,并按照说明从所有的SKScene中删除了大小参数,然后我收到了以下错误:

fatal error: use of unimplemented initializer 'init(size:)' for class 'SuperGame.PosterScene'

请查看下面的我的PosterScene类和调用它的GameViewController类。 PosterScene
class PosterScene: SKScene {

 override init(){
    super.init()

    let posterImage = SKSpriteNode(imageNamed: "poster")
    posterImage.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
    self.addChild(posterImage)

    let sequence = SKAction.sequence([  SKAction.wait(forDuration: 3.0), SKAction.run({ self.changeToMainMenuScene() }) ])

    self.run(sequence)

}

func changeToMainMenuScene  ()  {

    let mainMenuScene = MainMenuScene()
    self.view!.presentScene(mainMenuScene)

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

游戏视图控制器:

class GameViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    let skView = self.view as? SKView

    if skView?.scene == nil  {
        skView?.showsFPS = true
        skView?.showsNodeCount = true
        skView?.showsPhysics = true
        skView?.ignoresSiblingOrder = false

        //starting the game with the Poster Scene
        let posterScene = PosterScene()
        posterScene.scaleMode = .resizeFill
        skView?.presentScene(posterScene)
    }

}

override var shouldAutorotate : Bool {
    return true
}

override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return UIInterfaceOrientationMask.allButUpsideDown
    } else {
        return UIInterfaceOrientationMask.all
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override var prefersStatusBarHidden : Bool {
    return true
}

required init(coder aDecoder: NSCoder!) {
    super.init(coder: aDecoder)!
}
}

你应该重写 init(size:),而不是 init() - dan
@dan,我最初使用的是init(size:),它没有出现任何错误,但是在不同设备上精灵速度不同。为了解决这个问题,我按照链接中的建议删除了大小参数。 - iGetIt
@iGetIt,现在我可以在代码中看到这个问题,你误解了我的意思,我并没有说不要使用size:,我是说不要使用size:view.frame.size。如果你必须100%在代码中工作(我不建议这样做,将设计和功能分开会使生活变得轻松1000倍),那么你应该选择一个静态大小,而不是基于视图的大小,因为目标是在所有设备上进行缩放,以便看起来相同。 - Knight0fDragon
2个回答

3
您让我来看这个问题。
您的游戏在不同设备上感觉不一致,因为在您的GameViewController中将场景比例模式设置为.resizeFill。在大多数情况下,默认的.aspectFill设置是最佳选项。
关于错误消息,当您不使用xCode级别编辑器时,在init方法中需要给场景一个大小,例如:
let scene = GameScene(size: CGSize(width: ..., height: ...))

基本上有两种尺寸选项:
1)将场景大小设置为iPad,这是我个人的做法。这也是Apple在DemoBots中使用的尺寸,也是xCode 7的默认设置。因此,场景大小为1024x768(横屏)或768x1024(竖屏)。
我设计游戏区域时以iPhone为主要考虑因素,在iPad上只需显示更多背景,通常是地面和天空。这就是我喜欢玩的许多热门游戏所采用的方式,例如:《Modern Combat 5》、《Limbo》、《Altos Adventure》、《Leos Fortune》、《The Line Zen》、《Tower Dash》。
2)将场景大小设置为iPhone,并在iPhone上显示更多背景,在iPad上显示较少的背景,例如Lumino City。因此,场景大小将是xCode 8使用的尺寸,即1334x750(横屏)或750x1334(竖屏)。
这样,您的游戏在所有设备上都应该感觉一致。您唯一需要做的事情可能就是在iPad和iPhone之间微调一些UI,例如按钮位置。
希望对您有所帮助。

1
是的,绝对同意。在改变我的方法之前,我花了8个月和2个游戏的时间手动完成它而没有任何裁剪(.resizeFill)。要使其在所有设备上具有一致的体验是疯狂的。正如你所说,这也扼杀了我的创造性体验,因为我一半的时间都在为我没有测试过的设备调整东西,而不是改进实际的游戏本身。 - crashoverride777
非常正确。感谢您的好话,就像帮助别人一样。当我刚开始使用SpriteKit和Swift时,我也曾处于同样的困境,并始终感激那些在那个时候花时间回答我简单而可能愚蠢的问题的人们。 - crashoverride777
@crashoverride777,你说你的游戏区域是从中心设计的。这是否意味着你的(0,0)是中心? - iGetIt
取决于你的锚点是什么,我通常使用frame.midX/frame.midY。我所说的从中心设计是指你必须牢记在你裁剪的设备(无论是iPhone还是iPad)上的死区。举个例子,如果你制作横向游戏并使用iPad设置(1024x768),你会在iPad上拥有更多的边框顶部和底部。因此,如果你将某些东西放在frame.maxY或frame.minY处,你在iPhone上就看不到它了,因为它被裁剪了。所以你需要像frame.maxY - 200这样表达,才能在iPhone上看到它。这就是我所说的从中心设计的死区。 - crashoverride777
@crashoverride777,如果您能提供任何已经实现了您所解释的iPhone和iPad尺寸的Github项目链接,我将不胜感激。 - iGetIt
显示剩余12条评论

1
这是您的代码布局应该如何。如您所见,我将场景设计为iPhone 6的大小。这意味着在所有其他手机上,图像将会缩放(但您仍然可以看到所有内容),但在6上看起来完美。在iPad上,由于iPad是3:4而不是9:16,图像的顶部和底部各被裁剪了12.5%。
class GameViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    let skView = self.view as? SKView

    if skView?.scene == nil  {
        skView?.showsFPS = true
        skView?.showsNodeCount = true
        skView?.showsPhysics = true
        skView?.ignoresSiblingOrder = false

        //starting the game with the Poster Scene
        let posterScene = PosterScene(size:CGSize(width:375,height:667))
        posterScene.scaleMode = .aspectFill
        skView?.presentScene(posterScene)
    }

}

override var shouldAutorotate : Bool {
    return true
}

override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return UIInterfaceOrientationMask.allButUpsideDown
    } else {
        return UIInterfaceOrientationMask.all
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override var prefersStatusBarHidden : Bool {
    return true
}

required init(coder aDecoder: NSCoder!) {
    super.init(coder: aDecoder)!
}
}

并且

class PosterScene: SKScene {

 override init(size:CGSize){
    super.init(size:size)
    self.anchorPoint = CGPoint(x:0.5,y:0.5) //let's put 0,0 at the center of the screen
    let posterImage = SKSpriteNode(imageNamed: "poster")
    posterImage.position = CGPoint.zero
    self.addChild(posterImage)

    let sequence = SKAction.sequence([  SKAction.wait(forDuration: 3.0), SKAction.run({ self.changeToMainMenuScene() }) ])

    self.run(sequence)

}

func changeToMainMenuScene  ()  {

    let mainMenuScene = MainMenuScene()
    self.view!.presentScene(mainMenuScene)

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

你只需要为一个尺寸进行设计,而不是五个,这意味着你将在所有设备上获得一致的结果。如果你的物理学有误,这意味着你没有为一个设备进行设计。 - Knight0fDragon
@2x@3x是不同的问题,你可以在一个尺寸下设计游戏,iOS会在高分辨率屏幕上选择更高分辨率的图形,你永远不必担心它。 - Knight0fDragon
3
@Knight0fDragon,我刚才阅读了这篇文章和其中链接的内容以及所有评论。就个人而言,我更喜欢使用iGetIt最初处理位置和大小的方式,并且从情况看来,他将不得不做出大量更改来实现你的建议。我相信应该有一种更简单的方法让他获得一致的精灵移动。可以通过找到一个基于屏幕尺寸的因子来乘以精灵速度或类似的东西。这是我的意见。 - chronos
1
@chronos,另外,现在你还需要担心不同设备上的纵横比。当一个精灵斜向移动时,在不同设备上会呈现怎样的效果呢?它可能在iPad上看起来很棒,但在iPhone上却糟糕透顶,因为你的精灵向上移动得更多,而不是向右移动。有太多要考虑的事情,这简直太疯狂了,这就是游戏开发如此迷人之处,有如此多的问题需要解决。 - Knight0fDragon
PosterScene设置了一个背景图片。当我使用PosterScene(size: CGSize(width:375,height:667))时,这个图片似乎被放大了。 - iGetIt
显示剩余36条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接