cocos2d-x基本⾯试题
1、 阐述cocos2d-x的启动执⾏-退出流程.和⼀些基础对象
⾃⼰归纳:1.游戏启动流程:从main.cpp的Application::getInstance()->run();进⼊游戏,调⽤的就是 AppDelegate 之中的实现。⽽我们在此⽅法中我们了⼀些变量,创建了第⼀个 CCScene 场景等,之后的控制权,便全权交给了 CCDirector::sharedDirector()->mainLoop(); ⽅法了。CCApplication 到 CCDirector再下⼀步mainLoop();
游戏的运⾏以场景为基础,每时每刻都有⼀个场景正在运⾏,其内部有⼀个场景栈,遵循后进后出的原则,当我们显⽰的调⽤ end()⽅法,或者弹出当前场景之时,其⾃动判断,如果没有场景存在,也会触发 end() ⽅法,以说明场景运⾏的结束,⽽游戏如果没有场景,就像演出没有了舞台,程序进⼊最后收尾的⼯作,通过修改变量 m_bPurgeDirecotorInNextLoop 促使在程序 mainLoop ⽅法之内调
⽤ purgeDirector ⽅法。 m_pobOpenGLView->end(); ⽅法,在这⾥结束了 游戏进程。程序运⾏时期,由 mainLoop ⽅法维持运⾏着游戏之内的各个逻辑,当在弹出最后⼀个场景,或者直接调⽤ CCDirector::end(); ⽅法后,触发游戏的清理⼯作,执⾏ purgeDirector ⽅法,从⽽结束了 CCEGLView(不同平台不同封装,PC使⽤OpenGl封装,移动终端封装的为 OpenGl ES) 的运⾏,调⽤其 end() ⽅法,从⽽直接执⾏ exit(0); 退出程序进程,从⽽结束了整个程序的运⾏。(Android 平台的 end() ⽅法内
部通过Jni ⽅法terminateProcessJNI(); 调⽤ Java 实现的功能,其功能⼀样,直接结束了当前运⾏的进程)
2、 你使⽤过的cocos开发相关的⼯具有哪些?
c++ 版本 ⽤VS 最好2013以上版本。 如果你有mac电脑xcode⾃然妥妥的。移植Android需要eclipse或者android sutdio。如果需要编写lua 就配个sublime text+插件。如果做⼿机页游(javascript)⽤官⽅的creator。
TiledMap (地图编辑器)ParticleEditor(粒⼦编辑器)cocosBuilder(可视化编辑)Texture Packer(图⽚组合⼯具)plistEditor⼯具等。
3、阐述cocos2d-x 中Scene Layer Sprite Node Action之间的关系和区别
xcode入门开始:Director类直接继承的是Ref类,Node继承的也是Ref类,action也是继承Ref类和Clonable类,⽽Layer,sprite都是继承的Node 类是它的⼦类。
5、 描述下⼀个Node从创建然后添加到其他节点上,然后再移除,到销毁.哪些node的函数被调⽤到了?顺序是什么?
分步骤:1.创建⼀个Node节点,调⽤create函数;2.添加到其他节点上,调⽤addchild函数3.移除的话可以通过removerFromParent函数(这个函数还是要调⽤removeFromParentAndCleanup,默认参数为True)4.根据3步骤的函数⾥⾯涉及到Node的销毁的⼀些步骤,先调⽤removeChild,再调⽤detachChild,在这个函数⾥⾯有个重要的判断(1.退出运⾏的2.清除所有⼦节点的运⾏的(否则定时器之类的不会停⽌依旧在运⾏))so,先调⽤(onExitTransitionDidStart,再调⽤onExit),再调⽤cleanup函数(这⾥⾯会先调⽤stopAllActions,unscheduleAllCallbacks,最后会遍历所有⼦节点从⽽移除所有的定时器)最后还要把他们的parent给置为end,所以要调⽤setParent。
6、cocos如何管理内存中的对象
⽬前主要有两种实现智能管理内存的技术,⼀种是引⽤计数,⼀种是垃圾回收。Cocos2d-x采⽤的是引⽤计数机制。为此实现了⾃⼰的根类CCObject,每个对象都包含了⼀个⽤来控制⽣命周期的引⽤计数器,就是CCObject的成员变量m_uReference。
对于m_uReference,构造函数创建时对该引⽤计数器赋值为1(⾃引⽤,并没有实际的使⽤),当需要引⽤对象时调⽤retain()⽅法增1,当引⽤结束的时候调⽤release()⽅法减⼀。⽽autorelease()⽅法(create⼯⼚⽅法迫切需要)会将对象放⼊⾃动回收池(CCAutoReleasePool)实现灵活的垃圾回收。当每⼀帧结束的时候,⾃动回收池中的对象都会被执⾏⼀次release()
autorelease()⽅法⾥⾯代码将该对象添加到⾃动释放池中:CCPoolManager::sharedPoolManager()->addObject(this);
create⽅法将对象加⼊内存池后,对象的所有权已经属于内存池了, 我们返回的指针其实是没有所有权的. 主循环mainloop⼲了件⾮常重要的事情, 那就是pop最上层的autorelease pool, 此时是在release全部仅仅由此内存池所有的对象. 就是依靠这样的原理, 我们可以放⼼的将对象放在autorelease pool中, 知道在需要的时候, 这个对象就能正确的释放, 同时只要有上层的⽗节点通过addChild对游戏对象有了所有权以后, ⼜能正确的保证该对象不会被删除.
7、cocos2dx的屏幕适配⽅案?
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(720, 480, kResolutionShowAll);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(720, 480, kResolutionExactFit);
kResolutionUnKnown:
这是 cocos2d-x 编写的默认模式,没有做任何处理,在这种情况下,游戏画⾯的⼤⼩与⽐例都是不可控的
kResolutionExactFit:
牺牲了画质⽽保持了全屏显⽰,对画⾯进⾏了拉伸,意味着相对极端情况下,本来精灵是⽅形的,显⽰出来变成长⽅形,本来圆形的变成了椭圆,固此模式不推荐使⽤。
kResolutionShowAll:
为了保持设计画⾯⽐例对四周进⾏留⿊边处理,使得不同⽐例下画⾯不能全屏。鱼和熊掌不能兼得
kResolutionNoBorder:
此模式可以解决两个问题,其⼀:游戏画⾯全屏;其⼆:保持设置游戏时的宽⾼⽐例,相⽐ kResolutionShowAll 有所区别的是,为了填补留下的⿊边,将画⾯稍微放⼤,以⾄于能够正好补齐⿊边,⽽这样做的后果可想⽽知,补齐⿊边的同时,另⼀个⽅向上将会有⼀部分画⾯露出屏幕之外。
8、Cocos的更新机制是怎么实现的?
简单描述⾃⼰理解的热更新机制,简单来说就是下载的时候,判断是否有新的(改动的过的⽂件或新增⽂件),是则下载,否则跳过。
function UpdateInfo:checkVersion() -- 低于最低版本,必须更新app
if GTab.MIN_APP_VERSION and compareVersion(str2Tab(GTab.MIN_APP_VERSION), str2Tab(GTab.APP_VERSION)) > 0then
.... ....return alert:updateApp()
end
local local_version = str2Tab(GTab.VERSION_UPDATE)
local server_version = str2Tab(GTab.VERSION_SERVER)
local ret = compareVersion( local_version, server_version ) -- 没有更新地址
if GTab.RESOURCE_URL == nil or GTab.RESOURCE_URL == ""then
return self:finishHandler()
end-- 内部开发不⾛版本号更新
if GTab.CHANNEL_ID == "debug"t_test then
return self:updatePatch()
end-- 版本相同, 不需要更新
if ret == 0and lang_ret == 0then
return self:finishHandler()
end-- 本地版本⼤于服务器版本
if ret > 0or lang_ret > 0then
removeDir( GTab.UPDATE_RES_PATH )
end
self:updatePatch()
end
简单判断的话分这⼏个部分:⽐较版本号,匹配更新地址,服务器版本。如何判断是否更新结束(需要添加标记),需要在加⼊的更新的时候把需要添加的更新的加⼊更新列表,然后最后判断更新列表是否为空。但是为了避免由于异步产⽣造成的,时间偏差,列表空偏差,那么正确的判断还得判断是否还有正在下载的⽂件。
9、cocos⾥有⼏种event⽅案?其实现过程和原理是什么?
1、使⽤步骤
(1)获取事件分发器 :dispatcher = Director::getInstance()->getEventDispatcher();
(2)创建 :auto listener = EventListenerTouchOneByOne::create();
(3)绑定响应事件函数:listener->onTouchBegan = CC_CALLBACK_2(callback, this);
(4)将添加到事件分发器dispatcher中:dispatcher->addEventListenerWithSceneGraphPriority(Listener, this);
(5)编写回调响应函数:bool callback(Touch* touch, Event* event) { ... }
10、能不能⽤多线程处理cocos的逻辑?为什么?协程⾏不⾏?
不⾏,在 Cocos2d-x 中,最⼤的线程安全隐患是内存管理。引擎明确声明了 retain、release 和 autorelease 三个⽅法都不是线程安全的。如果在不同的线程间对同⼀个对象作内存管理,可能会出现严重的内存泄露或野指针问题。协程可以。
1.Sleep()函数是使得线程休眠的函数,这个函数不跨平台,仅仅在windows上能⽤,其他平台使⽤usleep。
2.在⾮主线程中不能使⽤cocos2d-x管理内存的CCObject::retain(), CCObject::release() 者CCObject::autorelease(),因为CCAutoreleasePool不是线程安全的,OPENGL的上下⽂也不是线程安全的,所以不要再⾮主线程中使⽤cocos2d-x的API和UI操作。cocos2dx内存管理与多线程问题: Cocos2d-x的内存管理采⽤Objective-C的机制,⼤喜过望。因为只要坚持Objective-C的原则“谁创建谁释放,谁备份谁释放”的原则即可确保内存使⽤不易出现Bug。
11、cocos的有⼏种设计模式?
1.单例模式
其实就是静态全局对象,实现上⼀个静态成员变量,⼀个静态成员函数,构造函数私有化,和静态全
局变量的区别是实例化的时机是可控制的。
2.观察者模式
注册通知
__NotificationCenter::getInstance()->addObserver(this, callfuncO_selector(ALayer::callBack), MSG_STATE, NULL);
解除通知
__NotificationCenter::getInstance()->removeObserver(this, MSG_STATE);
投送通知
__NotificationCenter::getInstance()->postNotification(MSG_STATE, s);
通知回调函数
void ALayer::callBack(cocos2d::Ref *sender) { log("ALayer callBack"); __String *str = (__String*)sender; Label* label = (Label*)this->getChildByTag(100); if (label) label->setString(str->ge
tCString()); }
3.⼯⼚模式
⼯⼚模式其实就是⽤⼀个⼯⼚类封装new过程。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论