-
Notifications
You must be signed in to change notification settings - Fork 43
cocos2d x 3.3 006 核心概念和相关类 导演
David edited this page Jan 14, 2015
·
6 revisions
- 单例模式
- 继承自Ref
- 子类DisplayLinkDirector
- setOpenGLView getOpenGLView getWinSize getWinSizeInPixels getVisibleSize
- runWithScene pushScene popScene popToRootScene popToSceneStackLevel replaceScene getRunningScene
- mainLoop end pause resume drawScene isPaused stopAnimation startAnimation
- setProjection getProjection setViewport setGLDefaultValues setDefaultValues setAlphaBlending setDepthTest pushMatrix popMatrix loadIdentityMatrix loadMatrix multiplyMatrix getMatrix resetMatrixStack
- getAnimationInterval setAnimationInterval isDisplayStats setDisplayStats
- convertToGL convertToUI
- getTextureCache getScheduler setScheduler getActionManager setActionManager getEventDispatcher setEventDispatcher getRenderer getConsole getDeltaTime getFrameRate
- purgeCachedData
- setContentScaleFactor getContentScaleFactor
- 由于对opengl的知识只知道个大概,so相关的代码就暂略过了,重点关注下业务方面的逻辑。 这也说明cocos有多厉害,他让你不懂opengl也依然可以写流弊的游戏,这也是吸引我的地方。
1. 单例的应用
Director* Director::getInstance()
{
if (!s_SharedDirector)
{
//单例
s_SharedDirector = new (std::nothrow) DisplayLinkDirector();
CCASSERT(s_SharedDirector, "FATAL: Not enough memory");
s_SharedDirector->init();
}
2. 初始化几个重要‘业务员’
bool Director::init(void)
{
setDefaultValues();
// scenes
_runningScene = nullptr;
_nextScene = nullptr;
_notificationNode = nullptr;
_scenesStack.reserve(15);
// FPS
_accumDt = 0.0f;
_frameRate = 0.0f;
_FPSLabel = _drawnBatchesLabel = _drawnVerticesLabel = nullptr;
_totalFrames = 0;
_lastUpdate = new struct timeval;
// paused ?
_paused = false;
// purge ?
_purgeDirectorInNextLoop = false;
_winSizeInPoints = Size::ZERO;
_openGLView = nullptr;
_contentScaleFactor = 1.0f;
//创建调度器
// scheduler
_scheduler = new (std::nothrow) Scheduler();
//创建动作管理器
//并设置每一帧都调用的callback
//导致每一帧都会调用到动作管理器的update方法,进而驱动action,详见动作篇
// action manager
_actionManager = new (std::nothrow) ActionManager();
_scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);
//创建事件分发器
_eventDispatcher = new (std::nothrow) EventDispatcher();
_eventAfterDraw = new (std::nothrow) EventCustom(EVENT_AFTER_DRAW);
_eventAfterDraw->setUserData(this);
_eventAfterVisit = new (std::nothrow) EventCustom(EVENT_AFTER_VISIT);
_eventAfterVisit->setUserData(this);
_eventAfterUpdate = new (std::nothrow) EventCustom(EVENT_AFTER_UPDATE);
_eventAfterUpdate->setUserData(this);
_eventProjectionChanged = new (std::nothrow) EventCustom(EVENT_PROJECTION_CHANGED);
_eventProjectionChanged->setUserData(this);
//init TextureCache
initTextureCache();
initMatrixStack();
_renderer = new (std::nothrow) Renderer;
_console = new (std::nothrow) Console;
return true;
}
3. 大循环, Application::run()中每一次循环调用mainloop, 程序在这里被驱动起来开始干活
void DisplayLinkDirector::mainLoop()
{
if (_purgeDirectorInNextLoop)
{
_purgeDirectorInNextLoop = false;
purgeDirector();
}
else if (! _invalid)
{
//具体干事的
drawScene();
//从这里看出,游戏的每一帧会清理下自动缓冲池
// release the objects
PoolManager::getInstance()->getCurrentPool()->clear();
}
}
4.具体干事的, 将活儿再分发给各个业务员, 让他们怕业务去
'兄弟们,你们上'
// Draw the Scene
void Director::drawScene()
{
// calculate "global" dt
calculateDeltaTime();
// skip one flame when _deltaTime equal to zero.
if(_deltaTime < FLT_EPSILON)
{
return;
}
if (_openGLView)
{
_openGLView->pollEvents();
}
//tick before glClear: issue #533
if (! _paused)
{
//调度器update,驱动起各种update callback和各种timer的触发或cancel等
_scheduler->update(_deltaTime);
//分发一个事件
_eventDispatcher->dispatchEvent(_eventAfterUpdate);
}
//opengl相关,略
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
* FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9
*/
if (_nextScene)
{
setNextScene();
}
pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
if (_runningScene)
{
//clear draw stats
_renderer->clearDrawStats();
//当前场景的渲染
//render the scene
_runningScene->render(_renderer);
_eventDispatcher->dispatchEvent(_eventAfterVisit);
}
// draw the notifications node
if (_notificationNode)
{
_notificationNode->visit(_renderer, Mat4::IDENTITY, 0);
}
if (_displayStats)
{
showStats();
}
_renderer->render();
_eventDispatcher->dispatchEvent(_eventAfterDraw);
popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_totalFrames++;
// swap buffers
if (_openGLView)
{
_openGLView->swapBuffers();
}
if (_displayStats)
{
calculateMPF();
}
}
5. 再看看场景管理相关的几个函数
void Director::runWithScene(Scene *scene)
{
CCASSERT(scene != nullptr, "This command can only be used to start the Director. There is already a scene present.");
CCASSERT(_runningScene == nullptr, "_runningScene should be null");
pushScene(scene);
startAnimation();
}
void Director::replaceScene(Scene *scene)
{
//CCASSERT(_runningScene, "Use runWithScene: instead to start the director");
CCASSERT(scene != nullptr, "the scene should not be null");
if (_runningScene == nullptr) {
runWithScene(scene);
return;
}
if (scene == _nextScene)
return;
if (_nextScene)
{
if (_nextScene->isRunning())
{
//onExit回调
_nextScene->onExit();
}
_nextScene->cleanup();
_nextScene = nullptr;
}
ssize_t index = _scenesStack.size();
_sendCleanupToScene = true;
//直接替换
_scenesStack.replace(index - 1, scene);
_nextScene = scene;
}
void Director::pushScene(Scene *scene)
{
CCASSERT(scene, "the scene should not null");
_sendCleanupToScene = false;
//栈结构
_scenesStack.pushBack(scene);
_nextScene = scene;
}
void Director::popScene(void)
{
CCASSERT(_runningScene != nullptr, "running scene should not null");
//出栈
_scenesStack.popBack();
ssize_t c = _scenesStack.size();
if (c == 0)
{
end();
}
else
{
_sendCleanupToScene = true;
_nextScene = _scenesStack.at(c - 1);
}
}
void Director::popToRootScene(void)
{
//直接退到root
popToSceneStackLevel(1);
}
void Director::popToSceneStackLevel(int level)
{
CCASSERT(_runningScene != nullptr, "A running Scene is needed");
ssize_t c = _scenesStack.size();
// level 0? -> end
if (level == 0)
{
end();
return;
}
// current level or lower -> nothing
if (level >= c)
return;
auto fisrtOnStackScene = _scenesStack.back();
if (fisrtOnStackScene == _runningScene)
{
_scenesStack.popBack();
--c;
}
//出栈直到达到需要的level
// pop stack until reaching desired level
while (c > level)
{
auto current = _scenesStack.back();
if (current->isRunning())
{
current->onExit();
}
current->cleanup();
_scenesStack.popBack();
--c;
}
_nextScene = _scenesStack.back();
// cleanup running scene
_sendCleanupToScene = true;
}
- 导演的责任是重大的,功能是全面的。同时他拥有一帮厉害的业务员负责各个领域的业务,比如事件分发器,timer相关的调度器,action管理器等
- 对场景的管理,导演维护的是一个栈结构
- 负责opengl相关的设置,这里不懂了,略
- 具体见上方API部分
Just build something.