《Cocos2D权威指南》——2.2 构建游戏场景

2.2 构建游戏场景

在构建游戏场景之前,我们需要将制作该游戏所需要资源文件添加进来。
2.2.1 添加资源目录
找到本书的随书源代码,打开chapter2/resource/arts目录,把需要的图片和声音资源都添加到项目中。右键单击Resource,选择“Add Files to"VerticalShootingGame"…”,如图2-3所示。
浏览chapter2/resource/arts目录,确保选中“Copy items into destination group抯 folder(if needed)”,然后单击“Add”,如图2-4所示。

    ![image](https://yqfile.alicdn.com/57e5a9fb36f81851618ffc1929c9c0d8c0998108.png)
      

2.2.2 添加游戏背景
在一个漆黑的游戏背景上玩游戏,肯定会让人觉得乏味。接下来,我们给游戏添加一个静态背景图片。iPhone屏幕大小是480*320,这里设置竖直放置,图片长度是480,宽度为320。打开HelloWorldLayer.m,找到init方法,在if判断里添加代码清单2-5所示代码。
代码清单2-5 在if判断里添加代码

if( (self=[super init]) ) {
        //1.get screen's size
    CGSizewinSize = [[CCDirector sharedDirector] winSize];
        //2.add background
        CCSprite *bgSprite = [CCSprite spriteWithFile:@"background_1.jpg"];
bgSprite.position = ccp(winSize.width / 2,winSize.height/2);
        [selfaddChild:bgSprite z:0];
    }

按照代码注释中的标号解释这段代码的作用。
1)通过CCDirector对象获得当前设备的屏幕大小。
屏幕大小以point为单位,支持Retina显示的iPhone4以及不支持Retina显示的iPhone 3GS屏幕都为(320,480)。想获得实际像素大小,也可以调用与之相应的像素级API winSizeInPixels。
2)通过sprite的spriteWithFile方法,从background_1.jpg实例化一个精灵,然后通过之前获得的屏幕大小计算出背景精灵图片放置的坐标位置。
因为精灵的坐标定位是相对于它的锚点(anchorPoint)而来,而sprite的anchorPoint为图片的中心点。所以,这里我们取屏幕的中点作为精灵的坐标点。最后,把该背景精灵图片作为当前层的子节点添加进去,Cocos2D框架会自动处理背景图片的渲染。
注意 这里背景图片格式为JPG,而不是大家常见的PNG图片,因为背景图片一般不需要有透明像素。JPG图片和PNG图片最大的区别就是JPG图片没有Alpha通道,因而能够缩小背景图片的大小,并且渲染的速度也会更快一些。
编译并运行,结果如图2-5所示。

2.2.3 添加玩家飞机
好了,是时候添加玩家操控的飞机了。
打开HelloWorldLayer.m文件,在@implementation HelloWorldLayer的上面添加下列枚举定义,如代码清单2-6所示。
代码清单2-6 在@implementation HelloWorldLayer的上面加上枚举定义

enum  {
   kTagPalyer = 1,
};

在init方法中添加背景图片的代码后面添加代码清单2-7所示代码。
代码清单2-7 在init方法中添加背景图片的代码后面添加代码

//3.add player's plane
    CCSprite *playerSprite = [CCSprite spriteWithFile:@"hero_1.png"];
    playerSprite.position = CGPointMake(winSize.width / 2, playerSprite.contentSize.height/2 + 20);
    [selfaddChild:playerSprite z:4 tag:kTagPalyer];

接下来,我们为大家解释代码清单2-7中的这段代码。
首先,从hero_1.png文件初始化一个player精灵,通过屏幕大小与精灵纹理大小的运算,计算放置player精灵的坐标。
注意 这里我们使用的是相对坐标,而不是绝对坐标,这样写有助于代码的可适应性,比如移植到Android平台后,有多种不同分辨率的设备,如果使用绝对坐标定位就会导致界面布局混乱。这里的CGPointMake等价于ccp宏。
然后,调用CCNode的addChild方法,把player精灵加到当前layer中。这里我们使用带tag的addChild版本,方便后面使用getChildByTag提取层中的精灵。
编译并运行结果如图2-6所示。

2.2.4 添加敌机
现在,我们需要添加一些敌机,希望敌机会从屏幕上方随机出现,然后向下俯冲。为了简单起见,这些敌机暂时不会发射子弹,随着学习的深入,玩家可以自行添加这个特性。
步骤1 添加一个CCArray *_enemySprites实例变量。
打开HelloWorldLayer.m文件,在init里代码清单2-7后面初始化此数组,如代码清单2-8所示。
代码清单2-8 在init里初始化数组

//4.init enemy sprites array
_enemySprites = [[CCArray alloc] init];

注意 这里的成员变量命名加了下划线作为前缀,它是一种编码风格,主要用于区别成员变量与局部变量。
步骤2 为了防止忘记释放内存,立刻在dealloc方法里释放掉该数组,如代码清单2-9所示。
代码清单2-9 在dealloc方法里释放掉数组

[_enemySprites release];
_enemySprites = nil;

步骤3 初始化一系列的敌机精灵,并把这些精灵都添加到数组中。
找到init方法,在代码清单2-8所示代码后添加代码清单2-10所示代码。
代码清单2-10 找到init方法添加代码

//5.initialize 10 enemy sprites & add them to _enemySprites array for future useage
const int NUM_OF_ENEMIES = 10;
for (int i=0; i < NUM_OF_ENEMIES; ++i) {
            CCSprite *enemySprite = [CCSprite spriteWithFile:@"enemy1.png"];
enemySprite.position = ccp(0,winSize.height + enemySprite.contentSize.height + 10);
enemySprite.visible = NO;
            [selfaddChild:enemySprite z:4];

            [_enemySpritesaddObject:enemySprite];
        }

这段代码和前面的类似,唯一区别就是在一个循环里初始10个sprite,并且把sprite初始可见性设置为NO,最后把这些sprite都添加到_enemySprites数组中。
如果现在运行项目,结果与上一次编译的没有区别,因为新初始化的敌机精灵是不可见的,同时它们的位置是在设备屏幕上方之外。现在,我们需要一些代码,希望能够隔一段时间有一架敌机随机从上方俯冲下来。
步骤4 打开init方法,在代码清单2-10后添加代码清单2-11所示代码。
代码清单2-11 init方法继续添加代码

//6.spawn enemy after 1.0 sec
        [self performSelector:@selector(spawnEnemy)
                 withObject:nil
                 afterDelay:1.0f];

该方法的作用是:调用完init方法之后,隔1.0秒调用spawnEnemy方法。这种特性非常有用,因为我们有时候希望在触发某个事件之后,不要求马上响应,而是隔一段时间再做处理。
步骤5 定义一些私有方法。
其实在Objective-C世界里不存在真正意义的私有方法,有时为了不让API暴露给客户端程序员,一些类的内部使用的方法和变量需要放在私有扩展里,而不是直接声明在头文件中。
找到HelloWorldLayer.m的@implementation HelloWorldLayer部分,紧跟上面代码清单2-11添加代码清单2-12所示代码。
代码清单2-12 @implementation HelloWorldLayer部分后添加代码

@interface HelloWorldLayer()
-(void) spawnEnemy;
-(CCSprite*) getAvailableEnemySprite;
@end

这里定义一个匿名的Category,把一些私有方法直接放到这里就可以。
步骤6 实现这两个方法。
在代码清单2-12中找到@end,在该行之前添加代码清单2-13所示代码。
代码清单2-13 @end之前添加代码

#pragma mark - private methods
-(void) spawnEnemy{
    //1.
    CGSizewinSize = [CCDirector sharedDirector].winSize;
    CCSprite *enemySprite = [self getAvailableEnemySprite];

    //2.
floatdurationTime = arc4random() % 4 + 1;
idmoveBy = [CCMoveBy actionWithDuration:durationTime
position:ccp(0,-enemySprite.position.y-enemySprite.contentSize.height)];
id callback = [CCCallBlockN actionWithBlock:^(id sender)
    {
        CCSprite *sp = (CCSprite*)sender;
        sp.visible = NO;
        sp.position = ccp(0,winSize.height + sp.contentSize.height + 10);
        CCLOG(@"reset enemy plane!");
    }];
id action = [CCSequence actions:moveBy,callback, nil];

enemySprite.visible = YES;
enemySprite.position = ccp( arc4random() % (int)(winSize.width - enemySprite.contentSize.width) + enemySprite.contentSize.width/2 , enemySprite.position.y);
CCLOG(@"enemySprite x = %f, y = %f",enemySprite.position.x, enemySprite.position.y);
    [enemySpriterunAction:action];

    //3.
    [selfperformSelector:_cmdwithObject:nil afterDelay:arc4random()%3 + 1];

}

-(CCSprite*) getAvailableEnemySprite{
    CCSprite *result = nil;
CCARRAY_FOREACH(_enemySprites, result)
    {
if (!result.visible) {
    break;
        }
    }
return result;
}

我们按照代码注释的序号逐步讲解spawnEnemy方法。
1)通过CCDirector的winSize获得设备的大小(以point为单位);通过调用自定义的getAvailableEnemySprite方法从_enemySprites数组中获取一个还没有飞行的飞机。
2)通过arc4random方法获取一个随机时间,以此时间建立一个CCMoveBy的action,同时计算出此action要移动的偏移量;接着,使用Block建立了一个回调action,最后通过CCSequence action把这两个action串在一起,把需要俯冲的敌机的可见性设置为YES;同时,为了视觉效果,在runAction之前,先设置敌机出现的坐标,改为随机位置出现;在moveBy的动作结束以后,精灵的可见性又变成NO,同时坐标也要发回初始化时的坐标位置。这一切都通过一种神奇函数式编程方式block做到。
3)隔1~4秒调用spawnEnemy方法,此处_cmd参数就是spawnEnemy方法本身。这样,随机地每隔一段时间,就会有一架敌机以不同速度向下俯冲。
编译并运行,我们应该会得到如图2-7所示的效果!

时间: 2024-11-10 00:25:27

《Cocos2D权威指南》——2.2 构建游戏场景的相关文章

《Cocos2D权威指南》——导读

前言 为什么要写这本书 2011年10月5日,秋风萧瑟,阴雨绵绵,在这颗蔚蓝色的美丽星球上,一代传奇伟人乔布斯在亲友的陪伴下安然离去,宛若流星划过天际,空留那辆银色的奔驰SL55AMG在落叶纷飞中孤独守候着曾经的主人.这个世界从此失去了一位引领科技创新的时代领袖. 从1976年在父母的车库中创业开始,乔布斯参与.开创并改变了几个行业-PC.电脑动画.数字音乐.移动互联网.他创办了苹果公司,中途又因某些原因被苹果驱逐.然而在苹果挣扎于濒死的边缘时,他又挺身而出将苹果救活,并把它推到无人可以企及的高

《Cocos2D权威指南》——3.8 垂直射击游戏—加载游戏数据

3.8 垂直射击游戏-加载游戏数据 为了使大家对CCSprite和各相关类的使用有更加直观的印象,下面我们结合前面的游戏示例,使用精灵表单优化游戏性能,同时在游戏开始和结束时添加菜单,让玩家对游戏有更多控制权.当然,在这个示例小游戏中,这种优化是看不出差别的.但这是最佳实践,建议读者以后编写游戏都以这种方式使用精灵. **3.8.1 注释draw方法和背景 ** 首先,在Xcode中打开之前的项目中把draw方法注释掉,同时恢复先前注释掉的添加游戏背景的代码段,编译并运行,如图3-6所示. 注意

《Cocos2D权威指南》——3.3 CCScene场景类

3.3 CCScene场景类 CCScene是CCNode的子类,和CCNode一样,也是一个抽象类.事实上,CCScene和CCNode几乎完全相同,唯一差异在于CCScene的锚点位置默认在屏幕中心.如果打开模板中CCScene.h文件,大家会发现其中只说明CCScene继承自CCNode,并没有任何其他内容.图3-4是典型的游戏场景跳转示意图.当前版本的Cocos2D中,CCScene类基本上没有附加任何逻辑机制和特殊功能.通常建议将CCScene作为其他所有节点的父节点,看作CCLaye

《Cocos2D权威指南》——3.1 Cocos2D节点基础知识

3.1 Cocos2D节点基础知识 在Cocos2D中,CCNode.CCScene和CCLayer这些类是没有视觉呈现的,但它们之间存在一个层级关系.3.1.1 节点层级图 节点层级图是由所有目前活跃的Cocos2D节点组成的一个层级图,又叫场景继承关系图.除了场景本身,每一个节点只有一个父节点,但是可以有任意数量的子节点. 将节点添加到其他节点中时,就在构建节点场景图.图3-1描绘了一个虚拟的游戏场景图,在顶层是一个场景(CCScene)节点,接下来是层(CCLayer)节点. CCLaye

《Cocos2D权威指南》——3.4 CCLayer层类

3.4 CCLayer层类 一个CCLayer是屏幕上可绘制的区域,可以是半透明的,这样就可以看到CCScene下面的其他层.在游戏编程的过程中,开发者大部分时间都需要跟层打交道.如图3-5所示,一个游戏场景包含3个层,背景层.动画层和菜单层. CCLayer直接继承自CCNode,作为精灵节点和其他节点的容器,它同时可以接收触摸输入和加速计输入的信息,前提是上述接收功能已经启用.3.4.1 CCLayer类的作用 CCLayer类的作用主要有三个. (1)其他子节点的容器和组织者 例如对一个层

《Cocos2D权威指南》——3.6 CCSprite精灵类

3.6 CCSprite精灵类 CCSprite是Cocos2D游戏开发中最常用的类,用图片把精灵(sprite)显示在屏幕上. 在游戏开发中,经常会遇到精灵(sprite)这个术语.精灵是一个图像,可以在屏幕上独立地移动.一个精灵可能是玩家角色.敌人,或者是大的背景图像.一般情况下,精灵来自于开发者所准备的PNG或PVRTC图像.一旦图像载入内存,就会将精灵转换成纹理图,从而被iPhone GPU用于在屏幕上渲染.3.6.1 CCSprite类的属性及方法 生成精灵的最简单方法是把图片文件加载

《Cocos2D权威指南》——3.2 CCNode节点类

3.2 CCNode节点类 CCNode是Cocos2D中最重要的类,同时也是所有节点的基类.它是一个抽象类,没有视觉表现,定义了所有节点都通用的属性和方法.在Cocos2D中,所有要绘制到屏幕的对象,或是自身包含要绘制到屏幕中的对象,都属于CCNode类.最重要的几个CCNode类分别是CCScene.CCLayer.CCSprite.CCMenu,这也是我们本章要重点学习的内容.CCNode的主要作用:包含其他的CCNode节点(addChild.getChildByTag.removeCh

《Cocos2D-x权威指南》——3.3 场景类

3.3 场景类 CCScene类是CCNode的子类.和CCNode相比,它只是添加了一个特性,那就是拥有自己的锚点,位置在屏幕的正中央.除此之外,它目前还没有额外的功能,只是一个抽象的概念. 3.1节中介绍CCNode类时,把屏幕上所有显示对象的父节点设置为我们定义的节点,这个父节点的角色一般由场景承担.CCScene类的继承关系如图3-9所示. 可以看到,CCScene类有CCTransitionScene(切换场景类),并且CCTransitionScene类有很多子类,这些类都用于切换场

《Cocos2D权威指南》——第2章 你的第一款iPhone游戏—垂直射击游戏 2.1 准备工作

第2章 你的第一款iPhone游戏-垂直射击游戏 本章我们将以一个垂直射击游戏为题材,带领大家动手制作一个简单的游戏,主要目的是让大家对Cocos2D开发游戏有一个感性的认识,同时体验Cocos2D的强大以及易用性.之后的章节将引入更多的游戏元素,逐步完善此游戏. 2.1 准备工作 作为开发者,首先需要有一台iOS设备,iPhone.iPod Touch或者iPad都可以:其次要拥有开发者账号,按照第1章介绍的方法下载并安装开发者证书,这样才可以把游戏编译运行到真机上.为什么非要真机呢?接下来向