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

2.8 添加难度选择场景

在本部分中,我们将学习如何添加难度选择场景,其中包含多种难度选择按钮,当你按下某个按钮时,相应难度水平的游戏就会被加载进来。

2.8.1 准备工作

为了创建难度级别选择场景,你需要一个自定义精灵,用来显示按钮背景图片以及表示难度级别的数字。首先,我们要创建这些按钮。

在创建好按钮精灵之后,接下来我们要创建一个新场景,用来存放背景图像、场景名称、按钮数组,以及变换场景到指定游戏难度的逻辑。

2.8.2 操作步骤

首先,我们创建一个新的 Cocoa Touch 类,命名为LevelSelectionBtn,它以CCSprite类作为父类。

然后,打开LevelSelectionBtn.h文件,在其中添加如下代码:

#import "CCSprite.h"

@interface LevelSelectionBtn : CCSprite

-(id)initWithFilename:(NSString *) filename
  StartlevelNumber:(int)lvlNum;

@end

上面代码中,我们创建了一个自定义的init函数,它带有两个参数,一个是图像文件名,用来指定按钮背景图像,另一个是整数,显示在按钮背景图像之上,表示难度级别。

这就是LevelSelectionBtn.h文件中的所有代码。在LevelSelectionBtn.m文件中,添加如下代码:

#import "LevelSelectionBtn.h"

@implementation LevelSelectionBtn

-(id)initWithFilename:(NSString *) filename StartlevelNumber:
(int)lvlNum;

{
  if (self = [super initWithImageNamed:filename]) {

    CCLOG(@"Filename: %@ and levelNUmber: %d",
      filename,
      lvlNum);

    CCLabelTTF *textLabel =
      [CCLabelTTF labelWithString:[NSString
      stringWithFormat:@"%d",lvlNum ]
      fontName:@"AmericanTypewriter-Bold"
      fontSize: 12.0f];

    textLabel.position =
      ccp(self.contentSize.width / 2,
      self.contentSize.height / 2);

    textLabel.color = [CCColor colorWithRed:0.1f
      green:0.45f
      blue:0.73f];

    [self addChild:textLabel];

  }

  return self;
}

@end

在自定义的init函数中,首先把参数传入的文件名与游戏难度级别数字在控制台中输出,而后创建一个文本标签,在把整数转换为字符串之后传递给它。

随后,把文本标签放置到当前精灵背景图像的中央,通过把图像的宽度与高度分别除以2得到图像中心点坐标。

由于图像背景与文本都是白色,所以需要把文本颜色修改为蓝色,以便把文本显示出来。

最后,我们把文本添加到当前的类中。

以上就是LevelSelectionBtn类的所有代码。接下来,我们将创建LevelSelectionScene类,并向其中添加精灵按钮与按下按钮所要执行的逻辑。

创建好LevelSelectionScene类之后,在头文件(LevelSelectionScene.h)中添加如下代码:

#import "CCScene.h"

@interface LevelSelectionScene : CCScene{

  NSMutableArray *buttonSpritesArray;
}

+(CCScene*)scene;

@end

请注意,在LevelSelectionScene.h中,除了常见代码之外,我们还创建了一个NSMutableArray类型的变量buttonsSpritesArray,在后面的代码中将会用到它。

接着,在LevelSelectionScene.m文件中,添加如下代码:

#import "LevelSelectionScene.h"
#import "LevelSelectionBtn.h"
#import "GameplayScene.h"

@implementation LevelSelectionScene

+(CCScene*)scene{

    return[[self alloc]init];

}

-(id)init{

  if(self = [super init]){

    CGSize winSize = [[CCDirector sharedDirector]viewSize];

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

    //add text heading for file

    CCLabelTTF *mainmenuLabel = [CCLabelTTF labelWithString:@
    "LevelSelectionScene" fontName:@"AmericanTypewriter-Bold"
fontSize:
    36.0f];
    mainmenuLabel.position = CGPointMake(winSize.width/2, winSize.
height
    * 0.8);
    [self addChild:mainmenuLabel];

    //initialize array
    buttonSpritesArray = [NSMutableArray array];

    int widthCount = 5;
    int heightCount = 5;
    float spacing = 35.0f;

    float halfWidth =
      winSize.width/2 - (widthCount-1) * spacing * 0.5f;
    float halfHeight =
      winSize.height/2 + (heightCount-1) * spacing * 0.5f;

    int levelNum = 1;

    for(int i = 0; i < heightCount; ++i){

      float y = halfHeight - i * spacing;

      for(int j = 0; j < widthCount; ++j){

        float x = halfWidth + j * spacing;

        LevelSelectionBtn* lvlBtn =
          [[LevelSelectionBtnalloc]
          initWithFilename:@"btnBG.png"
          StartlevelNumber:levelNum];
        lvlBtn.position = CGPointMake(x,y);

        lvlBtn.name =
          [NSString stringWithFormat:@"%d",levelNum];

        [self addChild:lvlBtn];

        [buttonSpritesArray addObject: lvlBtn];

        levelNum++;

      }
    }
  }

  return self;
}

在上述代码中,我们先添加了背景图像、场景标题文本,并对NSMutableArray进行了初始化。

然后,我们创建了6个变量,如下所示(见图2-10)。

  • widthCount:列数。
  • heightCount:行数。
  • spacing:精灵按钮之间的距离,防止它们重叠在一起。
  • halfWidth:指从屏幕中心到第一个精灵按钮左上角的距离在x轴上的投影而得到的距离。
  • halfHeight:指从屏幕中心到第一个精灵按钮左上角的距离在y轴上的投影而得到的距离。
  • lvlNum:指显示在精灵按钮上表示难度级别的数字,默认值为1,每次创建一个按钮,其值就会增加1。

在双重循环中,我们将获取每个按钮精灵的x与y坐标。首先,为了获取y值,我们要用halfHeight减去spacing与循环变量i的乘积。由于i的初始值为0,所以最顶行的y值为halfHeigh。

随后,计算按钮位置的x值,计算时我们使用halfWidth加上spacing与j的乘积。每次x值都会被spacing增大。

在获取x与y值之后,创建一个新的LevelSelectionBtn精灵,传入btnBG.png图像,以及lvlNum值,生成按钮精灵。

然后,把之前计算得到的x与y值赋给按钮精灵的position属性。

为了通过数字引用按钮,我们先把levelNum转换为字符串,而后将其赋给按钮精灵的name属性,也就是说引用按钮的数字与其上显示的代表难度级别的数字是一致的。

接下来,把按钮添加到场景之中,同时按钮也会被添加到之前创建的全局按钮精灵数组之中,这是因为后面我们需要对这些图像进行循环。

最后,把levelNum值增加1。

然而,目前我们还没有向精灵按钮添加任何交互行为,当添加交互行为后,每次按下按钮,就会加载相应难度级别的游戏场景。

为了添加触摸交互行为,我们将使用Cocos2d内置的touchBegan函数。在本书的后面章节中,我们将创建更复杂的游戏界面。而这里,我们只使用基本的touchBegan函数。

在同一个文件中,在init函数与@end之间添加如下代码:

-(void)touchBegan:(CCTouch *)touch withEvent:(CCTouchEvent *)event{
  CGPoint location = [touch locationInNode:self];

  for (CCSprite *sprite in buttonSpritesArray)
  {
    if (CGRectContainsPoint(sprite.boundingBox, location)){

      CCLOG(@" you have pressed: %@", sprite.name);

      CCTransition *transition =
        [CCTransition transitionCrossFadeWithDuration:0.20];

      [[CCDirector sharedDirector]replaceScene:[[GameplayScene
      alloc]initWithLevel:sprite.name] withTransition:transition];

      self.userInteractionEnabled = false;

    }
  }
}

每次当我们触碰屏幕时,touchBegan函数都会被调用执行。

因此,当我们触碰屏幕时,应用程序就会获取触碰的位置,并将其保存到location变量中。

而后,使用for in循环遍历添加到buttonSpritesArray数组中的所有按钮精灵。

并且,调用RectContainsPoint函数,检测我们触碰的位置是否位于任一个按钮精灵的矩形框之内。

若是,则在控制台中输出相关信息,告知用户单击了哪个按钮,这样一来,我们就能知道是否加载了正确难度级别的场景。

接着,我们创建了一个淡入淡出过渡效果,并且从当前场景切换到GameplayScene,并使用所单击的按钮精灵名称进行初始化。

最后,我们需要把Boolean型变量userInteractionEnabled设置为false,禁止当前类监听用户的触屏行为。

当然,这需要我们在init函数开始的时候先把userInteractionEnabled设置为TRUE,即在init函数中添加如下粗体代码。

if(self = [super init]){

      self.userInteractionEnabled = TRUE;

      CGSize  winSize = [[CCDirector sharedDirector]viewSize];

2.8.3 工作原理

至此,我们已经编写好了LevelSelectionScene类。但是,我们还需要向MainScene添加一个按钮以便打开LevelSelectionScene。

在MainScene的init函数中添加如下粗体代码。我们主要添加了menuBtn按钮,以及单击它时要调用的函数。

CCButton *playBtn =

        [CCButton buttonWithTitle:nil
        spriteFrame:[CCSpriteFrame frameWithImageNamed:@
        "playBtn_normal.png"]

        highlightedSpriteFrame:[CCSpriteFrame frameWithImageNamed:@
        "playBtn_pressed.png"]

         disabledSpriteFrame:nil];

      [playBtn setTarget:self
        selector:@selector(playBtnPressed:)];

      CCButton *menuBtn = [CCButton buttonWithTitle:nil

        spriteFrame:[CCSpriteFrame
        frameWithImageNamed:@"menuBtn.png"]
        highlightedSpriteFrame:[CCSpriteFrame
        frameWithImageNamed:@"menuBtn.png"]
        disabledSpriteFrame:nil];

      [menuBtn setTarget:self selector:@selector(menuBtnPressed:)];

      CCLayoutBox * btnMenu;
      btnMenu = [[CCLayoutBox alloc] init];
      btnMenu.anchorPoint = ccp(0.5f, 0.5f);
      btnMenu.position =
        CGPointMake(winSize.width/2, winSize.height * 0.5);

      btnMenu.direction = CCLayoutBoxDirectionVertical;
      btnMenu.spacing = 10.0f;

      [btnMenu addChild:menuBtn];
      [btnMenu addChild:playBtn];

      [self addChild:btnMenu];

请不要忘记把menuBtn.png文件从本章的资源文件夹复制到项目中,否则会出现编译错误。

接下来,添加menuBtnPressed函数,一旦menuBtn按钮按下且被释放,它就会被调用执行,代码如下:

-(void)menuBtnPressed:(id)sender{

  CCLOG(@"menu button pressed");
  CCTransition *transition = [CCTransition transitionCrossFadeWith

  Duration:0.20];
  [[CCDirector sharedDirector]replaceScene:[[LevelSelectionScene
  alloc]init] withTransition:transition];
}

现在,MainScene场景如图2-11所示。

单击play按钮之下的菜单按钮,你将看到如下LevelSelectScreen场景,里面罗列出了所有的难度级别,如图2-12所示。

此时,单击任意一个按钮,即可切换到GameplayScene场景,并且把你所单击的代表难度级别的数字一同显示出来。

由于我单击了18号按钮,所以在切换到GameplayScene场景后,显示出的数字为18,如图2-13所示。

时间: 2024-09-17 08:38:50

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

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

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

《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版)》一2.5 添加Gameplay场景

2.5 添加Gameplay场景 当按下play按钮时,游戏应该切换到另一个场景,为此我们需要创建一个新场景,以便从原来的场景切换到新场景.首先,让我们学习一下如何创建一个场景. 2.5.1 准备工作 现在,让我们添加gameplay场景.在第1章中,我们已经学习过如何创建文件,采用相同方法,创建GamePlayScene类文件. 2.5.2 操作步骤 如上,我创建了一个名为GamePlayScene类.GamePlayScene.h文件中包含的代码如下: #import "CCScene.h&

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

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

《Cocos2d 跨平台游戏开发指南(第2版)》一1.6 使用RenderTexture创建精灵

1.6 使用RenderTexture创建精灵 RenderTexture用来创建占位精灵,它们可以用来构建游戏原型.如果你想测试精灵的移动.跳跃代码,但又不想访问精灵,使用RenderTexture是创建精灵既快速又直接的方式. 1.6.1 准备工作 为了创建RenderTexture精灵,我们将编写一个新函数,当我们给出要创建精灵的尺寸与颜色时,它将创建并返回创建好的精灵. 1.6.2 操作步骤 在MainScene.h文件中,之前我们创建了scene函数,在该函数之下,添加如下粗体代码.

《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.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版)》一1.1 内容简介

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