从面试开始

    xiaoxiao2021-12-14  21

    1.内存管理机制

    Cocos2d-x所采用的内存管理方式是引用计数。通过给每个对象维护一个引用计数器,记录该对象被引用的次数。每当对象增加一次引用时,引用计数+1,对象失去一次引用时,引用计数-1。当对象引用计数为0时,标志着该对象生命周期结束,将被自动回收,delete this。 cocos2d-x中的create方法就是,在方法中new 一个对象,此时引用计数+1,然后调用autorelease方法,将其加入自动释放池中。(若此时使用addChild方法添加子节点。那么引用计数还会+1),当这个对象析构时,就会调用release方法引用计数-1。引用计数为0,说明此自动释放池中没有对象,这个自动释放池会自动释放掉。

    2.精灵帧缓存和纹理缓存

    1.精灵帧缓存:用来处理多张图合成的图集。一张图集中包含若干小图。把截取好的图片信息保存在一个plist文件中(可以用TexturePacker制作)。然后将其加入精灵帧缓存中。方便以后直接从精灵帧缓存中调用。节省内存。 2.纹理缓存:当游戏需要大量加载纹理时会十分的占用内存资源。故,可以将纹理图片预先异步加载进纹理缓存中,之后直接使用即可,节省图片加载时所消耗的大量内存。 cache也使用了引用计数的机制,防止缓存被释放掉。

    3.如何实现一个暂停窗口

    之前面试问过如何实现一个暂停窗口(即不释放旧场景,并创建一个新场景):可以使用PushScene(将正在运行的场景暂停,并压入栈)和PopScene(将栈中场景恢复并出栈)。 replaceScene,pushScene,popScene执行过程:

    使用pushScene将helloworld场景切换到setting场景

    使用popScene实现setting场景回到helloworld场景

    使用replaceScene实现从helloworld场景进入setting场景

    4.减少内存开销的措施

    1.及时释放内存,减少泄露。 2.重用资源。 3.延迟加载,逐帧加载。 4.使用缓存,将图片打包成图集。 5.降低图片质量。 6.尽量减少jpg格式的使用,因为会转化为png。

    5.屏幕自适应

    1.将涉及物体位置的坐标应该根据原点(origin)加上其坐标位置。 2.尽量不要用getWinSize来获取屏幕大小,使用getVisibleSize。

    EXACT_FIT :拉伸变形,是屏幕铺满。 NO_BORDER :等比缩放,全屏铺满不留黑边。 SHOW_ALL :按比例放缩,全部展示不裁剪。 FIXED_WIDTH :按比例放缩,宽度铺满屏幕。 FIXED_HEIGHT :按比例放缩,高度铺满屏幕。 横竖屏幕转换: AndroidManifest.xml文件中 (1)android:screenOrientation = “landscape” //横屏显示(默认) (2)android:screenOrientation = “portrait” //竖屏显示

    6.一些渲染及其效率的问题问题

    1.cocos的图形渲染机制:使用OpenGL。

    顶点着色(顶点坐标变幻等一系列操作)———>几何着色器(添加或删除部分顶点)———>光栅化(把数据信息转化成像素信息)———>片段着色器(把像素显示到屏幕上)着色器==其他操作(比如深度测试,光线叠加等) CCApplication::sharedApplication()->run()—>CCDirector::sharedDirector()->mainLoop()—>drawScene();

    2.使用图集减少DrawCall:

    使用图集减少draw call是有一定前提条件的,图集并不是减少draw call的直接条件。 真正减少draw call是需要多个连续绘制的节点使用同样的贴图时,可以一次性批量绘制 举个栗子 当你有A, B, C三种节点,其中A, B使用同一张贴图(在同一个图集中),C使用另一张贴图 假设绘制顺序是: A C B 这种情况下是无论任何引擎都无法减少draw call的,因为A绘制完需要替换贴图,然后绘制B之后再替换贴图,最后绘制C。 draw call:3 假设绘制顺序是: A B C 那么是可以做到将A, B同时绘制,最后绘制C draw call:2 如果你需要达到这样的效果,需要将所有使用同一个图集的Sprite对象用SpriteBatchNode来管理起来,这样SpriteBatchNode就可以一次性绘制自身所有的子结点(WebGL模式下)。 在Cocos2d-x 3.x中,已经做到了自动批处理,所以省去了用户的一些操作,但是当你想要最大化这种效应的时候,还是建议使用SpriteBatchNode从逻辑上自己控制 以上讨论都是基于WebGL,Canvas模式不具备批处理的能力,所以draw call数量无论是否使用SpriteBatchNode都无法减少,必然是一个对象一个对象的绘制,但是SpriteBatchNode依然可以在一定程度上提高性能。 此外,Layer的bake方法也可以有效得减少draw call。

    7.Cocos2DX中json文件的解析

    1.首先引入两个头文件

    #include"json/rapidjson.h" #include"json/document.h"

    2.创建数据的结构体

    Struct PersonData { int id; string name; }

    3.创建数据管理类包含解析json文件的函数和一个同来存放该数据的容器

    Class PersonDataManager { public: void loadFile(const char* filePath); private: std::vector<PersonData*> vecPerson; } //loadFile实现 void PersonDataManager::loadFile(const char* filePath) { std::string strPath=FileUtile::getInstance()->fullPathForFileName(filePath); std::string strData = FileUtils::getInstance()->getStringFromFile(strPath); rapidjson::Document doc; doc.Parse<0>(strData.c_str()); if(doc.isArray()) { for(int i=0;i<doc.Size();i++) { rapidjson::Value& vPerson=doc[i]; PersonData* data=new PersonData(); data->id=vPerson["id"].GetInt(); data->name=vPerson["name"].GetString(); } vecPerson->push_back(data); } }

    8.CocosStudio的使用

    1.在CocosStudio中制作好场景后,发布。生成csb文件。 2.在代码中使用如下代码调用

    //加入场景根节点 Node rootNode=CSLoader::createNode("_Scene/sceneName.csb"); this->addChild(rootNode); //如果想要获取CocosStudio中的UI则可以使用获取根的子节点然后强制类型转换。 //例: Button* button=static_cast<Button*>(rootNode->getChildByName("buttonName"));

    9.cocos的基础框架

    简单点用一个图来表示吧

    导演(Dirctor) 控制整个游戏的组织和控制核心,场景(Scene)、层(Layer)、精灵(Sprite)等均由导演控制。 场景(Scene) 继承于节点(Node),相当于用户所看到的游戏界面,里面管理着层(Layer)、精灵(Sprite)等游戏物体。在游戏过程中场景是唯一存在的。只能运行一个场景。 层(Layer) 继承于节点(Node),由场景所管理。一个场景可以有多个层。 精灵(Sprite) 继承于节点(Node),精灵即是游戏物体。一个场景可以存在多个精灵。

    转载请注明原文地址: https://ju.6miu.com/read-969428.html

    最新回复(0)