cocos2d-x基本面试题

1、  阐述cocos2d-x的启动执行-退出流程.和一些基础对象

 

自己归纳:1.游戏启动流程:从main.cppApplication::getInstance()->run();进入游戏,调用的就是 AppDelegate 之中的实现。而我们在此方法中我们初始化了一些变量,创建了第一个 CCScene 场景等,之后的控制权,便全权交给了 CCDirector::sharedDirector()->mainLoop(); 方法了。CCApplicationCCDirector再下一步mainLoop();

游戏的运行以场景为基础,每时每刻都有一个场景正在运行,其内部有一个场景栈,遵循后进后出的原则,当我们显示的调用 end() 方法,或者弹出当前场景之时,其自动判断,如果没有场景存在,也会触发 end() 方法,以说明场景运行的结束,而游戏如果没有场景,就像演出没有了舞台,程序进入最后收尾的工作,通过修改变量 m_bPurgeDirecotorInNextLoop 促使在程序 mainLoop 方法之内调用 purgeDirector 方法。 m_pobOpenGLView->end(); 方法,在这里结束了 cocos2d-x 游戏进程。程序运行时期,由 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之间的关系和区别

开始: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))  > 0 then        

         .... ....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" or self.tencent_test then        

return self:updatePatch()    

end      -- 版本相同, 不需要更新    

if ret == 0 and lang_ret == 0 then        

return self:finishHandler()    

end          -- 本地版本大于服务器版本    

if ret > 0 or lang_ret > 0 then        

removeDir( GTab.UPDATE_RES_PATH )    

end

self:updatePatch()

end

简单判断的话分这几个部分:比较版本号,匹配更新地址,服务器版本。如何判断是否更新结束(需要添加标记),需要在加入的更新的时候把需要添加的更新的加入更新列表,然后最后判断更新列表是否为空。但是为了避免由于异步产生造成的,时间偏差,列表空偏差,那么正确的判断还得判断是否还有正在下载的文件。

9、cocos里有几种event方案?其实现过程和原理是什么?

参考:https://www.cnblogs.com/mmidd/p/3782484.html

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->getCString());
}

3.工厂模式

工厂模式其实就是用一个工厂类封装new过程。
 

 

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值