《Cocos2d 跨平台游戏开发指南(第2版)》一1.11 添加视差效果

1.11 添加视差效果

在本部分,我们将向游戏中添加视差效果(背景滚动效果),它是游戏中非常流行的一种效果。在视差效果中,相比于背景中的对象,前景中的对象移动得更快,背景中的对象移动得要慢很多,借此产生立体感与运动错觉。

1.11.1 准备工作

回想一下以前的电影片段,其中的英雄或主角保持静止不动,他们看上去就像在骑马一样,背景不断循环,让人产生错觉,以为英雄在场景中真地向前移动,如图1-31所示。

下面我们将实现一个非常简单的视差效果,其中所有的背景对象(例如,树、灌木、草)都以相同的速度进行移动。为了实现这一效果,我们只要获取背景图像,并让它在一个循环中不断移动即可。

视差效果实现如下:针对背景图像,我们将使用两个精灵,而不是一个精灵,在游戏开始时把它们沿水平方向并排放在一起,如图1-31中的第一幅图所示。第一个精灵可见,第二个精灵在屏幕之外,最初玩家并不能看到它。

当游戏开始时,两个精灵将以一定的速度朝x轴的负方向移动,即向屏幕左侧移动。两个精灵以相同的速度移动,因此当游戏开始时,精灵1将慢慢地向左逐渐移出屏幕,随之精灵2将一点点地在屏幕显现出来。

一旦精灵1完全移出屏幕,它将快速移到精灵2的右侧,即精灵2在游戏开始时所处的位置上。

上述过程将在一个循环中不断重复进行。两个精灵总是向屏幕左侧移动。当一个精灵从屏幕左侧移出屏幕之后,它将立即移动到屏幕右侧,并且继续向左一点点地移动。

在为视差滚动创建资源,编写视差效果代码时,有几点需要各位牢记。首先,当为视差效果创建资源时,所使用的图像应该是连续的。例如,当你观看前面的第二幅图像时,会看到背景中的山脉好像是连续的。即使Sprite 1与Sprite 2是两幅不同的图像,当把它们放在一起时,它们看上去就像单独的一张图像。同样的现象也出现在山脚下的淡绿色灌木丛上。灌木丛的左半部分位于Sprite 1中,右半部分位于Sprite 2中,当把它们并排在一起时,它们就会一起组成一棵完整的灌木,让人产生一种它们本来就是一棵单独灌木的错觉。

第二点要注意的是图像之间的接缝。即使把图像无缝衔接在一起,并且让精灵以相同的速度移动,有时在精灵之间仍然可能会观察到有缝隙存在。尽管这不是一个非常普遍的问题,但是在一些框架中它可能会出现。为了防止出现这一问题,你可以把图像稍微拉伸一点点,使图像精灵彼此略微发生重叠,通常玩家觉察不到这种细微的变化。另一个方法是采用手工方式把精灵放置到屏幕精灵的末端,并且必要时做适当的调整,把精灵之间的接缝弥合。

上面这些就是视差滚动效果背后涉及到的主要理论。接下来,让我们一起编写代码,实现简单的视差滚动效果。

1.11.2 操作步骤

首先,采用类似于创建Hero类的方式,创建CocosTouchClass类型的文件,并且将其命名为ParallaxSprite。

打开ParallaxSprite.h文件,添加如下代码。

#import "CCSprite.h"

@interface ParallaxSprite :CCSprite{

  CGSize _winSize;
  CGPoint _center;
  CCSprite _sprite1, _sprite2;
  float _speed;
}

-(id)initWithFilename:(NSString *)filename Speed:(float)speed;
-(void)update:(CCTime)delta;

@end

在上述代码中,我们先创建了几个变量,这些变量后面会用到,例如变量_winSize和_center,前一个变量用来获取游戏运行设备的屏幕分辨率的大小,后一个用来计算屏幕中心。

接着,我们又创建了两个CCSprite类型的变量,持有两张图像,在视差效果中用来不断循环。

然后,我们添加了一个_speed变量,用来指定图像移动与循环的速度。

类似于Hero类,在ParallaxSprite类中,我们也创建了一个initWithFilename函数,它使用给定的文件名对类进行初始化。另外,我们也添加了一个float类型变量,用来指定精灵的速度。

此外,我们还需要一个update函数,它在 1 秒内会被调用60次,用来在类中更新两个精灵的位置。

以上就是ParallaxSprite.h文件的所有代码,接下来,转到并打开ParallaxSprite.m文件。

在ParallaxSprite.m文件中,添加如下代码:

#import "ParallaxSprite.h"

@implementation ParallaxSprite

-(id)initWithFilename:(NSString *)filename Speed:(float)speed;{

  if(self = [super init]){

    NSLog(@"[parallaxSprite] (init) ");

    _winSize = [[CCDirectorsharedDirector]viewSize];

    _center = CGPointMake(_winSize.width/2, _winSize.height/2);

    _speed = speed;

    _sprite1 = [CCSpritespriteWithImageNamed:filename];
    _sprite1.position = _center;
    [selfaddChild:_sprite1];

    _sprite2 = [CCSpritespriteWithImageNamed:filename];
    _sprite2.position = CGPointMake(_sprite1.position.x + _winSize.
width
, _center.y);
    [selfaddChild:_sprite2];

  }
return self;
}

在上述代码中,我们首先实现initWithFilename函数。在initWithFilename函数中,先初始化超类,获取_winSize。接着,通过把窗口的宽度与高度分别除以2计算出屏幕中心,再把speed的值赋给_speed变量。

然后,创建_sprite1和_sprite2两个变量,在spriteWithImageNames中,通过filename变量传入文件名字符串。

请注意,_sprite1被放置到屏幕中心,_sprite2被设置到屏幕之外,横坐标与_spirte1相差一个屏幕宽度,纵坐标与_spirte1相同。

最后,把两个精灵添加到类中。

接下来,我们开始实现update函数,添加代码如下:

-(void)update:(CCTime)delta{

  floatxPos1 = _sprite1.position.x - _speed;
  floatxPos2 = _sprite2.position.x - _speed;

  _sprite1.position = CGPointMake(xPos1, _sprite1.position.y);
  _sprite2.position = CGPointMake(xPos2, _sprite1.position.y);

  if(xPos1 + _winSize.width/2 <= 0){

    _sprite1.position = CGPointMake(_sprite2.position.x +
_winSize.width, _center.y);

}else if(xPos2 + _winSize.width/2 <= 0){

    _sprite2.position = CGPointMake(_sprite1.position.x + _winSize.
width
    , _center.y);
  }
}

@end

首先,我们分别为两个精灵计算它们在x轴上的新位置,计算时先获取精灵当前位置的x值,再用它减去精灵的移动速度。之所以这样做,是因为我们希望在每次调用update函数时让精灵沿着x轴的负方向进行移动。

接着,我们把新坐标分别指派给两个精灵,其中x值为上面计算得到的值,y值保持原值不变。

然后,检测图像的右边缘对于玩家是否仍然可见,还是已经移出屏幕左侧之外。如果是这样,我们就把精灵放到脱屏位置上,即纵坐标不变,横坐标与另一个精灵相距一个屏幕宽度,以确保两个精灵之间不会出现缝隙。

在代码中,我们使用了if-else语句,这是因为每次只会有一个精灵移出屏幕左侧边界。

1.11.3 工作原理

下面让我们一起看一下如何使用ParallaxSprite类。在MainScene.h类中,引入ParallaxSprite.h文件,创建一个ParallaxSprite类型的变量pSprite,代码如下:

#import "Hero.h"
#import "ParallaxSprite.h"

@interface MainScene :CCNode{

CGSizewinSize;
    Hero* hero;
ParallaxSprite* pSprite;

}

然后,在MainScene.m文件中,移除本章开始时用来添加背景精灵的代码,添加如下代码:

//Basic CCSprite - Background Image - REMOVE
//CCSprite* backgroundImage = [CCSpritespriteWithImageNamed:@"Bg.
png"];
//backgroundImage.position = CGPointMake(winSize.width/2,
winSize.height/2);
//[self addChild:backgroundImage];

//Parallax Background Sprite - ADD
pSprite = [[ParallaxSpritealloc]initWithFilename:@"Bg.png" Speed:5];
[selfaddChild:pSprite];

正如前面我们所做的那样,我们把Bg.png文件指派给pSprite,此外,我们又指定了速度值为5。

请注意,不必手工调用ParallaxSprite类的update函数,每一帧它都会被自动调用执行。而且,你也不必像以前那样调度它,开始时update函数会被自动初始化。

到此为止,我们已经编写好了所有代码,运行代码,我们将会看到如图1-32所示的背景滚动效果。

时间: 2024-12-02 01:30:10

《Cocos2d 跨平台游戏开发指南(第2版)》一1.11 添加视差效果的相关文章

《Cocos2d 跨平台游戏开发指南(第2版)》一导读

前 言 Cocos2d 跨平台游戏开发指南(第2版)自从2007年创始以来,Apple App Store一直保持着持续增长的势头,每天平均约有500个App提交.其中,大约80%的App是游戏.形成这种局面的部分原因是Apple构建了一个非常棒的生态系统,免费提供操作系统和IDE开发环境,便于普通开发者接触并使用它们.另一部分原因在于Cocos2d框架,它是目前应用最广泛的免费iOS游戏开发框架之一,借助它,开发者能够更方便地开发游戏和App应用. SpriteBuilder把Cocos2d集

《Cocos2d 跨平台游戏开发指南(第2版)》一第1章 精灵与动画

下载并安装Cocos2d 2D坐标系统 访问主场景(MainScene) 添加精灵到场景 使用RenderTexture创建精灵 创建自定义精灵类 动画精灵 添加动作到精灵 绘制gIPrimitives 添加视差效果

《Cocos2d 跨平台游戏开发指南(第2版)》一2.3 使用CCLabel添加文本

2.3 使用CCLabel添加文本 在这一部分,我们将学习如何向场景中添加文本.在Cocos2d中,有两种方法可以用来向场景中添加文本:一种是使用CCLabelTTF类,另一种是使用CCLabelBMFont类.我们将在本书第9章的Glyph Designer一节中讲解CCLabelBMFont,本部分我们只讲解CCLabels,了解一下它们是如何工作的. 2.3.1 准备工作 CCLabelTTF使用Mac系统中现有的系统字体.在使用CCLabelTTF类时,我们只需指定要使用的字体名称.希望

《Cocos2d 跨平台游戏开发指南(第2版)》一1.1 内容简介

1.1 内容简介 在本章中,我们将介绍有关Cocos2d框架的一些基本知识,以便帮助各位了解相关概念.首先,了解下载并安装SpriteBuilder/Cocos2d的过程,然后讲解Cocos2d中使用的2D坐标系统. 在学完基础内容之后,接着介绍精灵的基本属性以及如何把它们添加到场景之中.我们将了解一下如何把一幅图像添加到精灵对象,并讨论如何创建一个占位精灵,以便在游戏原型阶段测试基本的游戏机制与冲突.然后,再学习如何使用gIPrimitives创建基本形状.在此之后,我们将讨论如何使用动作对精

《Cocos2d 跨平台游戏开发指南(第2版)》一1.3 2D坐标系统

1.3 2D坐标系统 在2D游戏开发中,我们只需考虑两种坐标系统,一种是屏幕坐标系统,另一种是对象坐标系统. 在2D中,无论何时,当我们把一个对象放置到屏幕上时,总是要考虑对象离屏幕的左下角有多远.这是因为坐标原点位于屏幕的左下角,而非屏幕的中心.正因如此,如果把一个精灵放置到屏幕上,并且未修过它的位置时,它将在屏幕的左下角被创建出来.请记住,屏幕坐标原点[(0,0)]位于屏幕的左下角.如图1-11所示,如果你想把精灵放置到屏幕的中心,需要把精灵位置设置为位置属性中宽与高的一半.由于所有对象的位

《Cocos2d 跨平台游戏开发指南(第2版)》一2.9 滚动难度级别选择场景

2.9 滚动难度级别选择场景 假如你的游戏有多个难度级别,例如有20个等级,那么只用一个单独的难度级别选择场景来显示所有的级别选择按钮是可以的.但是,要是有更多等级呢?在本部分中,我们将修改前面编写的代码,创建一个节点,并进行初始化,从而产生一个可以滚动的难度级别选择场景. 2.9.1 准备工作 我们将创建一个新类,将其命名为LevelSelectionLayer,它继承自CCNode类.然后,把我们在前面添加到LevelSelectionScene中的所有代码复制到其中.这样一来,我们就有了一

《Cocos2d 跨平台游戏开发指南(第2版)》一1.8 让精灵动起来

1.8 让精灵动起来 在这一部分,我们将讨论如何让精灵动起来.我们将修改自定义精灵类,让角色动起来.通过提供带有许多图像的Cocos2D,并使之循环通过这些图像,即可产生动画效果. 1.8.1 准备工作 为了让精灵动起来,我们将添加 4 帧动画,并将其应用到 hero 精灵类,通过使用repeatForever动作让图像循环动起来.在下一部分,我们将详细讲解有关动作的内容. 1.8.2 操作步骤 在本章的Resources文件夹中,含有hero帧的普通.ipad.ipadhd版本图像.我们把所有

《Cocos2d 跨平台游戏开发指南(第2版)》一1.2 下载并安装Coscos2d

1.2 下载并安装Coscos2d 在创建并运行Cocos2d项目之前,必须先安装SpriteBuilder与Xcode.在本部分中,我们将简单地介绍一下如何安装它们. 1.2.1 准备工作 首先到http://cocos2d.spritebuilder.com下载Coscos2d,并进行安装. 目前Spritebuilder已成为Cocos2d的官方安装程序.单击Cocos2d-SpriteBuilder installer链接,随后打开Mac App Store Preview页面,而后完成

《Cocos2d 跨平台游戏开发指南(第2版)》一2.8 添加难度选择场景

2.8 添加难度选择场景 在本部分中,我们将学习如何添加难度选择场景,其中包含多种难度选择按钮,当你按下某个按钮时,相应难度水平的游戏就会被加载进来. 2.8.1 准备工作 为了创建难度级别选择场景,你需要一个自定义精灵,用来显示按钮背景图片以及表示难度级别的数字.首先,我们要创建这些按钮. 在创建好按钮精灵之后,接下来我们要创建一个新场景,用来存放背景图像.场景名称.按钮数组,以及变换场景到指定游戏难度的逻辑. 2.8.2 操作步骤 首先,我们创建一个新的 Cocoa Touch 类,命名为L