Cocos2d-x游戏开发实例详解7:对象释放时机

2015年03月25日 13:59 0 点赞 0 评论 更新于 2017-05-05 06:00

在上两篇文章中,我们详细讲解了内存自动释放机制。在本篇文章中,我们将深入探讨自动对象的释放时机。

当一个对象调用 autorelease() 函数后,它会被加入到自动释放池中。那么,这个对象究竟何时会被释放呢?下面我们从游戏主循环开始进行跟进分析。

游戏主循环起始点 CCApplication::run()

以下是 CCApplication::run() 函数的代码:

int CCApplication::run()
{
if (applicationDidFinishLaunching())
{
[[CCDirectorCaller sharedDirectorCaller] startMainLoop]; // 主循环开始
}
return 0;
}

在这个函数中,如果 applicationDidFinishLaunching() 函数返回 true,则会调用 CCDirectorCaller 单例的 startMainLoop 方法,从而启动游戏的主循环。

跟进 startMainLoop 函数

-(void) startMainLoop
{
// CCDirector::setAnimationInterval() is called, we should invalidate it first
[displayLink invalidate];
displayLink = nil;
// displayLink是CADisplayLink对象,target是自己,回调是coCaller
displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doCaller:)]; // 看这个doCaller回调
[displayLink setFrameInterval: self.interval]; // 设置帧率
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; // 添加到循环并启动
}

startMainLoop 函数中,首先会使之前的 displayLink 失效并置为 nil。然后创建一个新的 CADisplayLink 对象,将其 target 设置为自身,回调方法设置为 doCaller:。接着设置帧率,并将 displayLink 添加到当前的运行循环中启动。这里我们重点关注 doCaller 回调函数。

doCaller 回调函数 CCDisplayLinkDirector::mainLoop

void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene(); // draw the scene

// release the objects
CCPoolManager::sharedPoolManager()->pop();
}
}

CCDisplayLinkDirector::mainLoop 函数中,首先会检查 m_bPurgeDirecotorInNextLoop 标志。如果该标志为 true,则将其置为 false 并调用 purgeDirector() 函数。如果该标志为 falsem_bInvalidfalse,则会调用 drawScene() 函数绘制场景,然后调用 CCPoolManager::sharedPoolManager()->pop() 函数释放对象。

对象释放点

经过上述分析,我们可以看到,在一个循环结束时,CCPoolManager::sharedPoolManager()->pop() 函数被调用,这个函数就是用来释放自动释放池中的对象的。如果有同学对具体的释放过程感兴趣,可以深入跟进该函数的实现。

通过以上对游戏主循环的逐步分析,我们清晰地了解了自动对象在 Cocos2d-x 中的释放时机。

作者信息

boke

boke

共发布了 1025 篇文章