coco2dx对象统计及内存查漏

记一次对cocos2dx的对象统计及内存泄露的历程(ps:很老的cocos版本)

对象统计思路:

为了不对引擎造成破话,都是采取帮函数指针、增加借口、多态性的方式,所以不需要再引擎中include包含统计类,当做插件set进去,类似于组件模式,扩展引擎。

1、对象创建时统计:

因为创建对象是通过create接口创建(先不考虑引擎内部new对象的情况,下面会说明怎么避免这个问题),这个借口里又会调用autorelease放到自动释放池中自动管理内存,所以在autorelease里放个函数指针绑定统计函数CNodeCounterLog::newNodeCount(CCObject* _node),里面写统计逻辑

2、对象销毁时统计:

对象销毁时调用的是release,里面会判断引用计数是否为0,0则销毁,所以在这里也放个函数指针绑定统计函数CNodeCounterLog::deleteNodeCount(CCObject* _node) ,里面写统计逻辑

3、统计逻辑里面获取对象及其大小:

可以通过typeid(*_node).name()获取到对象的名称,大小的话sizeof(*_node)获取不到的,不像java可以通过反射获取到对象。所以就定了个反射列表来获取对应的大小:

if (_name == CC_LuaStack) return sizeof(CCLuaStack){}
else if (_name == CC_String) return sizeof(CCString){}
else //为了防止遗漏,把未在反射列表的对象写到本地记录一下
{
char tmp[128];
sprintf(tmp,“——- not found class:%s\n”,_name.c_str());
CCLOG(“%s”,tmp);
CNodeCounterLog::GetInstance()->log(tmp); //未添加经列表的写到日志中,方便添加
return -1;
}

信息结构体
对象名、个数、总大小,对象指针的集合vector

4、统计贴图纹理对象占用的内存:

再纹理缓存集合CCTextureCache中增加个借口让统计类调用获取缓存集合textures,遍历textures,
每个对象的占用计算结果 = width * height * 每个像素格式占用位数 / 8.f,单位byte

5、统计字体纹理对象占用的内存:

直接从统计集合中获取到ccLabelTTF在获取其纹理计算,公式同上。

6、统计lua占用内存:

在lua脚本引擎中增加个获取大小的借口即可,

int CCLuaEngine::getMemSize()
{
lua_State* state = m_stack->getLuaState();
return state ? lua_gc(state,LUA_GCCOUNT,0) : 0;
}

7、实时绘制信息:

利用多态性,统计类继承CCNode,重写visit函数,然后在CCDirector加个CCNode节点,把统计类set进去,每帧调用这个CCNode的visit。

8、规避引擎内不统一的写法造成统计类统计错误的问题:

引擎内部有些地方使用new来创建对象,release销毁对象,会造成统计类里对象不增加,但会减少的情况。所以为了避免这个问题,在CCObject中增加了个标记,只要调用了autorelease进入统计的对象就标记一下,减少的时候判断一下该对象是否为标记过得对象,否则不进入统计逻辑直接返回。

9、黑白名单模式:

通过黑白名单来决定对象是否需要统计,减少不必要的对象统计或者具体统计某些对象。

内存泄露查找

反复打开关闭某个界面几次,看对象统计的总和是否不断增加,如果是则有对象泄露(增量是一样的)。

内存泄露定位

查看是开的是哪个xxx.json,命令行有log,即可查找到对用的lua文件
搜索一下有retain的相关代码,注释掉后再次测一下,如果恢复正常则可以判断是忘了release
搜索一下有removeFromParentAndCleanup(false)的代码,改为true后恢复正常(removeFromParentAndCleanup里面是stopAll定时器、动画)

可以在vs装上lua调试插件BabeLua, 断点追踪,看下创建时和销毁时的地址是否一致

有图有真相

附上代码:

CCNodeCounterDef.h

#ifndef __NODE_DEFINE_H__
#define __NODE_DEFINE_H__

#include <vector>
#include <string>

#define CC_LuaStack "CCLuaStack"
#define CC_String "CCString"
#define CC_Array "CCArray"
#define CC_Bool "CCBool"
#define CC_Integer "CCInteger"
#define CC_LabelAtlas "CCLabelAtlas"
#define CC_TextureAtlas "CCTextureAtlas"
#define CC_Texture2D "CCTexture2D"
#define CC_Dictionary "CCDictionary"
#define CC_HTTPRequest "CCHTTPRequest"
#define CC_Image "CCImage"
#define CC_Sprite "CCSprite"
#define CC_GraySprite "CCGraySprite"
#define CC_Scene "CCScene"
#define CC_LabelTTF "CCLabelTTF"
#define CC_NodeRGBA "CCNodeRGBA"
#define CC_TargetedTouchHandler "CC_TargetedTouchHandler"
#define CC_UIButton "UIButton"
#define CC_Scale9Sprite "CCScale9Sprite"
#define CC_GUIRenderer "GUIRenderer"
#define CC_SpriteBatchNode "CCSpriteBatchNode"
#define CC_Timer "CCTimer"
#define CC_Layer "CCLayer"
#define CC_LayerRGBA "CCLayerRGBA"
#define CC_DrawNode "CCDrawNode"
#define CC_TexturePVR "CCTexturePVR"
#define CC_UILayer "UILayer"
#define CC_UIRootWidget "UIRootWidget"
#define CC_UILabel "UILabel"
#define CC_SchedulerScriptHandlerEntry "CCSchedulerScriptHandlerEntry"
#define CC_NotificationObserver "CCNotificationObserver"
#define CC_UIRectClippingNode "UIRectClippingNode"
#define CC_ProgressTimer "CCProgressTimer"
#define CC_DelayTime "CCDelayTime"
#define CC_Sequence "CCSequence"
#define CC_ZipFile "CCZipFile"
#define CC_AutoreleasePool "CCAutoreleasePool"
#define CC_CallFunc "CCCallFunc"
#define CC_TargetedTouchHandler "CCTargetedTouchHandler"
#define CC_Touch "CCTouch"
#define CC_BMFontConfiguration "CCBMFontConfiguration"
#define CC_LabelBMFont "CCLabelBMFont"
#define CC_Color3bObject "CCColor3bObject"
#define CC_ClippingRegionNode "CCClippingRegionNode"
#define CC_Invocation "CCInvocation"
#define CC_EditBox "CCEditBox"
#define CC_Set "CCSet"
#define CC_MenuItemSprite "CCMenuItemSprite"
#define CC_Menu "CCMenu"
#define CC_ProgressTo "CCProgressTo"
#define CC_AnimationConf "AnimationConf"
#define CC_UILayout "UILayout"
#define CC_UIImageView "UIImageView"
#define CC_UILabelBMFont "UILabelBMFont"
#define CC_MoveToPX "CCMoveToPX"
#define CC_MoveTo "CCMoveTo"
#define CC_FadeOut "CCFadeOut"
#define CC_MoveBy "CCMoveBy"
#define CC_Node "CCNode"
#define CC_AnimationFrame "CCAnimationFrame"
#define CC_Animation "CCAnimation"
#define CC_QtzSprite "QtzSprite"
#define CC_CallFuncN "CCCallFuncN"
#define CC_Animation222 "Animation"
#define CC_Display "Display"
#define CC_Joint "Joint"
#define CC_QtzBone "QtzBone"
#define CC_Animate "CCAnimate"
#define CC_RepeatForever "CCRepeatForever"
#define CC_AnimationClip "AnimationClip"
#define CC_RotateTo "CCRotateTo"
#define CC_QtzZOrderNode "QtzZOrderNode"
#define CC_QtzBoneAnimation "QtzBoneAnimation"
#define CC_ScaleTo "CCScaleTo"
#define CC_Repeat "CCRepeat"
#define CC_Spawn "CCSpawn"
#define CC_FadeTo "CCFadeTo"
#define CC_TintTo "CCTintTo"
#define CC_UIWidget "UIWidget"
#define CC_TouchScriptHandlerEntry "CCTouchScriptHandlerEntry"
#define CC_JumpTo "CCJumpTo"
#define CC_ParticleSystemQuad "CCParticleSystemQuad"
#define CC_EaseExponentialOut "CCEaseExponentialOut"
#define CC_StandardTouchHandler "CCStandardTouchHandler"
#define CC_TintBy "CCTintBy"
#define CC_EaseBackOut "CCEaseBackOut"
#define CC_LayerColor "CCLayerColor"
#define CC_SpriteFrame "CCSpriteFrame"
#define CC_UILoadingBar "UILoadingBar"
#define CC_FadeIn "CCFadeIn"
#define CC_QParticleSpriteQuad "QParticleSpriteQuad"
#define CC_ScaleBy "CCScaleBy"
#define CC_UIListView "UIListView"
#define CC_EaseBackIn "CCEaseBackIn"
#define CC_UILinearLayoutParameter "UILinearLayoutParameter"
#define CC_Show "CCShow"
#define CC_Hide "CCHide"
#define CC_UICheckBox "UICheckBox"
#define CC_UIListViewEx "UIListViewEx"
#define CC_UIListViewSmartAlign "UIListViewSmartAlign"
#define CC_UICCTextField "UICCTextField"
#define CC_UIRelativeLayoutParameter "UIRelativeLayoutParameter"
#define CC_OrbitCamera "CCOrbitCamera"
#define CC_UIScrollView "UIScrollView"
#define CC_UITextField "UITextField"
#define CC_RichText "RichText"

/****************** gloable singleton #define CC_GLProgram "CCGLProgram" #define CC_Configuration "CCConfiguration" #define CC_NotificationCenter "CCNotificationCenter" #define CC_ArmatureDataManager "CCArmatureDataManager" #define CC_DisplayLinkDirector "CCDisplayLinkDirector" #define CC_Scheduler "CCScheduler" #define CC_ActionManager "CCActionManager" #define CC_TouchDispatcher "CCTouchDispatcher" #define CC_KeypadDispatcher "CCKeypadDispatcher" #define CC_ShaderCache "CCShaderCache" #define CC_TextureCache "CCTextureCache" #define CC_SpriteFrameCache "CCSpriteFrameCache" */
std::vector<std::string>    gBlackList;
std::vector<std::string>    gWhiteList;
void gInitBlackList()
{
    //gBlackList.push_back(CC_LuaStack);
    //gBlackList.push_back(CC_String);
    gBlackList.push_back(CC_Array);
    //gBlackList.push_back(CC_Bool);
    //gBlackList.push_back(CC_Integer);
    //gBlackList.push_back(CC_LabelAtlas);
    //gBlackList.push_back(CC_TextureAtlas);
    gBlackList.push_back(CC_Texture2D);
    //gBlackList.push_back(CC_Dictionary);
    //gBlackList.push_back(CC_HTTPRequest);
    //gBlackList.push_back(CC_Image);
    //gBlackList.push_back(CC_Sprite);
    //gBlackList.push_back(CC_GraySprite);
    //gBlackList.push_back(CC_Scene);
    //gBlackList.push_back(CC_LabelTTF);
    //gBlackList.push_back(CC_NodeRGBA);
    //gBlackList.push_back(CC_TargetedTouchHandler);
    //gBlackList.push_back(CC_UIButton);
    //gBlackList.push_back(CC_Scale9Sprite);
    //gBlackList.push_back(CC_GUIRenderer);
    //gBlackList.push_back(CC_SpriteBatchNode);
    gBlackList.push_back(CC_Timer);//sssssssss
    //gBlackList.push_back(CC_Layer);
    //gBlackList.push_back(CC_LayerRGBA);
    //gBlackList.push_back(CC_DrawNode);
    //gBlackList.push_back(CC_TexturePVR);
    //gBlackList.push_back(CC_UILayer);
    //gBlackList.push_back(CC_UIRootWidget);
    //gBlackList.push_back(CC_UILabel);
    gBlackList.push_back(CC_SchedulerScriptHandlerEntry); //sssssssss
    //gBlackList.push_back(CC_NotificationObserver);
    //gBlackList.push_back(CC_UIRectClippingNode);
    //gBlackList.push_back(CC_ProgressTimer);
    gBlackList.push_back(CC_DelayTime);//sssssssss
    //gBlackList.push_back(CC_Sequence);
    gBlackList.push_back(CC_ZipFile);
    gBlackList.push_back(CC_AutoreleasePool);
    gBlackList.push_back(CC_CallFunc);
    gBlackList.push_back(CC_TargetedTouchHandler);
    gBlackList.push_back(CC_Touch);
    gBlackList.push_back(CC_BMFontConfiguration);
    //gBlackList.push_back(CC_LabelBMFont);
    //gBlackList.push_back(CC_Color3bObject);
    gBlackList.push_back(CC_ClippingRegionNode);
    gBlackList.push_back(CC_Invocation);
    //gBlackList.push_back(CC_EditBox);
    gBlackList.push_back(CC_Set);
    //gBlackList.push_back(CC_MenuItemSprite);
    //gBlackList.push_back(CC_Menu);
    gBlackList.push_back(CC_ProgressTo);
    gBlackList.push_back(CC_AnimationConf);
    //gBlackList.push_back(CC_UILayout);
    //gBlackList.push_back(CC_UIImageView);
    //gBlackList.push_back(CC_UILabelBMFont);
    gBlackList.push_back(CC_MoveToPX);
    gBlackList.push_back(CC_MoveTo);
    gBlackList.push_back(CC_FadeOut);
    gBlackList.push_back(CC_MoveBy);
    gBlackList.push_back(CC_Node);
    gBlackList.push_back(CC_AnimationFrame);
    gBlackList.push_back(CC_Animation);
    //gBlackList.push_back(CC_QtzSprite);
    gBlackList.push_back(CC_CallFuncN);
    gBlackList.push_back(CC_Animation222);
    gBlackList.push_back(CC_Display);
    gBlackList.push_back(CC_Joint);
    //gBlackList.push_back(CC_QtzBone);
    gBlackList.push_back(CC_Animate);
    gBlackList.push_back(CC_RepeatForever);
    gBlackList.push_back(CC_AnimationClip);
    //gBlackList.push_back(CC_RotateTo);
    //gBlackList.push_back(CC_QtzZOrderNode);
    //gBlackList.push_back(CC_QtzBoneAnimation);
    gBlackList.push_back(CC_ScaleTo);
    gBlackList.push_back(CC_Repeat);
    gBlackList.push_back(CC_Spawn);
    gBlackList.push_back(CC_FadeTo);
    gBlackList.push_back(CC_TintTo);
    //gBlackList.push_back(CC_UIWidget);
    gBlackList.push_back(CC_TouchScriptHandlerEntry);
    gBlackList.push_back(CC_JumpTo);
    gBlackList.push_back(CC_ParticleSystemQuad);
    gBlackList.push_back(CC_EaseExponentialOut);
    gBlackList.push_back(CC_StandardTouchHandler);
    gBlackList.push_back(CC_TintBy);
    gBlackList.push_back(CC_EaseBackOut);
    gBlackList.push_back(CC_LayerColor);
    //gBlackList.push_back(CC_SpriteFrame);
    //gBlackList.push_back(CC_UILoadingBar);
    gBlackList.push_back(CC_FadeIn);
    gBlackList.push_back(CC_QParticleSpriteQuad);
    gBlackList.push_back(CC_ScaleBy);
    //gBlackList.push_back(CC_UIListView);
    gBlackList.push_back(CC_EaseBackIn);
    gBlackList.push_back(CC_UILinearLayoutParameter);
    gBlackList.push_back(CC_Show);
    gBlackList.push_back(CC_Hide);
    //gBlackList.push_back(CC_UICheckBox);
    //gBlackList.push_back(CC_UIListViewEx);
    gBlackList.push_back(CC_UIListViewSmartAlign);
    //gBlackList.push_back(CC_UICCTextField);
    gBlackList.push_back(CC_UIRelativeLayoutParameter);
    gBlackList.push_back(CC_OrbitCamera);
    //gBlackList.push_back(CC_LabelTTF);
}

void gInitWhiteList()
{
    //gWhiteList.push_back(CC_RichText);
    gWhiteList.push_back(CC_LabelTTF);
    gWhiteList.push_back(CC_UILabel);
    gWhiteList.push_back(CC_Sprite);
    //gWhiteList.push_back(CC_Scale9Sprite);
    gWhiteList.push_back(CC_GUIRenderer);
    gWhiteList.push_back(CC_UIImageView);
    gWhiteList.push_back(CC_LabelBMFont);
    gWhiteList.push_back(CC_HTTPRequest);
    //gWhiteList.push_back(CC_Texture2D);

}

#endif

CCNodeCounter.h

#ifndef __NODE_COUNTER_H__
#define __NODE_COUNTER_H__ 

#include <iostream>
#include <vector>
#include <map>

#include "cocos2d.h"

/* * 改动文件 * CCDirector * CCObject * CCTextureCache * CCTexture2D * CCLuaEngine * GUIReader * document.h */

struct NodeInfo
{
    NodeInfo() : mName(""),mCounter(0),mTotalSize(0),mPerSize(0)
    {
    }
    std::string             mName;
    int                     mCounter;
    int                     mTotalSize;
    int                     mPerSize;
    std::vector<cocos2d::CCObject*> mPtrVec;
};

class CNodeCounterLog : public cocos2d::CCNode
{
public:
    CNodeCounterLog();
    virtual ~CNodeCounterLog();

    static CNodeCounterLog* GetInstance();
    static CNodeCounterLog* gNodeCounterLog;

    void            destory();
    void            initFunc();
    void            initHUD();
    void            initShowBtn();

    static void     newNodeCount(cocos2d::CCObject* _node);
    void            increaseFunc(const std::string _name,int size,cocos2d::CCObject* obj);
    static void     deleteNodeCount(cocos2d::CCObject* _node);
    void            decreaseFunc(const std::string _name,cocos2d::CCObject* obj);
    bool            isBeTraced(const std::string& _name,CCObject* _node,bool _isIncrease);
    bool            isBlackList(const std::string& _name) const;
    bool            isWhiteList(const std::string& _name) const;
    std::string     getTypeName(const cocos2d::CCObject* _node) const; //获取类型名字符串
    std::map<std::string,NodeInfo*>&       getNodeMap() { return mNodeMap; }

    //提供lua掉的接口
    void            setOpen(bool _open) const;
    void            setShowAll(bool _b);
    void            setWhiteCheck(bool _b) { mIsWhite = _b; }
    bool            isWhiteCheck() const { return mIsWhite; }
    void            log(const std::string& _str = ""); //写到本地log

    virtual void    visit() override;//利用node的visit绘制信息
    void            getInfo(std::string& _info,std::string& _info2);
    void            getTextureInfo(std::string& _info,float& _size);
    void            getCCLabelTextureInfo(std::string& _info,NodeInfo* _nodeInfo,float& _size);
    void            getLuaInfo(std::string& _info,float& _size);
    void            getJsonInfo(std::string& _info,float& _size);

private:
    typedef std::map<std::string,NodeInfo*> StrNodeMap;
    StrNodeMap                          mNodeMap;
    bool                                mIsWhite;
    bool                                mShowAll;

    cocos2d::CCNode*                    mParentNode;
    cocos2d::CCLayerColor*              mLayer;
    cocos2d::CCLabelTTF*                mLabelInfo;
    cocos2d::CCLabelTTF*                mLabelInfo2;
};

#define Get_NodeCounter() CNodeCounterLog::GetInstance();

#endif

CCNodeCounter.cpp

#include "CCNodeCounter.h"
#include "cocos2d.h"
#include <typeinfo>
#include "CCNodeCounterDef.h"
#include <fstream> 
#include <algorithm>

#include "CCLuaStack.h"
#include "network/CCHTTPRequest.h"
#include "CocosGUI.h"
#include "CCScale9Sprite.h"
#include "platform/CCZipFile.h"
#include "GUI/BaseClasses/UIWidget.h"
#include "GUI/CCEditBox/CCEditBox.h"
#include "QtzAnimation/AnimationData.h"
#include "QtzAnimation/AnimationClip.h"
#include "QtzAnimation/Animation.h"
#include "QtzAnimation/Display.h"
#include "QtzAnimation/Joint.h"

USING_NS_CC;
USING_NS_CC_EXTRA;
USING_NS_CC_EXT;

const static std::string gCocosNS   =   "::";
const static std::string logFile    =   "d:\\a_counterLog.lua";
const static std::string gLogFormat = "--- [num=%6d] [size=%8.2fkb] [%s]\n";
const static std::string gLogFormatTexture = "--- [num=%6d] [size=%8.2fmb] [%s]\n";
const static std::string gLogTotal = "------- [totalNum=%8u] [totalSize=%10.2lfmb]\n";
const static std::string gLogTotalMemSize = "------- [total Mem=%8.2fmb]\n";
const static int gChangeLine        =    18;

static int GetSizeByName(const std::string& _name)
{
    if (_name == CC_LuaStack) return sizeof(CCLuaStack);
    else if (_name == CC_String) return sizeof(CCString);
    else if (_name == CC_Array) return sizeof(CCArray);
    else if (_name == CC_Bool) return sizeof(CCBool);
    else if (_name == CC_Bool) return sizeof(CCBool);
    else if (_name == CC_Integer) return sizeof(CCInteger);
    else if (_name == CC_LabelAtlas) return sizeof(CCLabelAtlas);
    else if (_name == CC_TextureAtlas) return sizeof(CCTextureAtlas);
    else if (_name == CC_Texture2D) return sizeof(CCTexture2D);
    else if (_name == CC_Dictionary) return sizeof(CCDictionary);
    else if (_name == CC_HTTPRequest) return sizeof(CCHTTPRequest);
    else if (_name == CC_Image) return sizeof(CCImage);
    else if (_name == CC_Sprite) return sizeof(CCSprite);
    else if (_name == CC_GraySprite) return sizeof(CCGraySprite);
    else if (_name == CC_Scene) return sizeof(CCScene);
    else if (_name == CC_LabelTTF) return sizeof(CCLabelTTF);
    else if (_name == CC_NodeRGBA) return sizeof(CCNodeRGBA);
    else if (_name == CC_TargetedTouchHandler) return sizeof(CCTargetedTouchHandler);
    else if (_name == CC_UIButton) return sizeof(UIButton);
    else if (_name == CC_Scale9Sprite) return sizeof(CCScale9Sprite);
    else if (_name == CC_GUIRenderer) return sizeof(GUIRenderer);
    else if (_name == CC_SpriteBatchNode) return sizeof(CCSpriteBatchNode);
    else if (_name == CC_Timer) return sizeof(CCTimer);
    else if (_name == CC_Layer) return sizeof(CCLayer);
    else if (_name == CC_LayerRGBA) return sizeof(CCLayerRGBA);
    else if (_name == CC_DrawNode) return sizeof(CCDrawNode);
    else if (_name == CC_TexturePVR) return sizeof(CCTexturePVR);
    else if (_name == CC_UILayer) return sizeof(UILayer);
    else if (_name == CC_UIRootWidget) return sizeof(UIRootWidget);
    else if (_name == CC_UILabel) return sizeof(UILabel);
    else if (_name == CC_SchedulerScriptHandlerEntry) return sizeof(CCSchedulerScriptHandlerEntry);
    else if (_name == CC_NotificationObserver) return sizeof(CCNotificationObserver);
    else if (_name == CC_UIRectClippingNode) return sizeof(UIRectClippingNode);
    else if (_name == CC_ProgressTimer) return sizeof(CCProgressTimer);
    else if (_name == CC_DelayTime) return sizeof(CCDelayTime);
    else if (_name == CC_Sequence) return sizeof(CCSequence);
    else if (_name == CC_ZipFile) return sizeof(CCZipFile);
    else if (_name == CC_AutoreleasePool) return sizeof(CCAutoreleasePool);
    else if (_name == CC_CallFunc) return sizeof(CCCallFunc);
    else if (_name == CC_TargetedTouchHandler) return sizeof(CCTargetedTouchHandler);
    else if (_name == CC_Touch) return sizeof(CCTouch);
    else if (_name == CC_BMFontConfiguration) return sizeof(CCBMFontConfiguration);
    else if (_name == CC_LabelBMFont) return sizeof(CCLabelBMFont);
    else if (_name == CC_Color3bObject) return sizeof(CCColor3bObject);
    else if (_name == CC_ClippingRegionNode) return sizeof(CCClippingRegionNode);
    else if (_name == CC_Invocation) return sizeof(CCInvocation);
    else if (_name == CC_EditBox) return sizeof(CCEditBox);
    else if (_name == CC_Set) return sizeof(CCSet);
    else if (_name == CC_MenuItemSprite) return sizeof(CCMenuItemSprite);
    else if (_name == CC_Menu) return sizeof(CCMenu);
    else if (_name == CC_ProgressTo) return sizeof(CCProgressTo);
    else if (_name == CC_AnimationConf) return sizeof(AnimationConf);
    else if (_name == CC_UILayout) return sizeof(UILayout);
    else if (_name == CC_UIImageView) return sizeof(UIImageView);
    else if (_name == CC_UILabelBMFont) return sizeof(UILabelBMFont);
    else if (_name == CC_MoveToPX) return sizeof(CCMoveToPX);
    else if (_name == CC_MoveTo) return sizeof(CCMoveTo);
    else if (_name == CC_FadeOut) return sizeof(CCFadeOut);
    else if (_name == CC_MoveBy) return sizeof(CCMoveBy);
    else if (_name == CC_Node) return sizeof(CCNode);
    else if (_name == CC_AnimationFrame) return sizeof(CCAnimationFrame);
    else if (_name == CC_Animation) return sizeof(CCAnimation);
    else if (_name == CC_QtzSprite) return sizeof(QtzSprite);
    else if (_name == CC_CallFuncN) return sizeof(CCCallFuncN);
    else if (_name == CC_Animation222) return sizeof(Animation);
    else if (_name == CC_Display) return sizeof(Display);
    else if (_name == CC_Joint) return sizeof(Joint);
    else if (_name == CC_QtzBone) return sizeof(QtzBone);
    else if (_name == CC_Animate) return sizeof(CCAnimate);
    else if (_name == CC_RepeatForever) return sizeof(CCRepeatForever);
    else if (_name == CC_AnimationClip) return sizeof(AnimationClip);
    else if (_name == CC_RotateTo) return sizeof(CCRotateTo);
    else if (_name == CC_QtzZOrderNode) return sizeof(QtzZOrderNode);
    else if (_name == CC_QtzBoneAnimation) return sizeof(QtzBoneAnimation);
    else if (_name == CC_ScaleTo) return sizeof(CCScaleTo);
    else if (_name == CC_Repeat) return sizeof(CCRepeat);
    else if (_name == CC_Spawn) return sizeof(CCSpawn);
    else if (_name == CC_FadeTo) return sizeof(CCFadeTo);
    else if (_name == CC_TintTo) return sizeof(CCTintTo);
    else if (_name == CC_UIWidget) return sizeof(UIWidget);
    else if (_name == CC_TouchScriptHandlerEntry) return sizeof(CCTouchScriptHandlerEntry);
    else if (_name == CC_JumpTo) return sizeof(CCJumpTo);
    else if (_name == CC_ParticleSystemQuad) return sizeof(CCParticleSystemQuad);
    else if (_name == CC_EaseExponentialOut) return sizeof(CCEaseExponentialOut);
    else if (_name == CC_StandardTouchHandler) return sizeof(CCStandardTouchHandler);
    else if (_name == CC_TintBy) return sizeof(CCTintBy);
    else if (_name == CC_EaseBackOut) return sizeof(CCEaseBackOut);
    else if (_name == CC_LayerColor) return sizeof(CCLayerColor);
    else if (_name == CC_SpriteFrame) return sizeof(CCSpriteFrame);
    else if (_name == CC_UILoadingBar) return sizeof(UILoadingBar);
    else if (_name == CC_FadeIn) return sizeof(CCFadeIn);
    else if (_name == CC_QParticleSpriteQuad) return sizeof(QParticleSpriteQuad);
    else if (_name == CC_ScaleBy) return sizeof(CCScaleBy);
    else if (_name == CC_UIListView) return sizeof(UIListView);
    else if (_name == CC_EaseBackIn) return sizeof(CCEaseBackIn);
    else if (_name == CC_UILinearLayoutParameter) return sizeof(UILinearLayoutParameter);
    else if (_name == CC_Show) return sizeof(CCShow);
    else if (_name == CC_Hide) return sizeof(CCHide);
    else if (_name == CC_UICheckBox) return sizeof(UICheckBox);
    else if (_name == CC_UIListViewEx) return sizeof(UIListViewEx);
    else if (_name == CC_UIListViewSmartAlign) return sizeof(UIListViewSmartAlign);
    else if (_name == CC_UICCTextField) return sizeof(UICCTextField);
    else if (_name == CC_UIRelativeLayoutParameter) return sizeof(UIRelativeLayoutParameter);
    else if (_name == CC_OrbitCamera) return sizeof(CCOrbitCamera);
    else if (_name == CC_UIScrollView) return sizeof(UIScrollView);
    else if (_name == CC_UITextField) return sizeof(UITextField);
    else
    {
        char tmp[128];
        sprintf(tmp,"------- not found class:%s\n",_name.c_str());
        CCLOG("%s",tmp);
        CNodeCounterLog::GetInstance()->log(tmp); //未添加经列表的写到日志中,方便添加
        return -1;
    }
}

CNodeCounterLog* CNodeCounterLog::gNodeCounterLog = NULL;

CNodeCounterLog::CNodeCounterLog() 
: mIsWhite(false),mParentNode(NULL),mLabelInfo(NULL),mLabelInfo2(NULL),mShowAll(true)
{
    mNodeMap.clear();
}

CNodeCounterLog::~CNodeCounterLog()
{
    for (StrNodeMap::iterator iter = mNodeMap.begin(); iter != mNodeMap.end(); ++iter)
    {
        if (iter->second != nullptr)
            delete iter->second;
    }
    setOpen(false);
    CCDirector::sharedDirector()->setNodeCounter(NULL);
    mNodeMap.clear();
    mLayer->removeFromParentAndCleanup(true);
    mLabelInfo->removeFromParentAndCleanup(true);
    mLabelInfo2->removeFromParentAndCleanup(true);
    //TODO: 不知道为啥析构时这里老是蹦,所以上面释放子节点
    //CC_SAFE_RELEASE(mParentNode); 
}

CNodeCounterLog* CNodeCounterLog::GetInstance()
{
    if (!gNodeCounterLog)
    {
        gNodeCounterLog = new CNodeCounterLog();
        gNodeCounterLog->initFunc();
    }
    return gNodeCounterLog;
}

void CNodeCounterLog::destory()
{
    if (gNodeCounterLog)
    {
        delete gNodeCounterLog;
        gNodeCounterLog = NULL;
    }
}

void CNodeCounterLog::initFunc()
{
    setOpen(true);
    setWhiteCheck(false);
    gInitBlackList();
    gInitWhiteList();
    initHUD();

    CCDirector::sharedDirector()->setNodeCounter(this); //将这个类作为插件设置进去,以便每帧调用visit绘制
}

void CNodeCounterLog::initHUD()
{
    mParentNode = CCNode::create();
    mParentNode->retain();//retain父节点就行

    float scale = 1.5f;
    float alpha = 255.f;
    ccColor3B fontc = ccc3(255.f,255.f,255.f);
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    mLayer = CCLayerColor::create(ccc4(0.f,0.f,100.f),size.width,size.height);
    mLayer->setAnchorPoint(ccp(0.f,0.f));
    mLayer->setPosition(ccp(0.f,0.f));

    mLabelInfo = CCLabelTTF::create();
    mLabelInfo->setAnchorPoint(ccp(0.f,1.f));
    mLabelInfo->setPosition(ccp(0.f,size.height));
    mLabelInfo->setScale(scale);
    mLabelInfo->setOpacity(alpha);
    mLabelInfo->setColor(fontc);

    mLabelInfo2 = CCLabelTTF::create();
    mLabelInfo2->setAnchorPoint(ccp(0.f,1.f));
    mLabelInfo2->setPosition(ccp(size.width/2.f,size.height));
    mLabelInfo2->setScale(scale);
    mLabelInfo2->setOpacity(alpha);
    mLabelInfo2->setColor(fontc);

    mParentNode->addChild(mLayer);
    mParentNode->addChild(mLabelInfo);
    mParentNode->addChild(mLabelInfo2);
}

void CNodeCounterLog::setOpen(bool _open) const
{
    if (_open)
    {
        void(*pfunNew)(CCObject*) = &CNodeCounterLog::newNodeCount;
        void(*pfunDelete)(CCObject*) = &CNodeCounterLog::deleteNodeCount;
        CCObject::SetNodeCounterFunc(pfunNew,pfunDelete); //绑定函数到ccobject中
    }
    else
    {
        CCObject::SetNodeCounterFunc(NULL,NULL);
    }
}

void CNodeCounterLog::setShowAll(bool _b)
{
    mShowAll = _b;
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    if (_b)
    {
        mLayer->setContentSize(CCSize(size.width,size.height));
        mLayer->setPosition(0.f,0.f);
    }
    else
    {
        float width = 400.f;
        float height = 130.f;
        mLayer->setContentSize(CCSize(width,height));
        mLayer->setPosition(0.f,size.height - height);
    }

}

void CNodeCounterLog::newNodeCount(CCObject* _node)
{
    CNodeCounterLog* pLog = CNodeCounterLog::GetInstance();
    std::string typName(pLog->getTypeName(_node));
    _node->mIsAutoRelease = true;

    if (pLog->isWhiteCheck())
    {
        if (!pLog->isWhiteList(typName))
            return;
    }
    else
    {
        if (pLog->isBlackList(typName)) 
            return;
    }

    int size = ::GetSizeByName(typName);
    pLog->increaseFunc(typName,size,_node);
}

void CNodeCounterLog::increaseFunc(const std::string _name,CCObject* obj)
{
    CNodeCounterLog* pLog = CNodeCounterLog::GetInstance();
    StrNodeMap& nodeMap = pLog->getNodeMap();

    isBeTraced(_name,obj,true);

    bool isExist = false;
    for (StrNodeMap::iterator iter = nodeMap.begin(); iter != nodeMap.end(); ++iter)
    {
        if (_name == iter->first)
        {
            NodeInfo* nodeInfo = iter->second;
            nodeInfo->mCounter++;
            nodeInfo->mTotalSize += size;
            nodeInfo->mPtrVec.push_back(obj);
            isExist = true;
            break;
        }
    }
    if (!isExist)// 不存在,新建
    {
        NodeInfo* newNodeInfo = new NodeInfo();
        newNodeInfo->mName = _name;
        newNodeInfo->mCounter = 1;
        newNodeInfo->mTotalSize = size;
        newNodeInfo->mPerSize = size;
        newNodeInfo->mPtrVec.push_back(obj);
        nodeMap.insert(std::make_pair(_name,newNodeInfo));
    }
}

void CNodeCounterLog::deleteNodeCount(CCObject* _node)
{
    if (!_node->mIsAutoRelease)
        return;

    CNodeCounterLog* pLog = CNodeCounterLog::GetInstance();
    std::string typName(pLog->getTypeName(_node));
    if (pLog->isWhiteCheck())
    {
        if (!pLog->isWhiteList(typName))
            return;
    }
    else
    {
        if (pLog->isBlackList(typName))
            return;
    }

    int size = ::GetSizeByName(typName);
    pLog->decreaseFunc(typName,_node);
}

void CNodeCounterLog::decreaseFunc(const std::string _name,false);

    for (StrNodeMap::iterator iter = nodeMap.begin(); iter != nodeMap.end(); ++iter)
    {
        if (_name == iter->first)
        {
            NodeInfo* nodeInfo = iter->second;
            nodeInfo->mCounter--;
            nodeInfo->mTotalSize -= size;
            for (std::vector<CCObject*>::iterator ptrIter = nodeInfo->mPtrVec.begin(); ptrIter != nodeInfo->mPtrVec.end(); ++ptrIter)
            {
                if (*ptrIter == obj)
                {
                    nodeInfo->mPtrVec.erase(ptrIter);
                    break;
                }
            }

            if (nodeInfo->mCounter == 0)
                nodeMap.erase(iter);
            break;
        }
    }
}

//追踪具体的某个对象
bool CNodeCounterLog::isBeTraced(const std::string& _name,bool _isIncrease)
{
    return false;

    const char* tmp = _name.c_str();
    //if (strcmp(tmp,CC_UILayout) == 0)
    //{
    // UIWidget* layout = dynamic_cast<UIWidget*>(_node);
    // if (layout)
    // {
            char logStr[128] = { 0 };
            if (_isIncrease)
                sprintf(logStr,"--- Increase %s\t\t:0x%x\n",tmp,_node);
            else
                sprintf(logStr,"--- Decrease %s\t\t:0x%x\n",_node);
            log(logStr);

    // return true;
    // }
    //}
    return false;
}

bool CNodeCounterLog::isBlackList(const std::string& _name) const
{
    for (std::vector<std::string>::const_iterator iter = gBlackList.begin(); iter != gBlackList.end(); ++iter)
    {
        if (_name == *iter)
            return true;
    }
    return false;
}

bool CNodeCounterLog::isWhiteList(const std::string& _name) const
{
    for (std::vector<std::string>::const_iterator iter = gWhiteList.begin(); iter != gWhiteList.end(); ++iter)
    {
        if (_name == *iter)
            return true;
    }
    return false;
}

std::string CNodeCounterLog::getTypeName(const cocos2d::CCObject* _node) const
{
    std::string typName(typeid(*_node).name());
    short lastpos = typName.find_last_of(gCocosNS); //干掉前缀class coocs2d::
    if (lastpos == std::string::npos)
    {
        assert(false,"--------- typName is not cocos2d::");
        return typName;
    }
    return  typName.substr(lastpos + 1,typName.length() - lastpos - 1);;
}

void CNodeCounterLog::log(const std::string& _str /* = "" */)
{
    std::ofstream osOutFile(logFile.c_str(),std::ios::app);
    if (!osOutFile.is_open())
    {
        osOutFile.close();
        assert(false,"--- Error: write file error");
        return;
    }
    osOutFile << _str;
    osOutFile.close();
}

void CNodeCounterLog::visit()
{
    std::string info("");
    std::string info2("");
    getInfo(info,info2);
    if (mParentNode && mLabelInfo && mLabelInfo2) 
    {
        mLabelInfo->setString(info.c_str());
        mLabelInfo2->setString(info2.c_str());
        mParentNode->visit();
    }
    else
        assert(false,"--- Error: display node null");
}

void CNodeCounterLog::getInfo(string& _info,std::string& _info2) 
{
    std::string allInfo("");
    std::string allInfo2("\n");
    unsigned int totalNum = 0;
    unsigned int totalSize = 0;
    int flag = 0;
    float totalMem = 0.f;

    std::string labelTextureInfo("");
    for (StrNodeMap::const_iterator iter = mNodeMap.begin(); iter != mNodeMap.end(); ++iter)
    {
        //cclabel纹理信息
        getCCLabelTextureInfo(labelTextureInfo,iter->second,totalMem);

        totalNum += iter->second->mCounter;
        totalSize += iter->second->mTotalSize;
        char tmp[128] = { 0 };
        sprintf(tmp,gLogFormat.c_str(),iter->second->mCounter,(float)iter->second->mTotalSize/1024.f,iter->second->mName.c_str());
        if (flag < gChangeLine) // 挂在另一个节点显示
            allInfo.append(tmp);
        else
            allInfo2.append(tmp);
        flag++;
    }

    //纹理信息
    std::string textureInfo("");
    getTextureInfo(textureInfo,totalMem);

    //lua大小
    std::string luaInfo("");
    getLuaInfo(luaInfo,totalMem);

    //json缓存大小
    std::string jsonInfo("");
    getJsonInfo(jsonInfo,totalMem);

    char tmp1[128] = { 0 };
    char tmp2[128] = { 0 };
    float totalMb = (float)(totalSize / 1024) / 1024.f;
    totalMem += totalMb;

    sprintf(tmp1,gLogTotalMemSize.c_str(),totalMem);
    sprintf(tmp2,gLogFormatTexture.c_str(),totalNum,totalMb,"CCNodes");

    _info.append(tmp1); //total
    _info.append(textureInfo);
    _info.append(labelTextureInfo);
    _info.append(luaInfo);
    _info.append(jsonInfo);
    _info.append(tmp2); //total

    if (mShowAll)
    {
        _info.append("----------- split -----------\n");
        _info.append(allInfo);
        _info2.append(allInfo2);
    }
}

void CNodeCounterLog::getTextureInfo(std::string& _info,float& _size)
{
    CCDictionary* textures = CCTextureCache::sharedTextureCache()->getAllTextures();
    unsigned int counter = 0;
    unsigned int totalBytes = 0;

    CCDictElement* pElement = NULL;
    CCDICT_FOREACH(textures,pElement)
    {
        CCTexture2D* tex = (CCTexture2D*)pElement->getObject();
        unsigned int bpp = tex->bitsPerPixelForFormat();
        unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8;
        totalBytes += bytes;
        counter++;
    }

    if (totalBytes > 0)
    {
        float totalMb = (float)(totalBytes / 1024) / 1024.f;
        _size += totalMb;
        char tmp[128] = { 0 };
        sprintf(tmp,counter,CC_Texture2D);

        //if (totalMb > 150.f)
        // CCTextureCache::sharedTextureCache()->removeUnusedTextures();

        _info.append(tmp);
    }
}

void CNodeCounterLog::getCCLabelTextureInfo(std::string& _info,float& _size)
{
    if (strcmp(_nodeInfo->mName.c_str(),CC_LabelTTF) != 0)
        return;

    unsigned int totalBytes = 0;
    for (std::vector<CCObject*>::const_iterator iter = _nodeInfo->mPtrVec.begin(); iter != _nodeInfo->mPtrVec.end(); ++iter)
    {
        CCLabelTTF* label = dynamic_cast<CCLabelTTF*>(*iter);
        if (label)
        {
            CCTexture2D* tex = label->getTexture();
            unsigned int bpp = tex->bitsPerPixelForFormat();
            if (bpp != -1)
            {
                unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8;
                totalBytes += bytes;
            }
            else
            {
                int a = 1;
            }
        }
    }

    if (totalBytes > 0)
    {
        float totalMb = (float)(totalBytes / 1024) / 1024.f;
        _size += totalMb;
        char tmp[128] = { 0 };
        sprintf(tmp,_nodeInfo->mPtrVec.size(),CC_LabelTTF);

        /*if (totalMb > 150.f) //缓存纹理超过150自动清除unusedTex CCTextureCache::sharedTextureCache()->removeUnusedTextures();*/

        _info.append(tmp);
    }
}

void CNodeCounterLog::getLuaInfo(std::string& _info,float& _size)
{
    int size = CCLuaEngine::defaultEngine()->getMemSize();
    if (size > 0)
    {
        char tmp[128] = { 0 };
        float totalMb = (float)size / 1024.f;
        _size += totalMb;
        sprintf(tmp,1,CC_LuaStack);
        _info.append(tmp);
    }
}

void CNodeCounterLog::getJsonInfo(std::string& _info,float& _size)
{
    unsigned int totoal = 0;
    int num = 0;
    std::map<std::string,rapidjson::Document *>* jsonMap = GUIReader::shareReader()->getJsonCache();
    if (jsonMap)
    {
        for (std::map<std::string,rapidjson::Document *>::iterator iter = jsonMap->begin(); iter != jsonMap->end(); ++iter)
        {
            totoal += iter->second->sizeTmp;
            num += 1;
        }
    }

    if (totoal > 0)
    {
        char tmp[128] = { 0 };
        float totalMb = (float)(totoal / 1024) / 1024.f;
        _size += totalMb;
        sprintf(tmp,num,"JsonCache");
        _info.append(tmp);
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是