到上一篇为止,我们已经基于cocos2d-x开发出一个很简单的Uphone游戏原型了。下面再添加一些音效、背景音乐和简单的游戏逻辑就可以完工了。
六、音乐音效的实现
cocos2d-iphone中包含一个cocosDenshion库,里面从底到高提供三层接口,CDSoundEngine->CDAudioManager->SimpleAudioEngine。 cocosDenshion整个是依赖于OpenAL实现的。但OpenAL并不像OpenGL是Khronos Group的标准,而是Creative(创新)公司的一个开源库,可以软实现或硬件实现,只是名字起的比较山寨容易让人联想到OpenGL而已。目前硬件实现了OpenAL的好像就苹果一家,对于没有OpenAL的Uphone而言,我们就无法提供cocosDenshion库里底层那些复杂的音效支持了。而最顶一层,SimpleAudioEngine是最简单实用的、也是开发者最常用到的,cocos2d-x提供了这层接口的封装。我们来看游戏代码中如何“只用一行”就实现了音效播放
首先把background-music-aac.mp3和pew-pew-lei.wav两个文件拷贝到 D:\Work7\NEWPLUS\TDA_DATA\UserData 目录下。这里说明两点
- Wenderlic文章中提供的这两个音乐文件,是caf格式,这是苹果自己的格式。我们在这里分别转成WAV和MP3,演示一下SimpleAudioEngine对这两种大众格式的支持
- 和前面的图片资源一样,我们先简单化地把音乐资源拷贝到uphone模拟器默认的资源目录下,通过直接读文件来使用。在本系列教程的下一篇“打包发布”中将会描述如何把图片和音乐和程序打在一个二进制包里,游戏开发者不用担心资源被人轻易拷走后山寨的问题
先在HelloWorldScene.cpp的开头,添加对SimpleaudioEngine.h的包含
// cpp with cocos2d-x
#include "SimpleAudioEngine/SimpleAudioEngine.h"
|
// objc with cocos2d-iphone
#import "SimpleAudioEngine.h"
|
然后在bool HelloWorld::init()方法中,加入播放背景音乐的代码
// cpp with cocos2d-x
SimpleAudioEngine::getSharedEngine()->playBackgroundMusic(
"background-music-aac.mp3");
|
// objc with cocos2d-iphone
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:
@"background-music-aac.caf"];
|
接着在ccTouchesEnded方法中播放扔出飞镖的音效
// cpp with cocos2d-x
SimpleAudioEngine::getSharedEngine()->playEffect("pew-pew-lei.wav");
|
// objc with cocos2d-iphone
[[SimpleAudioEngine sharedEngine] playEffect:@"pew-pew-lei.caf"];
|
音效和背景音乐就这样简单搞定了。
七、最后的润色
现在让我们创建一个新场景,在打掉若干小怪、或者被小怪穿到屏幕左边时显示“You Win”或“You Lose”的界面。在Visual Studio中新建两个文件, GameOverScene.cpp和GameOverScene.h
GameOverScene.h的内容
1 // cpp with cocos2d-x
2 #ifndef _GAME_OVER_SCENE_H_
3 #define _GAME_OVER_SCENE_H_
4
5 #include "cocos2d.h"
6
7 class GameOverLayer : public cocos2d::CCColorLayer
8 {
9 public:
10 GameOverLayer():_label(NULL) {};
11 virtual ~GameOverLayer();
12 bool init();
13 LAYER_NODE_FUNC(GameOverLayer);
14
15 void gameOverDone();
16
17 CCX_SYNTHESIZE_READONLY(cocos2d::CCLabel*, _label, Label);
18 };
19
20
21
22
23
24 class GameOverScene : public cocos2d::CCScene
25 {
26 public:
27 GameOverScene():_layer(NULL) {};
28 ~GameOverScene();
29 bool init();
30 SCENE_NODE_FUNC(GameOverScene);
31
32 CCX_SYNTHESIZE_READONLY(GameOverLayer*, _layer, Layer);
33 };
34
35
36
37 #endif // _GAME_OVER_SCENE_H_
|
1 // objc with cocos2d-iphone
2
3
4
5 #import "cocos2d.h"
6
7 @interface GameOverLayer : CCColorLayer
8 {
9
10
11
12
13
14
15
16
17 CCLabel *_label;
18 }
19
20 @property (nonatomic, retain) CCLabel *label;
21
22 @end
23
24 @interface GameOverScene : CCScene
25 {
26
27
28
29
30
31
32 GameOverLayer *_layer;
33 }
34
35 @property (nonatomic, retain) GameOverLayer *layer;
36
37 @end
|
接着就实现GameOverScene.cpp的内容
1 // cpp with cocos2d-x
2 #include "GameOverScene.h"
3 #include "HelloWorldScene.h"
4
5 using namespace cocos2d;
6
7
8 bool GameOverScene::init()
9 {
10 if( CCScene::init() )
11 {
12 this->_layer = GameOverLayer::node();
13 _layer->retain();
14 this->addChild(_layer);
15
16 return true;
17 }
18 else
19 {
20 return false;
21 }
22 }
23
24 GameOverScene::~GameOverScene()
25 {
26 if (_layer)
27 {
28 _layer->release();
29 _layer = NULL;
30 }
31 }
32
33
34
35
36
37
38 bool GameOverLayer::init()
39 {
40 if ( CCColorLayer::initWithColor( ccc4(255,255,255,255) ) )
41 {
42 CGSize winSize = CCDirector::getSharedDirector()->getWinSize();
43 this->_label = CCLabel::labelWithString("","Artial", 32);
44 _label->retain();
45 _label->setColor( ccc3(0, 0, 0) );
46 _label->setPosition( ccp(winSize.width/2, winSize.height/2) );
47 this->addChild(_label);
48
49 this->runAction( CCSequence::actions(
50 CCDelayTime::actionWithDuration(3),
51 CCCallFunc::actionWithTarget(this,
52 callfunc_selector(GameOverLayer::gameOverDone)),
53 NULL));
54
55 return true;
56 }
57 else
58 {
59 return false;
60 }
61 }
62
63 void GameOverLayer::gameOverDone()
64 {
65 CCDirector::getSharedDirector()->replaceScene( HelloWorld::scene() );
66 }
67
68 GameOverLayer::~GameOverLayer()
69 {
70 if (_label)
71 {
72 _label->release();
73 _label = NULL;
74 }
75 }
76
77
|
1 // objc with cocos2d-iphone
2 #import "GameOverScene.h"
3 #import "HelloWorldScene.h"
4
5 @implementation GameOverScene
6 @synthesize layer = _layer;
7
8 - (id)init
9 {
10 if ((self = [super init]))
11 {
12 self.layer = [GameOverLayer node];
13
14 [self addChild:_layer];
15 }
16 return self;
17 }
18
19
20
21
22
23
24 - (void)dealloc
25 {
26
27
28 [_layer release];
29 _layer = nil;
30 [super dealloc];
31 }
32
33 @end
34
35 @implementation GameOverLayer
36 @synthesize label = _label;
37
38 -(id) init
39 {
40 if( (self=[super initWithColor:ccc4(255,255,255,255)] ))
41 {
42 CGSize winSize = [[CCDirector sharedDirector] winSize];
43 self.label = [CCLabel labelWithString:@"" fontName:@"Arial" fontSize:32];
44
45 _label.color = ccc3(0,0,0);
46 _label.position = ccp(winSize.width/2, winSize.height/2);
47 [self addChild:_label];
48
49 [self runAction:[CCSequence actions:
50 [CCDelayTime actionWithDuration:3],
51 [CCCallFunc actionWithTarget:self
52 selector:@selector(gameOverDone)],
53 nil]];
54 }
55 return self;
56 }
57
58
59
60
61
62
63 - (void)gameOverDone
64 {
65 [[CCDirector sharedDirector] replaceScene:[HelloWorld scene]];
66 }
67
68 - (void)dealloc
69 {
70
71
72 [_label release];
73 _label = nil;
74 [super dealloc];
75 }
76
77 @end
|
注意,上面GameOverScene.cpp里有两个对象,一个场景(scene)和一个图层(layer),场景可以包含多个图层,而这个图层只在屏幕正中间放了一个文字标签(label),显示3秒种后返回到HelloWorldScene中。
最后,为了调用起这个GameOverScene,我们需要在HelloWorldScene中添加一些游戏逻辑代码。先得添加一个变量,判断我们的带头大哥一共用飞镖干掉了多少杂兵。在class HelloWorld中添加一个成员变量:
1 // cpp with cocos2d-x
2 protected:
3 int _projectilesDestroyed;
|
1 // objc with cocos2d-iphone
2
3 int _projectilesDestroyed;
|
然后在HelloWorldScene.cpp中,添加对GameOverScene.h的引用
// cpp with cocos2d-x
#include "GameOverScene.h"
|
// objc with cocos2d-iphone
#import "GameOverScene.h"
|
在HelloWorld::update方法中的removeChild(target)后面的targetsToDelete循环中增加计数并检查获胜条件,获胜了就显示"You Win!"界面
// cpp with cocos2d-x
_projectilesDestroyed++;
if (_projectilesDestroyed > 30)
{
GameOverScene *gameOverScene = GameOverScene::node();
gameOverScene->getLayer()->getLabel()->setString("You Win!");
CCDirector::getSharedDirector()->replaceScene(gameOverScene);
}
|
// objc with cocos2d-iphone
_projectilesDestroyed++;
if (_projectilesDestroyed > 30)
{
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:@"You Win!"];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
}
|
与之匹配的是失败条件:任何一个反派小兵穿越了屏幕的最左边,你就挂了。于是修改spriteMoveFinished方法,在if (sprite->getTag() == 1)条件里面增加“You Lose”的代码:
// cpp with cocos2d-x
GameOverScene *gameOverScene = GameOverScene::node();
gameOverScene->getLayer()->getLabel()->setString("You Lose :[");
CCDirector::getSharedDirector()->replaceScene(gameOverScene);
|
// objc with cocos2d-iphone
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:@"You Lose :["];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
|
最后编译并运行整个游戏项目,这样你就可以听到带头大哥扔飞镖同时很嚣张地发出的DIU~DIU~的声音,还有很HIGH的背景音乐循环播放;另一方面,游戏赢或输了会有一个界面提示。
这个游戏至此,已经在模拟器上100%完成了。下一篇我们讲如何做交叉编译成linux版本(也就是Uphone真机运行的版本), 如何打包图片和音乐资源到程序二进制中防止被拷贝、以及如何用制作成Uphone安装包发布。
著作权声明:本文由http://www.walzer.cn/原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!