bool
AppDelegate::applicationDidFinishLaunching()
initialize director
4 CCDirector *pDirector =
CCDirector::sharedDirector();
5
6 pDirector->
setOpenGLView(CCEGLView::sharedOpenGLView());
7
8 TargetPlatform target =
getTargetPlatform();
9
if (target ==
kTargetIpad)
11 {
12 ipad
13 CCFileUtils::sharedFileUtils()->setResourceDirectory(
iphonehd");
14
15 don't enable retina because we don't have ipad hd resource
16 CCEGLView::sharedOpenGLView()->setDesignResolutionSize(
640,kResolutionNoBorder);
17 }
if (target ==
kTargetIphone)
19 {
20 iphone
21
try to enable retina on device
23 if (
true == CCDirector::sharedDirector()->enableRetinaDisplay(
true))
24 {
25 iphone hd
26 CCFileUtils::sharedFileUtils()->setResourceDirectory(
27 }
28 else
29 {
30 CCFileUtils::sharedFileUtils()->setResourceDirectory(
iphone31 }
32 }
33 34 {
35 android,windows,blackberry,linux or mac
36 use 960*640 resources as design resolution size
37 CCFileUtils::sharedFileUtils()->setResourceDirectory(
38 CCEGLView::sharedOpenGLView()->setDesignResolutionSize(
39 }
40
turn on display FPS
42 pDirector->setDisplayStats(
true);
44 set FPS. the default value is 1.0/60 if you don't call this
45 pDirector->setAnimationInterval(
1.0 /
60);
46
47 create a scene. it's an autorelease object
48 CCScene *pScene =
HelloWorld::scene();
run
51 pDirector->
runWithScene(pScene);
52
53 return 54 }
这个函数主要是完成CCDirector类和CCScene类对象的初始化,设置资源路径、分辨率大小和帧率(FPS:Frames Per Second);最后通过CCDirector::runWithScene函数开始场景。
对于另外两个函数,他们的实现就相对简单的多(至少代码量就少很多):把所有事情都交给CCDirector去完成
This function will be called when the app is inactive. When comes a phone call,it's be invoked too
2 void AppDelegate::applicationDidEnterBackground()
3 {
4 CCDirector::sharedDirector()->
stopAnimation();
if you use SimpleAudioEngine,it must be pause
SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
8 }
9
this function will be called when the app is active again
11 void AppDelegate::applicationWillEnterForeground()
12 {
13 CCDirector::sharedDirector()->
startAnimation();
14
SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
17 }
如注释所陈述的,applicationDidEnterBackground函数会在程序进入“非活跃”状态(即失去窗口焦点)时被调用,而applicationWillEnterForeground函数会在程序进入“活跃”状态(即获得窗口焦点)时被调用(可以自己在这个函数里面下断点看看具体执行的流程)。
舞台需要场景
演员站在舞台上,却表演于场景中
—— by 我挂科了
赋词一句略显文艺范儿,求勿喷!言归正传,首先我们来看看HelloWorld的继承关系
HelloWorld从CCLayer继承,而CCLayer又是一个非常复杂的(至少它的father太多了)。你一定觉得HelloWorld很复杂吧,其实它没有传说中那么复杂
class HelloWorld :
public cocos2d::CCLayer
Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'id' in cocos2d-iphone
bool init();
there's no 'id' in cpp,so we recommend returning the class instance pointer
static cocos2d::CCScene*
scene();
a selector callback
void menuCloseCallback(CCObject*
pSender);
touch callback
void ccTouchesBegan(cocos2d::CCSet *pTouches,cocos2d::CCEvent *
pEvent);
15
implement the "static node()" method manually
17 CREATE_FUNC(HelloWorld);
18 };
多么单纯的类啊!你也许会说:CREATE_FUNC是神马东东?它一点都不单纯啊~
3.1、CREATE_FUNC
其实HelloWorld还是很单纯的,因为CREATE_FUNC定义很简单
#define CREATE_FUNC(__TYPE__)
static __TYPE__*
create()
3 {
4 __TYPE__ *pRet =
new __TYPE__();
if (pRet && pRet->
init())
6 {
7 pRet->
autorelease();
8 return pRet;
9 }
else
11 {
12 delete pRet;
13 pRet =
NULL;
14 return NULL;
15 }
16 }
CREATE_FUNC是一个宏,它定义了一个名为create的static函数,该函数完成下面几个事情:
1)创建__TYPE__类型的对象指针
2)如果创建成功,则调用该对象的init函数
a)如果init函数执行成功,则调用该对象的autorelease函数并返回该对象指针
b)如果init函数执行失败,则释放该对象并返回NULL
将这个宏在HelloWorld类中展开,HelloWorld就露出了它的真面目了
static HelloWorld*
create()
18 {
19 HelloWorld *pRet =
new HelloWorld();
if (pRet && pRet->
init())
21 {
22 pRet->
autorelease();
23 return pRet;
24 }
26 {
27 delete pRet;
28 pRet =
NULL;
29 return NULL;
30 }
31 }
32 };
我比较奇怪的是,为什么注释上写的是“static node()”而不是“static create()”呢?隐约听到有人在喊:这一定是笔误!好吧,不要在意这些细节。
3.2 梦回AppDelegate
还记得AppDelegate::applicationDidFinishLauching函数吗?它的实现中有这么一句
bool
AppDelegate::applicationDidFinishLaunching()
其他操作
6 CCScene *pScene =
HelloWorld::scene();
8 pDirector->
runWithScene(pScene);
其他操作
11 }
这是我们的HelloWorld第一次在程序中被使用,那我们就从HelloWorld::scene函数入手吧
1 CCScene*
HelloWorld::scene()
'scene' is an autorelease object
4 CCScene *scene =
CCScene::create();
5
'layer' is an autorelease object
7 HelloWorld *layer =
HelloWorld::create();
add layer as a child to scene
10 scene->
addChild(layer);
return the scene
return scene;
14 }
这个函数的实现完成了3个事情:
1)创建了一个空的CCScene对象scene
2)通过上面分析过的HelloWorld::create函数创建了一个HelloWorld对象layer,并将layer作为scene的一个子节点添加到scene中
3)将scene返回
3.3 初始化
在前面我们已经展示了HelloWorld::create函数,它创建了HelloWorld对象后会调用该对象的init函数来初始化对象。HelloWorld::init函数实现如下
on "init" you need to initialize your instance
bool HelloWorld::init()
4 //////////////////////////////
1. super init first
if ( !
CCLayer::init() )
10
11 CCSize visibleSize = CCDirector::sharedDirector()->
getVisibleSize();
12 CCPoint origin = CCDirector::sharedDirector()->
getVisibleOrigin();
14 /////////////////////////////
2. add a menu item with "X" image,which is clicked to quit the program
you may modify it.
add a "close" icon to exit the progress. it's an autorelease object
19 CCMenuItemImage *pCloseItem =
CCMenuItemImage::create(
20 CloseNormal.png",128); line-height:1.5!important">21 CloseSelected.png22 this,128); line-height:1.5!important">23 menu_selector(HelloWorld::menuCloseCallback));
24 pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/
2,128); line-height:1.5!important">25 origin.y + pCloseItem->getContentSize().height/
2));
create menu,it's an autorelease object
27 CCMenu* pMenu =
CCMenu::create(pCloseItem,128); line-height:1.5!important">28 pMenu->
setPosition(CCPointZero);
this->addChild(pMenu,128); line-height:1.5!important">31
3. add your codes below...
33
34 add a label shows "Hello World"
create and initialize a label
36 CCLabelTTF* pLabel = CCLabelTTF::create(
Hello WorldArial24);
37 position the label on the center of the screen
38 pLabel->setPosition(ccp(origin.x + visibleSize.width/
39 origin.y + visibleSize.height - pLabel->
getContentSize().height));
40 add the label as a child to this layer
this->addChild(pLabel,128); line-height:1.5!important">43
add "HelloWorld" splash screen"
44 CCSprite* pSprite = CCSprite::create(
HelloWorld.png45 position the sprite on the center of the screen
46 pSprite->setPosition(ccp(visibleSize.width/
2 + origin.x,visibleSize.height/
2 +
origin.y));
add the sprite as a child to this layer
48 this->addChild(pSprite,128); line-height:1.5!important">49
enable standard touch
51 this->setTouchEnabled(
52
54 }
不要看这个函数很长,实际上主要完成了4个事情
1)调用父类的初始化函数(CCLayer::init())完成对继承自父类成员的初始化
2)创建一个菜单(CCMenu)并在其中添加一个菜单项(CCMenuItem),将菜单显示在HelloWorld中。点击这个菜单项可以关闭程序
3)创建一个标签(CCLabel),让它在HelloWorld中显示“HelloWorld”字串
4)创建一个精灵(CCSprite),让它在HelloWorld中显示图片“HelloWorld.png”
HelloWorld::init函数中所创建的都是我们在运行起来的界面中所能看到的东西,这其中涉及到一些类将在后面学习,这里不深究。我比较好奇的是菜单项所实现的功能:点击后关闭程序(不信你亲自点一下试试)。这是怎么实现的呢?仔细分析一下菜单项的创建过程
2 CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
3 4 5 6 menu_selector(HelloWorld::menuCloseCallback));
最后一个参数形式很特别啊~ 我们先看看menu_selector是神马东西
#define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)
又是一个宏!它所完成的事情是将_SELECTOR取址并强制转换为SEL_MenuHandler类型。那么SEL_MenuHandler又是什么类型呢?
1 typedef void (CCObject::*SEL_MenuHandler)(CCObject*);
它是一个函数指针,这类函数有一个CCObject*类型的参数。此时我们可以将创建菜单项的代码展开,看看其真实的原貌
6 (SEL_MenuHandler)&HelloWorld::menuCloseCallback);
HelloWorld::menuCloseCallback函数以回调函数的方式传入菜单项,在点击菜单项时被触发。也就是说实现关闭程序功能的是HelloWorld::menuCloseCallback函数
void HelloWorld::menuCloseCallback(CCObject*
pSender)
3 CCDirector::sharedDirector()->
end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
6 exit(
7 #endif
8 }
最终,由CCDirector::end函数完成程序的关闭(在IOS中还需要调用exit函数)。
参考文献
Cocos2d-x 高级开发教程:制作自己的捕鱼达人