建置应用程序很不简单,但是做游戏其实更难,特别是开发者本身不是一个玩家,虽然每当我开始学习游戏编程时,都会这样对自己说,最终却都退却了。今年,我终于意识到我做错了:过去太专注在建立一个大的东西,因此从一开始就害怕眼前的巨大任务,但应该是从小的部分开始,保持愉快的开发步调。我们想制作有趣的游戏,所以如果没有享受创造它们的乐趣,那如何抓得到重点呢?因此,我得到了启发:你不必从头开始创建一个完整的游戏,你只需要想到一些简易的任务来起头,其余的就会自然发展下去。
在这个系列教程中,你会面对一个简单的挑战:藉由SpriteKit与Apple的2D游戏框架,当你点击屏幕时,将会同时让标签移动,缩放和旋转,以下为本文读者需要了解的概念:
Scenes
Nodes
Labels
Points
Gesture recognisers
Actions
这些概念实际上是相当丰富的,所以让我们开始吧!
本系列教程介绍
在本系列的第一个部分中,透过将标签(labels)置中在屏幕画面的动作,来了解关于场景(scenes)、节点(nodes)、标签(labels)和坐标点(points)的所有知识。第二部分藉由移动,缩放和旋转标签,来教你关于手势识别和动作的全部用法。
你可能会想,为什么我会在系列教程的第一部分,教你如何将标签置中。这不是很容易吗?
学习显示并置中卷标的动作,是刚开始学习场景和节点并且将它们融会贯通最简单的方法。在学习进阶内容(如手势识别和动作)之前,先了解如何定位标签,以及操作节点和场景是非常重要的。
如果你没有理解和正确地掌握基本知识,那介绍更进阶的东西(如碰撞检测和物理动作)也是没有意义的。让我们从基础开始吧!
你的第一个SpriteKit专案
学习一个framework最好的方法就是使用它。所以,现在来创建我们第一个SpriteKit项目。请先启动Xcode并从iOS项目选单中选择Game的模板(template),如下所示:
下一步进入项目设定:
在这里,最重要的事情是选择Game Technology项目字段-确认你在对应的选单中选择了SpriteKit:
现在请储存你的项目,完成 – 该是整理它的时候了!
整理你的项目
游戏模板会提供样板程序代码便利你的初始工作,但读者将从头开始编写所有内容,因此,请清除GameScene.swift和GameViewController.swift文件中的所有内容。
GameScene.sks和Actions.sks文件可帮助你更直观的设计场景和动作。但是,先以编程方式创建它们会更容易理解,所以现在请先删除这两个文件 – 你将在另一个教程学习如何使用SpriteKit编辑器。请确保在提示时将文件永久移动到垃圾桶,而不是仅仅从项目中删除它们的引用:
这些就是我们前期需要做的项目整理工作 – 编写程序代码的时候到了!
建立视图控制器
因为我们已经清空GameViewController.swift,我们现在将从头开始创建视图控制器(view controller),将以下这段程序代码添加到GameViewController.swift文件,开始我们的编码动作:
import SpriteKit class GameViewController: UIViewController { }
这里我们import SpriteKit的框架进来,并且进行类别宣告,该类别是一个标准的视图控制器,它的主要作用是在控制器的视图加载后呈现游戏场景,因此将viewDidLoad()方法添加到class里面:
override func viewDidLoad() { let scene = GameScene(size: view.frame.size) let skView = view as! SKView skView.presentScene(scene) }
让我们一步一步介绍上述程序代码的意义:
Line #1 – 你覆写了视图控制器里面的viewDidLoad()方法 – 它在视图控制器加载到内存后立即运行。
Line #2 – 你使用GameScene类别内指定的初始化方法(designated initialiser)创建场景:它贴满整个屏幕画面,因此它与控制器视图的frame相同大小。
注意:此时Xcode会显示错误:Use of unresolved identifier “GameScene”,因为您尚未实现GameScene类别,接下来我们会尽快解决这个问题。
Line #3 – 强制将控制器的视图转型为SpriteKit视图 – 这是唯一呈现SpriteKit内容的视图类型。在这种情况下,因为我们正在使用游戏模板,所以转型动作大多会是成功的,因此将控制器视图的类别预设为SKView,而不是storyboard里面的UIView。
Line #4 – 在屏幕画面上呈现游戏场景(scene)。在一个完整的游戏中,你将透过转换来呈现多个场景,但现在为了保持项目的简洁,将只会使用一个。
以上为视图控制器的设置作业。 现在,让我们继续创建一个场景。
创建一个场景
同样,我们将GameScene.swift文件的内容清空。我将在这里教你如何从头开始创建它。请先将以下程序代码添加到GameScene.swift文件中,开始我们的建置作业:
import SpriteKit class GameScene: SKScene { }
你将SpriteKit框架import进来,并且定义了类别,它是标准SpriteKit场景的子类别(即SKScene)。前一个错误已经被修复,所以构建和运行项目,查看你场景的呈现结果:
注意:我使用iPhone 5s仿真器来运行这个项目,读者可以随意挑选你最喜欢的仿真器。
场景看起来是空的,除了本身做为场景之外,它没有其他节点连接到它。Okay,现在停止这个应用程序,并返回到编辑器,添加第一个节点到这个场景!
替场景添加一个节点
第一个节点只是一个简单的标签(label)。在GameScene类别中,宣告一个名为label的label属性:
let label = SKLabelNode(text: "Hello SpriteKit!")
当游戏需要在某一时点显示文本(text),SpriteKit提供了一个类别名为SKLabelNode来显示文本卷标。上面的代码只是实例化一个SKLabelNode对象,并将其初始字符串设置为Hello SpriteKit!,但是,除非在视图控制器呈现场景时,将其添加到场景的节点树,否则不会发生任何事情。换句话说,您必须提供额外的实作,才能在屏幕画面上显示卷标。
现在向类别添加一个名为didMove(to:)的新方法:
override func didMove(to view: SKView) { addChild(label) }
我们覆写场景的didMove(to:)方法。它是在场景由其相应的视图呈现之后立即运行的方法。在方法实作中,我们调用addChild方法将标签做为子节点添加到场景的节点树。
现在,再次运行这个应用程序,你应该会在屏幕画面上看到卷标:
但是这边出现一个问题:这个标签被切掉了,因为它的位置默认值被设置为(0,0)。
好的,现在让我们继续本教程的最后一部分,更改一些设定让卷标能置中显示。
将标签置中
在标签添加到场景之前,将下列这一行程序代码添加到didMove(to:)方法中:
label.position = CGPoint(x: view.frame.width / 2, y: view.frame.height / 2)
你可以使用视图的宽度和高度来确定标签的坐标,藉此将其放置在画面中心。屏幕的尺寸不是写死的,所以标签可以正确放置在所有iPhone仿真器上。
运行并且瞧瞧画面的显示结果!卷标应该会在屏幕上完美呈现。
除了卷标的position属性,还有很多属性可以调整更改卷标样式。举例来说,你可以更改其字体大小,类型和颜色,如下所示:
label.fontSize = 45 label.fontColor = SKColor.yellow label.fontName = "Avenir"
结论
本教程的第一部分已经接近尾声 – 读者已经在SpriteKit使用场景、节点、标签和坐标点,让卷标在屏幕画面上居中显示。 在下一部分中,你将使用手势辨识器(gesture recognizers)和动作(actions),移动、缩放和旋转标签。敬请关注,在此期间如果读者有任何问题或问题,请让我知道。
以供参考,读者可以在GitHub下载完整专案。