天天看点

《Cocos2D权威指南》——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所示。

2.2.2 添加游戏背景

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

代码清单2-5 在if判断里添加代码

按照代码注释中的标号解释这段代码的作用。

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所示。

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

2.2.3 添加玩家飞机

好了,是时候添加玩家操控的飞机了。

打开helloworldlayer.m文件,在@implementation helloworldlayer的上面添加下列枚举定义,如代码清单2-6所示。

代码清单2-6 在@implementation helloworldlayer的上面加上枚举定义

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

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

接下来,我们为大家解释代码清单2-7中的这段代码。

首先,从hero_1.png文件初始化一个player精灵,通过屏幕大小与精灵纹理大小的运算,计算放置player精灵的坐标。

注意 这里我们使用的是相对坐标,而不是绝对坐标,这样写有助于代码的可适应性,比如移植到android平台后,有多种不同分辨率的设备,如果使用绝对坐标定位就会导致界面布局混乱。这里的cgpointmake等价于ccp宏。

然后,调用ccnode的addchild方法,把player精灵加到当前layer中。这里我们使用带tag的addchild版本,方便后面使用getchildbytag提取层中的精灵。

编译并运行结果如图2-6所示。

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

2.2.4 添加敌机

现在,我们需要添加一些敌机,希望敌机会从屏幕上方随机出现,然后向下俯冲。为了简单起见,这些敌机暂时不会发射子弹,随着学习的深入,玩家可以自行添加这个特性。

步骤1 添加一个ccarray *_enemysprites实例变量。

打开helloworldlayer.m文件,在init里代码清单2-7后面初始化此数组,如代码清单2-8所示。

代码清单2-8 在init里初始化数组

注意 这里的成员变量命名加了下划线作为前缀,它是一种编码风格,主要用于区别成员变量与局部变量。

步骤2 为了防止忘记释放内存,立刻在dealloc方法里释放掉该数组,如代码清单2-9所示。

代码清单2-9 在dealloc方法里释放掉数组

步骤3 初始化一系列的敌机精灵,并把这些精灵都添加到数组中。

找到init方法,在代码清单2-8所示代码后添加代码清单2-10所示代码。

代码清单2-10 找到init方法添加代码

这段代码和前面的类似,唯一区别就是在一个循环里初始10个sprite,并且把sprite初始可见性设置为no,最后把这些sprite都添加到_enemysprites数组中。

如果现在运行项目,结果与上一次编译的没有区别,因为新初始化的敌机精灵是不可见的,同时它们的位置是在设备屏幕上方之外。现在,我们需要一些代码,希望能够隔一段时间有一架敌机随机从上方俯冲下来。

步骤4 打开init方法,在代码清单2-10后添加代码清单2-11所示代码。

代码清单2-11 init方法继续添加代码

该方法的作用是:调用完init方法之后,隔1.0秒调用spawnenemy方法。这种特性非常有用,因为我们有时候希望在触发某个事件之后,不要求马上响应,而是隔一段时间再做处理。

步骤5 定义一些私有方法。

其实在objective-c世界里不存在真正意义的私有方法,有时为了不让api暴露给客户端程序员,一些类的内部使用的方法和变量需要放在私有扩展里,而不是直接声明在头文件中。

找到helloworldlayer.m的@implementation helloworldlayer部分,紧跟上面代码清单2-11添加代码清单2-12所示代码。

代码清单2-12 @implementation helloworldlayer部分后添加代码

这里定义一个匿名的category,把一些私有方法直接放到这里就可以。

步骤6 实现这两个方法。

在代码清单2-12中找到@end,在该行之前添加代码清单2-13所示代码。

代码清单2-13 @end之前添加代码

我们按照代码注释的序号逐步讲解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所示的效果!

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

继续阅读