今天忙于学校的招聘,我发现招聘游戏互联网公司来学校的挺少的,而限定cocos2d 开发的也比较少,但是这不一定就意味着我要放弃这个行业。
不废话了。
今天主要看了下cocos2d怎么使用吧。
Cocos2d 这个游戏引擎还是很好上手的。
我看的书
首先要理解
1.CCDirector导演就是负责CCScene怎么显示啊,等等,导演就是看场景的也可以很好的理解
2.CCScene感觉就像容器,里面装各种CCLayer
3.CCSprite是处理角色或者背景,精灵对象
4.CCMenu、CCMenuItem 也很简单 不用解释了,里面还有参数是函数地址的,也就是回调函数、感觉也比较简单。具体都是什么selector;
上面的大部分类都是继承CCNode
我猜:
这里有个设计模式,可以参考c++可复用的设计模式,组件模式,个人感觉有点像,具体代码没有深究
来看下cocos2d HelloWorld的代码;
class HelloWorld : public cocos2d::CCLayer
{
public:
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual 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);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
};
看起来都挺简单,不用解释什么,这里有个宏也看看,CREATE_FUNC
去看看定义,
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL; \
} \
}
咦,不错哦,cocos2d还帮我自动调用init(),自动调用autorelease()
那这样我只要专注于init出事化代码了,内存也不用关心了,
来具体看下init
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
/////////////////////////////
// 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
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback));
pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
origin.y + pCloseItem->getContentSize().height/2));
// create menu, it's an autorelease object
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition(CCPointZero);
this->addChild(pMenu, 1);
/////////////////////////////
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
// position the label on the center of the screen
pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - pLabel->getContentSize().height));
// add the label as a child to this layer
this->addChild(pLabel, 1);
// add "HelloWorld" splash screen"
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
// position the sprite on the center of the screen
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// add the sprite as a child to this layer
this->addChild(pSprite, 0);
return true;
}
咋一看,代码有点多,不过就是父类初始化,菜单,背景啊什么的,设置设置位置,不复杂。
可是,代码是怎么运行的呢?
看看main在哪里。
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
eglView->setViewName("Mota");
eglView->setFrameSize(480, 320);
return CCApplication::sharedApplication()->run();
}
封装的真心不错,声明了一个app 还是代理类的app 我猜,肯定完成了很多初始化的任务。具体看看去。
class AppDelegate : private cocos2d::CCApplication
{
public:
AppDelegate();
virtual ~AppDelegate();
/**
@brief Implement CCDirector and CCScene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
/**
@brief The function be called when the application enter background
@param the pointer of the application
*/
virtual void applicationDidEnterBackground();
/**
@brief The function be called when the application enter foreground
@param the pointer of the application
*/
virtual void applicationWillEnterForeground();
};
真心继承了CCApplication,只是重写了几个方法,
/**
@brief Implement CCDirector and CCScene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
这个方法简介不错,仔细瞧瞧,
bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
CCDirector* pDirector = CCDirector::sharedDirector();
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
pDirector->setOpenGLView(pEGLView);
// turn on display FPS
pDirector->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);
// create a scene. it's an autorelease object
CCScene *pScene = HelloWorld::scene();
// run
pDirector->runWithScene(pScene);
return true;
}
好像,我刚刚的HelloWorld 用到了,这里就是初始化了么,
runWithScene() 是怎么样的方法?
敲敲去。
pushScene(pScene);
startAnimation();
看了下,里面有个CCScene的Stack
startAnimation()又干嘛了?
void CCDisplayLinkDirector::startAnimation(void)
{
if (CCTime::gettimeofdayCocos2d(m_pLastUpdate, NULL) != 0)
{
CCLOG("cocos2d: DisplayLinkDirector: Error on gettimeofday");
}
m_bInvalid = false;
#ifndef EMSCRIPTEN
CCApplication::sharedApplication()->setAnimationInterval(m_dAnimationInterval);
#endif // EMSCRIPTEN
}
里面好像没有什么重要的东西哦!我怎么没看到循环呢,等等,主函数中还有一个方法,
CCApplication::sharedApplication()->run();
具体是什么呢,看看去吧~
int CCApplication::run()
{
PVRFrameEnableControlWindow(false);
// Main message loop:
MSG msg;
LARGE_INTEGER nFreq;
LARGE_INTEGER nLast;
LARGE_INTEGER nNow;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nLast);
// Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())
{
return 0;
}
CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView();
pMainWnd->centerWindow();
ShowWindow(pMainWnd->getHWnd(), SW_SHOW);
while (1)
{
if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// Get current time tick.
QueryPerformanceCounter(&nNow);
// If it's the time to draw next frame, draw it, else sleep a while.
if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)
{
nLast.QuadPart = nNow.QuadPart;
CCDirector::sharedDirector()->mainLoop();
}
else
{
Sleep(0);
}
continue;
}
if (WM_QUIT == msg.message)
{
// Quit message loop.
break;
}
// Deal with windows message.
if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
一目了然,so easy windows的消息循环在这里了!!看看什么,就是while 循环嘛,然后还设置了下帧数!!不是很简单!!??
今天就看到这里吧!这个引擎真的不难!
简单粗暴,就是好!!!