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(); 方法,在这里结束了 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过程。