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

发布时间:2026/11/5 17:50:37

【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
延伸阅读

更多相关文章

2026/11/4 16:25:31

Unity 2023安装本质:Hub调度、模块化构建与URP默认管线解析

1. 项目概述:这不是“又一个安装教程”,而是Unity开发者绕不开的首道关卡Unity 2023不是某个孤立版本,它是Unity引擎演进路线中承上启下的关键节点——它首次将Universal Render Pipeline(URP)正式设为新建2D/3D项目的…

2026/11/4 23:26:30

基于micro:bit的语音控制智能小车开发指南

1. 项目背景与核心功能这个项目将语音识别套件与micro:bit开发板结合,打造一个能通过语音指令控制的智能小车。这种组合在教育领域特别有价值,因为它能让学生同时学习硬件编程、语音识别和机器人控制三个关键技术点。语音识别小车的基本工作原理是&#…

2026/10/27 5:20:38

Kimi vs 秘塔 AI:AI 聊天 vs AI 搜索怎么选?

Kimi vs 秘塔 AI:AI 聊天 vs AI 搜索怎么选? Kimi 和秘塔 AI 搜索不是同一类产品。Kimi 更像一个能聊天、写作、读文档、做PPT、写代码、跑Agent任务的通用AI助手;秘塔 AI 搜索更像一个无广告、带引用源、能做全网/学术/文库检索的信息搜索与研究工具。选择时不要问“谁更强…

2026/11/5 16:51:33

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被…

2026/11/5 16:26:13

Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6…

2026/11/5 15:00:49

基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享…

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑