一、游戏入口
WinMain ---> APPDeleGate ---> applicationDidFinishLaunching
游戏最终在从APPDeleGate 中的applicationDidFinishLaunching这个函数开始的,关于applicationDidFinishLaunching函数,这里涉及到一个完美的多态的实现。
二、游戏结构设计
一个游戏是由多个场景构成的,一个场景又是由多个层组成的,一个层是由多个精灵组成的。
三、开始制作自己的第一个层
//BackGroundLayer.h
#pragma once
#ifndef _BACKGROUNDLAYER_H_
#define _BACKGROUNDLAYER_H_
#include"cocos2d.h"
class BackGroundLayer:public cocos2d::CCLayer {
public:
CREATE_FUNC(BackGroundLayer);
/*static BackGroundLayer* create() {
BackGroundLayer* pRet = new BackGroundLayer;
if (pRet && pRet->init()) {
pRet->autorelease();
return pRet;
}
else {
delete pRet;
pRet = NULL;
return NULL;
}
}*/
bool init();
};
#endif
//BackGroundLayer.cpp
#include "BackGroundLayer.h"
//using namespace cocos2d;
USING_NS_CC;
bool BackGroundLayer::init() {
if(CCLayer::init()){
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSprite* background = CCSprite::create("bj03.jpg");
background->setPosition(winSize.width * 0.5, winSize.height * 0.5);
this->addChild(background);
return true;
}
return false;
}
//在APPDeleGate.applicationDidFinishLaunching()函数中加入
auto scene = CCScene::create();
auto pLayer = BackGroundLayer::create();
scene->addChild(pLayer);
// run
director->runWithScene(scene);
1、要创建层,就得让新创建的这个层类继承与CCLayer,要继承CCLayer就得导入cocos2d.h这个头文件,以后创建新类只要包含这么一个头文件就可以了,这就自动导入了cococs2d里封装的各种类;
#include"cocos2d.h"
class BackGroundLayer:public cocos2d::CCLayer
2、BackGroundLayer::create()函数是一个静态成员函数,被cocos把create这个函数封装成了一个宏CREATE_FUNC,这个宏的实现是这样的:
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = nullptr; \
return nullptr; \
} \
}
与我注释掉的代码:
static BackGroundLayer* create() {
BackGroundLayer* pRet = new BackGroundLayer;
if (pRet && pRet->init()) {
pRet->autorelease();
return pRet;
}
else {
delete pRet;
pRet = NULL;
return NULL;
}
}
是一样的,可以自己写,也可以直接使用封装好的宏,既然人家好心帮我们封装好了,非要自找麻烦有啥意思嘞,那我们就调用宏。
3、BackGroundLayer::init() 函数用来初始化这个层, 首先要初始化CCLayer层:
CCLayer::init()
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
这句是获取到导演中定义的窗口的大小,sharedDirector()应用了单例设计设计模式(学cocos2d-x还能学到不好设计模式,真是赚了),来看看是如何实现单例模式的,进入到sharedDirector()函数:
CC_DEPRECATED_ATTRIBUTE static Director* sharedDirector() { return Director::getInstance(); }
可以看到他是Director类下的一个静态成员函数,返回了一个Director型的指针,看调用方式就可以知道getInstance()函数也是个静态成员函数,然后再进入到getInstance()函数:
static DisplayLinkDirector *s_SharedDirector = nullptr;
Director* Director::getInstance()
{
if (!s_SharedDirector)
{
s_SharedDirector = new (std::nothrow) DisplayLinkDirector();
CCASSERT(s_SharedDirector, "FATAL: Not enough memory");
s_SharedDirector->init();
}
return s_SharedDirector;
}
这里就是实现单例模式的精华了,有s_SharedDirector 这个一个静态DisplayLinkDirector *类型的对象指针,初始化是一个nullptr(空指针),那么再getInstance函数中,判断这个对象指针是否为空,为空说明就没有创建过这个对象,那么就创建,如果不为空,说明创建过了,那么就直接返回。
CCSprite* background = CCSprite::create("bj03.jpg");
这句创建一个精灵,把背景图像bj03.jpg作为这个精灵,这个bj03.jpg图像是放在项目的resource文件夹下的。
background->setPosition(winSize.width * 0.5, winSize.height * 0.5);
这句的目的是把背景图像的中心定位在游戏窗口的中心。
this->addChild(background);
最后把精灵加载到当前层中。
这里为什么不用构造函数初始化,而要用一个create函数和一个init函数呢,首先cocos2d-x是基于ios游戏开发cocos中用的Object-C语言的,OC(Object-C的简称)语言中没有构造器,就是用create和init来初始化的,转成cocos2d-x也同样沿用了这样的方法。同时构造器还有个缺点就是子类创建的同时必然会去调用父类的构造,可能会有重复的内容,这也是这里不用构造器初始化的原因。
层都弄好之后就要到游戏入口如创建了,也就是AppDelegate::applicationDidFinishLaunching()下:
auto scene = CCScene::create();
创建一个场景,auto自动识别scene的类型,也可以写成CCScene*。
auto pLayer = BackGroundLayer::create();
通过create可以创建出前面写的背景层了,这里auto也可以写成BackGroundLayer*。
scene->addChild(pLayer);
将创建的背景层加入到场景中去:
director->runWithScene(scene);
导演director就去运行这个场景,游戏中有且仅有一个导演director,这个导演在创建项目是就写在里面了,不需要我们再改动了。最后运行出来就是这样了。
最后说明一个地方,一般都要导入cocos2d的命名空间:
//using namespace cocos2d;
USING_NS_CC;
可以用using namespace cocos2d;这种方式,也可以用cocos2d已经封装好的宏USING_NS_CC都是一样的。