本节书摘来异步社区《cocos2d 跨平台游戏开发指南(第2版)》一书中的第1章,第1.11节,作者: 【印度】siddharth shekar(谢卡)译者: 武传海 责编: 胡俊英,更多章节内容可以访问云栖社区“异步社区”公众号查看。
在本部分,我们将向游戏中添加视差效果(背景滚动效果),它是游戏中非常流行的一种效果。在视差效果中,相比于背景中的对象,前景中的对象移动得更快,背景中的对象移动得要慢很多,借此产生立体感与运动错觉。
回想一下以前的电影片段,其中的英雄或主角保持静止不动,他们看上去就像在骑马一样,背景不断循环,让人产生错觉,以为英雄在场景中真地向前移动,如图1-31所示。
下面我们将实现一个非常简单的视差效果,其中所有的背景对象(例如,树、灌木、草)都以相同的速度进行移动。为了实现这一效果,我们只要获取背景图像,并让它在一个循环中不断移动即可。
视差效果实现如下:针对背景图像,我们将使用两个精灵,而不是一个精灵,在游戏开始时把它们沿水平方向并排放在一起,如图1-31中的第一幅图所示。第一个精灵可见,第二个精灵在屏幕之外,最初玩家并不能看到它。
当游戏开始时,两个精灵将以一定的速度朝x轴的负方向移动,即向屏幕左侧移动。两个精灵以相同的速度移动,因此当游戏开始时,精灵1将慢慢地向左逐渐移出屏幕,随之精灵2将一点点地在屏幕显现出来。
一旦精灵1完全移出屏幕,它将快速移到精灵2的右侧,即精灵2在游戏开始时所处的位置上。
上述过程将在一个循环中不断重复进行。两个精灵总是向屏幕左侧移动。当一个精灵从屏幕左侧移出屏幕之后,它将立即移动到屏幕右侧,并且继续向左一点点地移动。
在为视差滚动创建资源,编写视差效果代码时,有几点需要各位牢记。首先,当为视差效果创建资源时,所使用的图像应该是连续的。例如,当你观看前面的第二幅图像时,会看到背景中的山脉好像是连续的。即使sprite 1与sprite 2是两幅不同的图像,当把它们放在一起时,它们看上去就像单独的一张图像。同样的现象也出现在山脚下的淡绿色灌木丛上。灌木丛的左半部分位于sprite 1中,右半部分位于sprite 2中,当把它们并排在一起时,它们就会一起组成一棵完整的灌木,让人产生一种它们本来就是一棵单独灌木的错觉。
第二点要注意的是图像之间的接缝。即使把图像无缝衔接在一起,并且让精灵以相同的速度移动,有时在精灵之间仍然可能会观察到有缝隙存在。尽管这不是一个非常普遍的问题,但是在一些框架中它可能会出现。为了防止出现这一问题,你可以把图像稍微拉伸一点点,使图像精灵彼此略微发生重叠,通常玩家觉察不到这种细微的变化。另一个方法是采用手工方式把精灵放置到屏幕精灵的末端,并且必要时做适当的调整,把精灵之间的接缝弥合。
上面这些就是视差滚动效果背后涉及到的主要理论。接下来,让我们一起编写代码,实现简单的视差滚动效果。
首先,采用类似于创建hero类的方式,创建cocostouchclass类型的文件,并且将其命名为parallaxsprite。
打开parallaxsprite.h文件,添加如下代码。
在上述代码中,我们先创建了几个变量,这些变量后面会用到,例如变量_winsize和_center,前一个变量用来获取游戏运行设备的屏幕分辨率的大小,后一个用来计算屏幕中心。
接着,我们又创建了两个ccsprite类型的变量,持有两张图像,在视差效果中用来不断循环。
然后,我们添加了一个_speed变量,用来指定图像移动与循环的速度。
类似于hero类,在parallaxsprite类中,我们也创建了一个initwithfilename函数,它使用给定的文件名对类进行初始化。另外,我们也添加了一个float类型变量,用来指定精灵的速度。
此外,我们还需要一个update函数,它在 1 秒内会被调用60次,用来在类中更新两个精灵的位置。
以上就是parallaxsprite.h文件的所有代码,接下来,转到并打开parallaxsprite.m文件。
在parallaxsprite.m文件中,添加如下代码:
在上述代码中,我们首先实现initwithfilename函数。在initwithfilename函数中,先初始化超类,获取_winsize。接着,通过把窗口的宽度与高度分别除以2计算出屏幕中心,再把speed的值赋给_speed变量。
然后,创建_sprite1和_sprite2两个变量,在spritewithimagenames中,通过filename变量传入文件名字符串。
请注意,_sprite1被放置到屏幕中心,_sprite2被设置到屏幕之外,横坐标与_spirte1相差一个屏幕宽度,纵坐标与_spirte1相同。
最后,把两个精灵添加到类中。
接下来,我们开始实现update函数,添加代码如下:
首先,我们分别为两个精灵计算它们在x轴上的新位置,计算时先获取精灵当前位置的x值,再用它减去精灵的移动速度。之所以这样做,是因为我们希望在每次调用update函数时让精灵沿着x轴的负方向进行移动。
接着,我们把新坐标分别指派给两个精灵,其中x值为上面计算得到的值,y值保持原值不变。
然后,检测图像的右边缘对于玩家是否仍然可见,还是已经移出屏幕左侧之外。如果是这样,我们就把精灵放到脱屏位置上,即纵坐标不变,横坐标与另一个精灵相距一个屏幕宽度,以确保两个精灵之间不会出现缝隙。
在代码中,我们使用了if-else语句,这是因为每次只会有一个精灵移出屏幕左侧边界。
下面让我们一起看一下如何使用parallaxsprite类。在mainscene.h类中,引入parallaxsprite.h文件,创建一个parallaxsprite类型的变量psprite,代码如下:
然后,在mainscene.m文件中,移除本章开始时用来添加背景精灵的代码,添加如下代码:
正如前面我们所做的那样,我们把bg.png文件指派给psprite,此外,我们又指定了速度值为5。
请注意,不必手工调用parallaxsprite类的update函数,每一帧它都会被自动调用执行。而且,你也不必像以前那样调度它,开始时update函数会被自动初始化。
到此为止,我们已经编写好了所有代码,运行代码,我们将会看到如图1-32所示的背景滚动效果。