第2章 手动移动
iOS和tvOS 2D游戏开发教程
Ray Wenderlich撰写
如果你完成了第1章的挑战,现在屏幕上已经有一个较大一些的僵尸了,如图2-1所示。
图2-1
注意
如果没有能够完成挑战或者跳过了第1章,也不要担心,直接打开本章的初始工程,从第1章留下的地方继续进行。
当然,你想要让精灵移动起来,而不只是站在那里,这个僵尸也渴望动起来。
在Sprite Kit中,要移动一个精灵,有两种方法:
1.在第1章中,你可能已经注意到了(如果看一下Apple所提供的模板代码的话),可以使用一个叫做动作(action)的概念,让精灵动起来。我们将在第3章中更详细地学习动作。
2.也可以用更为“经典”的方式来移动精灵,这就是随着时间流逝而手动地设置位置。先学习这种方式是很重要的,因为它提供了大多数的控制,并且将帮助你理解动作能做些什么。
然而,要随着时间流逝而设置精灵的位置,需要一个方法,让游戏在运行的时候周期性地调用它。这就引入了一个新的概念,即Sprite Kit游戏循环。
2.1 Sprite Kit游戏循环
游戏就像一个翻书动画一样地工作,如图2-2所示。如果你绘制了一系列连续的图像,当尽快地翻动它们的时候,就会产生移动的错觉。
你所绘制的每一个单个的图片,都叫做一帧(frame)。游戏通常会试图在每秒中绘制30到60帧,以使得动画给人流畅的感觉。这个绘制的速率,叫做帧速率(frame rate),或者更具体地称之为每秒帧数(frames per second,FPS)。默认情况下,Sprite Kit会在游戏的右下角显示这个数据,如图2-3所示。
图2-3
注意
Sprite Kit默认地在屏幕上显示每秒帧数,这一点很方便,因为你在开发自己的游戏的时候,希望能看到FPS,以确保游戏能够很好地运行。理想情况下,我们希望FPS至少达到30。
然而,你只应该关注在一台真实设备上的FPS,因为在模拟器上所得到的FPS会颇为不同。特别是,你的Mac的CPU比iPhone或iPad的处理器要更快,而且Mac拥有更多的内存,但糟糕的是拖慢了模拟的熏染,因此,你不能指望Mac给出任何准确的性能数据。再强调一下,一定在真实设备上测试性能。
除了FPS,Sprite Kit还会显示它在最近一次循环中所渲染的节点数。
可以打开GameViewController.swift,并且把skView.showsFPS和skView.showsNodeCount都设置为false,从而从屏幕去除掉FPS和节点数显示。
在场景背后,Sprite Kit运行了一个无限的循环,我们通常称之为游戏循环(gameloop),如图2-4所示。
图2-4
图2-4示意了在每一帧中,Sprite Kit都做如下的事情:
1.在场景上调用一个名为update()的方法。可以将想要在每一帧中运行的代码放到这里,因此这是更新精灵的位置或旋转精灵的好地方。
2.做一些其他事情。我们将会在后续的各章再次回顾游戏循环,以进一步理解图2-4中剩下的内容。
3.渲染场景。然后,Sprite Kit会绘制场景图中的所有对象,在场景背后使用OpenGL的绘制命令。
Sprite Kit试图尽可能快地绘制帧,最高可达到60FPS。然而,如果update()方法花得时间太长,或者如果Sprite Kit必须绘制的精灵比硬件一次所能处理的精灵更多的话,帧速率可能会下降。
1.保持update()尽可能的快。例如,在这个方法中,要避免那些较慢的算法,因为该方法在每一种帧中都会调用。
2.保持节点数尽可能的少。例如,当节点离屏并且你不再需要它们的时候,将其从场景图删除,这是一种好的做法。
现在,我们已经知道了update()会在每一帧中调用,并且这是更新精灵位置的好地方,让我们来尝试让僵尸动起来。