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

发布时间:2026/7/16 5:49:45

【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

相关新闻

OpenAI技术面试全攻略:算法、系统设计与项目经验解析

OpenAI技术面试全攻略:算法、系统设计与项目经验解析

2026/7/16 5:39:44

最近在技术圈里,OpenAI 的面试体验又成了热门话题。不少开发者分享了自己参与面试的经历,普遍反馈流程专业、题目有深度,特别是对算法基础和系统设计能力的考察很到位。这让很多正在准备面试或对 AI 领域感兴趣的同学跃跃欲试。不过也有网友调…

小白程序员轻松入门AI Agent,抢占高薪赛道学习路线全解析

小白程序员轻松入门AI Agent,抢占高薪赛道学习路线全解析

2026/7/16 5:39:44

本文为想要进入AI Agent领域的程序员提供了一份完整的学习路线。文章首先建议选择Python或Go作为后端开发语言,然后深入讲解了大模型基础,包括提示词工程和LLM基础知识。接着,介绍了LangChain和LangGraph两大核心框架,以及如何从0…

Unity开发中C#泛型约束where的六大类型与实战应用详解

Unity开发中C#泛型约束where的六大类型与实战应用详解

2026/7/16 5:39:44

1. 项目概述:为什么Unity开发者必须掌握泛型约束在Unity项目里写代码,尤其是构建框架、工具或者可复用的系统模块时,我们经常会遇到一个经典困境:想写一个既通用又安全的类或方法。比如,你设计了一个对象池ObjectPool&…

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

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

2026/7/16 5:49:45

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

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

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

2026/7/16 5:49:45

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

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

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

2026/7/16 5:49:45

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

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

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

2026/7/16 5:49:45

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

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

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

2026/7/16 5:49:45

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

OpenAI技术面试全攻略:算法、系统设计与项目经验解析

OpenAI技术面试全攻略:算法、系统设计与项目经验解析

2026/7/16 5:39:44

最近在技术圈里,OpenAI 的面试体验又成了热门话题。不少开发者分享了自己参与面试的经历,普遍反馈流程专业、题目有深度,特别是对算法基础和系统设计能力的考察很到位。这让很多正在准备面试或对 AI 领域感兴趣的同学跃跃欲试。不过也有网友调…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/16 0:35:09

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/13 20:43:19

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/15 0:26:43

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

Python实现跨境电商商品图批量翻译教程

Python实现跨境电商商品图批量翻译教程

2026/7/16 0:09:31

一、问题引入做跨境电商的卖家朋友,你是否遇到过这样的困扰?每次上架新品到亚马逊、Shopee或Lazada等平台,都需要处理大量商品图片的多语言版本。比如上架200款衣服,每款需要翻译成英语、日语、韩语等5种语言,这意味着…

跨境电商多语言商品图翻译方案实现

跨境电商多语言商品图翻译方案实现

2026/7/16 0:09:31

一、问题引入对于做跨境电商的卖家来说,多语言商品图的制作一直是令人头疼的环节。当你准备在亚马逊、Shopee、Lazada等多个平台同步上架新品时,首先遇到的就是图片翻译问题。以一位做家居用品的卖家为例,他需要将200张商品图片中的英文文案全…

Windows系统文件d3dx9_36.dll丢失找不到问题解决

Windows系统文件d3dx9_36.dll丢失找不到问题解决

2026/7/16 0:09:31

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…