【2014-01-27】cocos2dx学习笔记:CCNode回调流程
[历史归档]本文原发布于 cstriker1407.info 个人博客内容为历史存档仅供参考。发布时间2014-01-27 标题cocos2dx学习笔记CCNode回调流程分类编程 / C C / cocos2dx 标签cocos2dxcocos2dx学习笔记CCNode回调流程CCNode的回调流程CCNode的几个回调函数cocos2dx程序框架流程首先进入main.cpp函数可以发现程序调用了Appliaction的run方法然后查看run方法是一个while1循环调用了Director的mainloop方法查看mainLoop方法发现其调用了drawScene方法查看drawScene方法没有场景切换动画时的回调流程void CCDirector::setNextScene(void)有场景切换动画时的回调流程从场景A切换到场景XCCTransitionScene和CCTransitionShrinkGrow片段由场景X切换场景B:最近项目中用到了cocos2dx来开发一个基于陀螺仪的demo忙了半个星期一边学习一边开发总算搞了出来。这里备份下开发中学习到的一些cocos2dx知识。CCNode的回调流程在使用CCLayerCCScene的时候往往想在layer或者场景切换的时候处理一些资源类的东西于是就在CCNode里发现了一些回调函数但是这些回调函数如何调用作者在网上也没有搜索自己翻了下源码发现比较简单。在这里备份下。CCNode的几个回调函数classCC_DLLCCNode:publicCCObject{public:。。。。。 。。。。。virtualboolinit();staticCCNode*create(void);/** * Event callback that is invoked every time when CCNode enters the stage. * If the CCNode enters the stage with a transition, this event is called when the transition starts. * During onEnter you cant access a sister/brother node. * If you override onEnter, you shall call its parents one, e.g., CCNode::onEnter(). * js NA * lua NA */virtualvoidonEnter();/** Event callback that is invoked when the CCNode enters in the stage. * If the CCNode enters the stage with a transition, this event is called when the transition finishes. * If you override onEnterTransitionDidFinish, you shall call its parents one, e.g. CCNode::onEnterTransitionDidFinish() * js NA * lua NA */virtualvoidonEnterTransitionDidFinish();/** * Event callback that is invoked every time the CCNode leaves the stage. * If the CCNode leaves the stage with a transition, this event is called when the transition finishes. * During onExit you cant access a sibling node. * If you override onExit, you shall call its parents one, e.g., CCNode::onExit(). * js NA * lua NA */virtualvoidonExit();/** * Event callback that is called every time the CCNode leaves the stage. * If the CCNode leaves the stage with a transition, this callback is called when the transition starts. * js NA * lua NA */virtualvoidonExitTransitionDidStart();/// } end of event callbacks./** * Stops all running actions and schedulers */virtualvoidcleanup(void);。。。。。 。。。。。};cocos2dx程序框架流程首先进入main.cpp函数可以发现程序调用了Appliaction的run方法intAPIENTRY_tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,intnCmdShow){。。。。。 。。。。。returnCCApplication::sharedApplication()-run();}然后查看run方法是一个while1循环调用了Director的mainloop方法intCCApplication::run(){。。。。。 。。。。。while(1){。。。。。CCDirector::sharedDirector()-mainLoop();。。。。。}。。。。。}查看mainLoop方法发现其调用了drawScene方法voidCCDisplayLinkDirector::mainLoop(void){。。。。。 。。。。。drawScene();。。。。。}查看drawScene方法voidCCDirector::drawScene(void){。。。。。 。。。。。if(m_pNextScene){setNextScene();}。。。。。if(m_pRunningScene){m_pRunningScene-visit();}。。。。。}查看代码到这里就可以大致的知道cocos2dx程序的运行流程通过不停的循环来执行当前scene的visit方法绘制界面如果有场景切换就切换场景后继续visiit。这里作者不关心visit和draw方法只关注于CCNode的回调流程。没有场景切换动画时的回调流程void CCDirector::setNextScene(void)voidCCDirector::setNextScene(void){boolrunningIsTransitiondynamic_castCCTransitionScene*(m_pRunningScene)!NULL;boolnewIsTransitiondynamic_castCCTransitionScene*(m_pNextScene)!NULL;// If it is not a transition, call onExit/cleanupif(!newIsTransition){if(m_pRunningScene){m_pRunningScene-onExitTransitionDidStart();m_pRunningScene-onExit();}// issue #709. the root node (scene) should receive the cleanup message too// otherwise it might be leaked.if(m_bSendCleanupToScenem_pRunningScene){m_pRunningScene-cleanup();}}if(m_pRunningScene){m_pRunningScene-release();}m_pRunningScenem_pNextScene;m_pNextScene-retain();m_pNextSceneNULL;if((!runningIsTransition)m_pRunningScene){m_pRunningScene-onEnter();m_pRunningScene-onEnterTransitionDidFinish();}}通过查看setNextScene的方法就可以发现在没有场景切换动画时各个回调函数的调用流程很清楚了。首先调用要退出场景的 onExitTransitionDidStart 方法和 onExit 方法如果当前是切换场景不是push场景就继续调用cleanup方法最后在执行新场景的 onEnter 和 onEnterTransitionDidFinish 方法。我们查看下这4个onXXXX方法CCScene和CCLayer均继承自CCNode这4个方法也是CCNode的方法。我们以onEnter为例voidCCNode::onEnter(){arrayMakeObjectsPerformSelector(m_pChildren,onEnter,CCNode*);。。。。。}可以发现里面有个宏这个就是关键所在~~宏的定义如下#definearrayMakeObjectsPerformSelector(pArray,func,elementType)\do{\if(pArraypArray-count()0)\{\CCObject*child;\CCARRAY_FOREACH(pArray,child)\{\elementType pNode(elementType)child;\if(pNode)\{\pNode-func();\}\}\}\}\while(false)由此就很清晰了当场景切换时新老场景的各个回调方法会被回调这些回调方法又会递归调用其children的相同的回调方法由于CCSceneCCLayerCCSprite等在cocos2dx的场景构建时为父子关系那么场景中的各种元素都会回调一次。有场景切换动画时的回调流程有场景动画时回调比较复杂一点首先需要明确的是场景切换动画也是场景。这样当场景A通过动画X切换到场景B时实际上是有3个场景AXB。为了便于分析我们假设场景切换动画X为 CCTransitionShrinkGrow 类的动画。从场景A切换到场景X回到函数 void CCDirector::setNextScene(void) 中当从A切到X时m_pRunningScene 是场景Am_pNextScene 是场景XA不是场景切换动画类CCTransitionShrinkGrowCCTransitionSceneX是场景切换动画类。那么根据函数逻辑函数流程会直接走向场景X的onEnter和onEnterXXX函数但不会走向场景A的onExitXXX和onExit函数。CCTransitionScene和CCTransitionShrinkGrow片段代码较多但是根据代码的走向就很清晰了。classCC_DLLCCTransitionScene:publicCCScene{protected:CCScene*m_pInScene;CCScene*m_pOutScene;。。。。。 。。。。。}classCC_DLLCCTransitionShrinkGrow:publicCCTransitionScene,publicCCTransitionEaseScene{。。。。。 。。。。。}CCTransitionScene*CCTransitionScene::create(floatt,CCScene*scene){CCTransitionScene*pScenenewCCTransitionScene();if(pScenepScene-initWithDuration(t,scene)){pScene-autorelease();returnpScene;}CC_SAFE_DELETE(pScene);returnNULL;}boolCCTransitionScene::initWithDuration(floatt,CCScene*scene){CCAssert(scene!NULL,Argument scene must be non-nil);if(CCScene::init()){m_fDurationt;// retainm_pInScenescene;m_pInScene-retain();m_pOutSceneCCDirector::sharedDirector()-getRunningScene();if(m_pOutSceneNULL){m_pOutSceneCCScene::create();m_pOutScene-init();}m_pOutScene-retain();CCAssert(m_pInScene!m_pOutScene,Incoming scene must be different from the outgoing scene);sceneOrder();returntrue;}else{returnfalse;}}voidCCTransitionScene::finish(){。。。。。 。。。。。this-schedule(schedule_selector(CCTransitionScene::setNewScene),0);}voidCCTransitionScene::setNewScene(floatdt){。。。。。 CCDirector*directorCCDirector::sharedDirector();。。。。。 director-replaceScene(m_pInScene);。。。。。}// custom onEntervoidCCTransitionScene::onEnter(){CCScene::onEnter();// disable events while transitionsCCDirector::sharedDirector()-getTouchDispatcher()-setDispatchEvents(false);// outScene should not receive the onEnter callback// only the onExitTransitionDidStartm_pOutScene-onExitTransitionDidStart();m_pInScene-onEnter();}// custom onExitvoidCCTransitionScene::onExit(){CCScene::onExit();// enable events while transitionsCCDirector::sharedDirector()-getTouchDispatcher()-setDispatchEvents(true);m_pOutScene-onExit();// m_pInScene should not receive the onEnter callback// only the onEnterTransitionDidFinishm_pInScene-onEnterTransitionDidFinish();}voidCCTransitionShrinkGrow::onEnter(){CCTransitionScene::onEnter();。。。。。 。。。。。 m_pInScene-runAction(this-easeActionWithAction(scaleIn));m_pOutScene-runAction(CCSequence::create(this-easeActionWithAction(scaleOut),CCCallFunc::create(this,callfunc_selector(CCTransitionScene::finish)),NULL));}首先当走向场景X的onEnter时CCTransitionShrinkGrow类的onEnter函数首先调用了父类CCTransitionScene的onEnter函数然后调用了CCTransitionScene的finish函数。根据CCTransitionScene的initXX函数可以知道在CCTransitionScene中m_pInScene是场景Bm_pOutScene是场景A那么根据CCTransitionScene的onEnter函数的逻辑知道此时场景A的onExitXXX被调用场景B的onEnter被调用。再来分析CCTransitionScene的finish函数该函数又调用了CCTransitionScene的setNewScene函数在该函数中我们发现程序调用了我们熟悉的ReplaceScene函数前面已经知道了m_pInScene是场景B即程序现在开始执行由场景X切换场景B。由场景X切换场景B:和上面一样我们分析void CCDirector::setNextScene(void) 中当从X切到B时m_pRunningScene 是场景Xm_pNextScene 是场景BB不是场景切换动画类CCTransitionShrinkGrowCCTransitionSceneX是场景切换动画类。那么根据函数逻辑函数流程会走向场景X的onExitXXX和onExit函数但是不会执行场景B的onEnter和onEnterXXX函数。场景X类是CCTransitionShrinkGrow类执行场景X的onExitXXX函数和onExit函数时会进入CCTransitionScene函数的onExit函数由于cocos2dx是类实例指针传递因此这里的实例和上面由A切到X的类实例是一个那么m_pInScene依然是场景Bm_pOutScene依然是场景A在CCTransitionScene函数的onExit函数里场景A的onExit被调用场景B的onEnterXXX被调用。此时整个场景切换过程已经完成。综上可得没有切换动画时调用流程A: onExitTransitionDidStartA: onExitB: onEnterB: onEnterTransitionDidFinish有切换动画时调用流程A: onExitTransitionDidStartB: onEnterA: onExitB: onEnterTransitionDidFinish

相关新闻

VC++ MFC桌面时钟开发:从定时器到系统集成的实战指南

VC++ MFC桌面时钟开发:从定时器到系统集成的实战指南

1. 项目概述与核心价值最近在整理一些老项目,发现很多开发者对VC和MFC的印象还停留在“古老”、“过时”的层面。其实,用VC和MFC来打造一个功能完备的桌面应用,尤其是像多功能时钟这种需要稳定后台运行、实时界面交互的程序,依然是…

2026/7/16 5:41:42阅读更多 →
C++实战:从零构建命令行记账本,掌握文件操作与数据结构设计

C++实战:从零构建命令行记账本,掌握文件操作与数据结构设计

1. 项目概述与核心价值 最近在带几个刚学完C基础语法的实习生,发现他们普遍面临一个困境:书本上的语法都懂,但一到自己动手写个完整的、能跑起来的程序就无从下手。这让我想起了自己当年学编程的经历,光看不动手,知识永…

2026/7/16 5:41:42阅读更多 →
B样条曲线C++实现:从原理到拟合与性能优化

B样条曲线C++实现:从原理到拟合与性能优化

1. 项目概述:从需求到实现的平滑之路在图形学、机器人路径规划、计算机辅助设计乃至数据可视化领域,我们常常面临一个核心问题:如何将一系列离散的、可能带有噪声的控制点,转化为一条光滑、连续且符合特定数学约束的曲线&#xff…

2026/7/16 5:41:42阅读更多 →
C++实现HDLC协议栈:从原理到嵌入式工业通信实战

C++实现HDLC协议栈:从原理到嵌入式工业通信实战

1. 项目概述:为什么要在C里折腾HDLC?如果你在嵌入式、工业通信或者一些老牌通信设备公司的代码里翻过,大概率会碰到HDLC(高级数据链路控制)协议。乍一看,这协议名字里带个“高级”,但其实是上个…

2026/7/16 5:46:46阅读更多 →
PCB设计工程师核心技能与学习路径:从入门到进阶

PCB设计工程师核心技能与学习路径:从入门到进阶

这次我们来聊聊PCB设计工程师这个岗位到底需要掌握哪些技能,哪些内容可以暂时放一放。对于刚入行的工程师来说,最头疼的就是不知道学习重点在哪里,担心学了一堆用不上的东西,反而错过了核心技能。PCB设计工程师主要负责电路板的设…

2026/7/16 5:46:46阅读更多 →
【AI总结】2026年6月 主流国内外大模型总结

【AI总结】2026年6月 主流国内外大模型总结

目录 引言一、 国际主流模型 1. OpenAI GPT 系列2. Anthropic Claude 系列3. Google Gemini 系列4. Meta Llama 系列5. xAI Grok 系列6. 其他值得关注的国际模型 二、 国内主流模型 1. 百度 文心大模型2. 阿里 通义千问3. 腾讯 混元大模型4. 字节跳动 豆包大模型 / 扣子5. 智谱…

2026/7/16 5:46:46阅读更多 →
Java循环控制进阶:while与do..while的实战抉择与break/continue的精准调控

Java循环控制进阶:while与do..while的实战抉择与break/continue的精准调控

1. 为什么需要while和do..while循环?在日常编程中,我们经常遇到需要重复执行某段代码的场景。比如读取用户输入直到输入合法、处理文件中的每一行数据、或者游戏中的主循环。这时候,循环结构就派上用场了。Java提供了三种主要的循环结构&…

2026/7/16 5:46:46阅读更多 →
【2014-01-27】cocos2dx学习笔记:CCNode回调流程

【2014-01-27】cocos2dx学习笔记:CCNode回调流程

[历史归档] 本文原发布于 cstriker1407.info 个人博客,内容为历史存档,仅供参考。 发布时间: 2014-01-27 | 标题:cocos2dx学习笔记:CCNode回调流程 | 分类: 编程 / C &&…

2026/7/16 5:46:46阅读更多 →
VC++ MFC桌面时钟开发:从定时器到系统集成的实战指南

VC++ MFC桌面时钟开发:从定时器到系统集成的实战指南

1. 项目概述与核心价值最近在整理一些老项目,发现很多开发者对VC和MFC的印象还停留在“古老”、“过时”的层面。其实,用VC和MFC来打造一个功能完备的桌面应用,尤其是像多功能时钟这种需要稳定后台运行、实时界面交互的程序,依然是…

2026/7/16 5:41:42阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/15 6:42:19阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/16 6:53:04阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/15 10:54:00阅读更多 →
A--10 Codex Review与GitHub PR工作流实战指南:从代码审查到安全合并

A--10 Codex Review与GitHub PR工作流实战指南:从代码审查到安全合并

摘要:本文系统讲解如何利用Codex App的Review功能与GitHub PR工作流,实现从代码修改到安全合并的完整流程。涵盖Review面板深度使用、/review命令实战、GitHub Connector配置、PR描述撰写技巧,以及常见问题排查方法。通过多个实战案例和流程图,帮助开发者建立高效的AI辅助代…

2026/7/16 0:00:38阅读更多 →
遗传算法解5皇后问题:从Hello World到工业优化的进化实验室

遗传算法解5皇后问题:从Hello World到工业优化的进化实验室

1. 项目概述:为什么用遗传算法解5皇后问题,而不是直接回溯?我带过十几届算法课,也给不少初创团队做过AI架构咨询。每次讲到组合优化问题,学生和工程师的第一反应永远是“写个回溯试试”。这没错——55棋盘上找所有合法…

2026/7/16 0:00:38阅读更多 →
5.1V稳压管输出为何只有4.7V?工作电流与负载影响分析

5.1V稳压管输出为何只有4.7V?工作电流与负载影响分析

前几天调试一个简单的电源模块,用到了5.1V稳压管。电路接好,上电测试,万用表一量——输出居然只有4.7V。第一反应是稳压管坏了,换了一个新的,结果还是4.7V。这让我想起很多初学者都会遇到的困惑:明明标称5.…

2026/7/16 0:00:38阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/15 15:50:47阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/15 8:52:38阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/15 14:06:23阅读更多 →