欢迎转载:http://blog.csdn.net/fylz1125/article/details/8524081

游戏逻辑其实就像拍摄一部电影,整个过程都由导演来驱动。

游戏中的一个一个关卡,一个一个场景都跟电影中类似。每一个场景都有一些特定的元素,比如林冲风雪山神庙这个场景,大环境就是一个大风雪的夜晚,一个银装素裹的破败山头,有一个破败的山神庙,当然还可以有一些其他的元素,比如火光,野狼,灯光, 乌鸦连声叫、黄狗大声吼等。这就是一个特定的场景了,呵呵。然后导演大叫一声:“Action!”,然后所有的故事情节就在这里展开,主角和一干配角上场了...

以上所有的元素就组成了这么一个场景,那么在游戏里又如何组织这些元素呢。先来看看cocos2d-x的场景处理流程。

cocos2d-x中的导演执行单元就是场景CCScene。一个场景又有那么多元素,比如一个大的背景,然后又有一些小元素,比如星星,火堆,狗等,又是如何加到场景里的呢。

可以这么说,一个场景就是一个特别的容器(其实就是一个CCNode),它能容纳各类节点(通过addChild)。那么跟电影一样,镜头一出来先有一个大的环境。这个就是主背景层(CCLayer),对,就是CCLayer(怎么翻译好一点)。然后在这个主Layer里面再添加一些其他的元素,比如人物、火堆、狂奔的大狗、清唱的小鸟等。这些元素都是独立的对象(继承CCSprite),他们都有各自的属性和行为,比如人物是一个男人,他在漫无目的的行走,火堆在燃烧放出一跳一跳的火光,狗在奔跑,鸟在飞来飞去等。所有这些元素都添加到主Layer里面,然后这个主Layer又被添加都场景里面(CCScene),最后导演执行这个场景(pDirector->runWithScene(pScene)),一个画面就出来了。

来看一看代码级别的执行过程:

主循环(不知道的看我前面的文章)

[cpp] view plaincopyprint?
  1. void CCDisplayLinkDirector::mainLoop(void)
  2. {
  3. if (m_bPurgeDirecotorInNextLoop)
  4. {
  5. m_bPurgeDirecotorInNextLoop = false;
  6. purgeDirector();
  7. }
  8. else if (! m_bInvalid)
  9. {
  10. drawScene();// 注意这里就是画场景了
  11. // release the objects
  12. CCPoolManager::sharedPoolManager()->pop();
  13. }
  14. }

跟进drawScene()看看怎么画的

[cpp] view plaincopyprint?
  1. void CCDirector::drawScene(void)
  2. {
  3. // calculate "global" dt
  4. calculateDeltaTime();
  5. //tick before glClear: issue #533
  6. if (! m_bPaused)
  7. {
  8. m_pScheduler->update(m_fDeltaTime);//按照优先级调度update函数(每个节点都有这么个函数)
  9. }
  10. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  11. /* to avoid flickr, nextScene MUST be here: after tick and before draw.
  12. XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
  13. if (m_pNextScene) // 这个变量存下次绘制的场景,本次绘制则是上一次设置的场景
  14. {
  15. setNextScene();// 注意这个,不要被名字误导,其实就是设置下一次要运行的场景
  16. }
  17. kmGLPushMatrix();
  18. // draw the scene
  19. if (m_pRunningScene)
  20. {
  21. m_pRunningScene->visit();// 注意看这里,这个visit函数就是递归绘制子节点
  22. }
  23. // draw the notifications node
  24. if (m_pNotificationNode)
  25. {
  26. m_pNotificationNode->visit();
  27. }
  28. if (m_bDisplayStats)
  29. {
  30. showStats();
  31. }
  32. kmGLPopMatrix();
  33. m_uTotalFrames++;
  34. // swap buffers
  35. if (m_pobOpenGLView)
  36. {
  37. m_pobOpenGLView->swapBuffers();
  38. }
  39. if (m_bDisplayStats)
  40. {
  41. calculateMPF();
  42. }
  43. }

好,看注释,有个visit函数,这个就是递归绘制子节点的

[cpp] view plaincopyprint?
  1. void CCNode::visit()
  2. {
  3. // quick return if not visible. children won't be drawn.
  4. if (!m_bVisible)
  5. {
  6. return;
  7. }
  8. kmGLPushMatrix();
  9. if (m_pGrid && m_pGrid->isActive())
  10. {
  11. m_pGrid->beforeDraw();
  12. }
  13. this->transform();
  14. CCNode* pNode = NULL;
  15. unsigned int i = 0;
  16. if(m_pChildren && m_pChildren->count() > 0)//这里开始,如果有子节点就进入
  17. {
  18. sortAllChildren();// 按z坐标排序,就是z序排列子节点
  19. // draw children zOrder < 0
  20. ccArray *arrayData = m_pChildren->data;
  21. for( ; i < arrayData->num; i++ )//画z序<0的子节点
  22. {
  23. pNode = (CCNode*) arrayData->arr[i];
  24. if ( pNode && pNode->m_nZOrder < 0 )
  25. {
  26. pNode->visit();
  27. }
  28. else
  29. {
  30. break;
  31. }
  32. }
  33. // self draw
  34. this->draw(); // 画自己
  35. for( ; i < arrayData->num; i++ )
  36. {
  37. pNode = (CCNode*) arrayData->arr[i];
  38. if (pNode)
  39. {
  40. pNode->visit();
  41. }
  42. }
  43. }
  44. else
  45. {
  46. this->draw(); // 没有子节点就画自己
  47. }
  48. // reset for next frame
  49. m_uOrderOfArrival = 0;
  50. if (m_pGrid && m_pGrid->isActive())
  51. {
  52. m_pGrid->afterDraw(this);
  53. }
  54. kmGLPopMatrix();
  55. }

这个是主循环的,但是要运行一个场景是从哪开始的呢,比如

[cpp] view plaincopyprint?
  1. CCScene *pScene = HelloWorld::scene();
  2. // run
  3. pDirector->runWithScene(pScene);

看,第一个场景从这里开始的,跟进

[cpp] view plaincopyprint?
  1. void CCDirector::runWithScene(CCScene *pScene)
  2. {
  3. CCAssert(pScene != NULL, "This command can only be used to start the CCDirector. There is already a scene present.");
  4. CCAssert(m_pRunningScene == NULL, "m_pRunningScene should be null");// 当前运行为NULL(第一次)
  5. pushScene(pScene);// push是什么呢
  6. startAnimation(); // 这里控制帧率,同时又进入主循环
  7. }

看这个pushScene函数,是干什么的

[cpp] view plaincopyprint?
  1. void CCDirector::pushScene(CCScene *pScene)
  2. {
  3. CCAssert(pScene, "the scene should not null");
  4. m_bSendCleanupToScene = false;
  5. m_pobScenesStack->addObject(pScene);// 当前scene入栈
  6. m_pNextScene = pScene; // next Scene,就是下一次绘制当前scene
  7. }

好了,这个pushScene干了两件事,将要绘制的scene入栈,将下次要绘制的场景设为pScene。这个函数返回后接着是

startAnimation(),这个函数调整帧率然后再次进入主循环。

再回头看看主循环的drawScene()函数(上面有),其中有段:

[cpp] view plaincopyprint?
  1. if (m_pNextScene)// 刚才的pushScene函数设置了这个值
  2. {
  3. setNextScene(); // 将下个要运行的Scene给m_pRunningScene
  4. }
  5. kmGLPushMatrix();
  6. // draw the scene
  7. if (m_pRunningScene) // 这里开始渲染当前要运行的Scene
  8. {
  9. m_pRunningScene->visit();
  10. }

看代码有点绕,其实就是一个迭代过程。最开始第一次m_pRunningScene是NULL,然后 runWithScene后就有了,m_pRunningScene就是你传进去的Scene,不过是在下次循环绘制运行。这里有两个过程,一个就是runWithScene函数和replaceScene函数,这两个函数都会设置下个Scene,同时将要运行的Scene入栈。然后进入主循环,在主循环中每次都会检测当前要运行的Scene,如果有就渲染执行。就是这么一个过程。

导演每次只能执行一个场景,执行并不仅仅是绘制,还包括其动作,回调,过渡等。每个场景实质上是一个CCNode,

前面讲过,CCNode有个很重要的成员变量m_pChildren,这是一个CCArray,用来存放添加到该节点的子节点。Scene在渲染的时候会递归渲染其子节点,这就组成一个渲染链,保证整个场景的所有元素都会被渲染。

cocos2d-x游戏开发(十)执行单元场景CCScene相关推荐

  1. Android游戏开发十日通(7)- 开发一个双人游戏

    提要 游戏需要分享才能获得快乐,想想你以前玩过的那些游戏,那些会是真正地存在你婶婶的脑海里?是独自一人躲在被窝里酣战PSP,还是和哥们在网吧一起开黑?是一个人单刷迅龙三连,还是和朋友联机怒刷黄黑龙? ...

  2. iOS cocos2d 2游戏开发实战(第3版)---你的第一个游戏!

    2019独角兽企业重金招聘Python工程师标准>>> 随着苹果公司不断地创新与发展,新的iPhone 5.iPad 4以及iPad mini产品相继问世,包括iOS与Xcode在内 ...

  3. confluence 编辑器这次没有加载_喵的Unity游戏开发之路 - 多场景:场景加载

    如果丢失格式.图片或视频,请查看原文:喵的Unity游戏开发之路 - 多场景:场景加载 很多童鞋没有系统的Unity3D游戏开发基础,也不知道从何开始学.为此我们精选了一套国外优秀的Unity3D游戏 ...

  4. 《Cocos2d 跨平台游戏开发指南(第2版)》一1.9 添加动作到精灵

    本节书摘来异步社区<Cocos2d 跨平台游戏开发指南(第2版)>一书中的第1章,第1.9节,作者: [印度]Siddharth Shekar(谢卡)译者: 武传海 责编: 胡俊英,更多章 ...

  5. APP游戏开发十诫!第一个雏型就要搞定的事

    APP游戏开发十诫!第一个雏型就要搞定的事 半路:在启动游戏 App 项目时,多数开发者都能条列出上百项的重要功能,似乎每个项目都非得完成不可,但到底哪些才是项目早期至关紧要,必须在第一个游戏雏型完成 ...

  6. iOS cocos2d 2游戏开发实战(第3版)

    <iOS cocos2d 2游戏开发实战(第3版)> 基本信息 原书名:Learn cocos2d 2: Game Development for iOS 作者: (美)Steffen I ...

  7. 【通知】▁▂▃ Himi 最新著作《iOS游戏编程之从零开始—Cocos2d-x与cocos2d引擎游戏开发》★书籍源码+第4/5/6样章★-免费下载★ ▃▂▁

    2013年新年,Himi的第二本著作:<iOS游戏编程之从零开始-Cocos2d-x与cocos2d引擎游戏开发>一书正式发售: (大家可以到新华书店.淘宝.拍拍.当当.亚马逊等进行购买) ...

  8. 【Android游戏开发十四】深入Animation,在SurfaceView中照样使用Android—Tween Animation!

     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigame.com/android-game/331.html 很多童鞋说 ...

  9. Cocos2D手机游戏开发之优化篇

    Cocos2D手机游戏开发之优化篇 在这个手机游戏盛行已久的年代,一款产品想要博得更多用户的喜爱就要在细节上做得更加到位.而游戏的优化在这里面起到了非常关键的作用.试想下,一款画面和玩法都深受用户喜欢 ...

最新文章

  1. TextRNN用于文本分类
  2. 用Windows Live Writer发布博客也可以不生成缩略图
  3. UriComponentsBuilder和UriComponents url编码
  4. oracle10 数据库审计,Oracle数据库审计用法实例
  5. python网课答案查询_中国大学慕课Python编程基础期末考试查题公众号答案
  6. Linux内核 eBPF基础: 探索USDT探针
  7. 美团搜索中查询改写技术的探索与实践
  8. C++中两个类中互相包含对方对象的指针问题
  9. 一文看懂二叉搜索树~(又叫二叉查找树) 代码+详解(C/C++)
  10. 数据分析项目实战项目四:亚马逊Kindle书籍多渠道商业分析项目
  11. linux将pdf转为png,将多页PDF转换为PNG并返回(Linux)
  12. WIFI提示“已连接,但无法访问互联网”
  13. 基于JSP学生学籍管理系统
  14. 故宫的首夜,一票难求,网站遭“围攻”宕机
  15. “耀星计划”之华为信用钱包,覆盖HMS生态多领域
  16. php ssl 465,帝国CMS邮件无法发送 SSL465端口无法发送的问题解决办法
  17. 图书馆机器人索书号识别
  18. tcp端对端 ip点对点
  19. 【概率论】设随机变量X~N(0, 1), 则P(X>1)的值为
  20. 微信公众平台SDK JAVA实现WeChat-SDK

热门文章

  1. 初始化方法-在类的外部给对象增加属性的隐患
  2. 数据库(MySQL)
  3. dice系数什么意思_轮胎上的数字和字母是什么意思 轮胎上的红点黄点是什么意思...
  4. c语言中 c2059错误是,解决error C2059: 语法错误:“::”问题
  5. log4j2.xml 的标签 loggers 中 root 的属性 level 指的是什么
  6. 210314阶段三VS使用Linux 的sqlite3 API
  7. 分析工厂模式中的问题并改造
  8. 阿里:马云从未转让和退出淘宝股份 也没有这个打算
  9. A quick introduction to Google test
  10. Linux---一台主机部署多版本mysql服务和mysql实例