给 想转2dx 却无从下手的aser

本贴是达叔从as3转到2dx的心路历程
对于没有任何C艹基础的人来说,也许会有帮助。建议从头到尾看一遍。里面的问题相信你也能遇到。
会陆续更新。
写不对的欢迎指正。






Ctrl + , (逗号) 是打开某个类 就是FB里的 Ctrl + Shift + R
Ctrl + K ,+ D 是代码格式化 (先按K,再按D)
注释是 Ctrl + K ,+ C
反注释是 Ctrl + K ,+ U
删除整行:Control + L ( FB是Ctrl + D )
格式化整个块:Ctrl+K+F
重命名 shift + alt + R
查看上次阅读处反上次查看处:Control + "-" Control + Shift + "-"   (很长用的快捷键,fb 里的 alt + 左右)
还有以前按住Ctrl 再鼠标点击的东西 现在都是F12
代码提示 Ctrl+J


int billy [5];
int billy [5] = { 16, 2, 77, 40, 12071 }; 
int billy [] = { 16, 2, 77, 40, 12071 };  // 不写个数也可以
如果我们声明一个全局数组(在所有函数之外),则它的内容将被初始化为所有元素均为0。
char * terry = "hello";

删除
delete pRet; 
pRet = NULL;   

if ( pRet && pRet->init() )
{
    这个和as3一样
} 

遍历nodeCCArray * pChildrenArray = this->getChildren();  
CCLayer* child = NULL;  
CCObject* pObject = NULL;  

CCARRAY_FOREACH( pChildrenArray, pObject  )
{
    child = (CCLayer*)pObject;  
    if(!child)
    break;  
    //child->dosomething();  
}

for (int i = 0; i < int( arr->count() ); i++)
{
CCLabelTTF* test = (CCLabelTTF*)( arr->objectAtIndex(i) );
test->setPosition( ccp(400,300 + 60 * i) );
CCLog("length::%d" , i );
}

输出int型

CCLog("length::%d" , i );


http://www.ityran.com/archives/2105

在项目上右键添加 -> 类,一次生成cpp 和 h 文件,这是我一个初学者想到的,也是最基本的需求。
但是这样文件的位置无法改变。所以必须用添加项,h 和 cpp 分开添加,然后指定目录。还能更麻烦点吗?

想做socket,看教程,教程里之字没提导包的事,试了半天没有想要的包。后来知道需要的配置下。

加载plist文件

CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("1.plist");
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("2.plist");

CCSprite *sp = CCSprite::createWithSpriteFrameName("test.jpg");

this->addChild(sp); 

就这么简单,他会自动管理缓存里的文件。
只要知道名字就行,可恶的是需要知道后缀。
不过他的管理方式已经比as3还简单了。

http://www.cnblogs.com/sambird/archive/2013/07/18/3197562.html 

cocos2d-x在使用CCScale9Sprite的时候需要注意,因为使用到了扩展库所以要
在项目属性中的C/C++的附加包含目录中,添加$(SolutionDir)extensions,设置include路径
在连接器的输入中,添加libExtensions.lib,这个库文件位于cocos2d-x编译结果目录中(Debug.win32)
接下来需要在源码中加入相应的代码,首先是添加头文件及名字空间

#include "cocos-ext.h" 
USING_NS_CC_EXT;  
交叉编译的时候要注意在Android.mk中要加
$(call import-module,extensions)
方可编译成功


CCTexture2D *tt2d = CCTextureCache::sharedTextureCache()->addImage("1.png");

CCSpriteBatchNode *qb = CCSpriteBatchNode::createWithTexture(tt2d);
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("1.plist",tt2d);
关于这个管理混乱的问题,可以参看这个文章
http://blog.csdn.net/sdhjob/article/details/8227181 讲的特别详细

想实现这个的话。。。
"ying" + ( int(i / 2) + 1) + ".jpg"  就得这样
char nameStr[100] = {0};
memset( nameStr, 0, sizeof(nameStr) );
sprintf( nameStr,  "fish%d_%d%d.png" ,  13   ,   i / 10  ,  i%10  );

移动的时候会用到的
但是快速移动的时候会有很大延迟,没找到更好的办法。
CCSetIterator iter1 = pTouches->begin();
CCTouch *t1 = (CCTouch*)(*iter1);
iter1++;

ccpSub( getLocation(), getPreviousLocation() );  计算两点距离的宏

移动的话 这么写就行 直接相加 操作符已经重载了 
node->setPosition( t1->getDelta() + node->getPosition() );

关于大小的问题。
as3里直接width height
2dx要麻烦些。

http://blog.csdn.net/bill_ming/article/details/9078781  

CCNode类的setPosition,getPosition函数如果是一个Node的Child则获取的坐标就是该Node的本地坐标
另一个关键问题就是在cocos2d-x里就是各种对象的大小问题。
因为在cocos2d-x里CCNode对象有缩放的方法setScaleX和setScaleY。
所以在获取对象大小的时候必须根据情况明确指定获取对象原始大小,还是缩放后的大小。
当然cocos2d-x里提供了对应函数来完成这些操作:

getContentSize 函数来获得节点原始的大小。只是逻辑尺寸,不是像素
boundingBox 函数来获得经过缩放和旋转之后的外框盒大小。
getContentSizeInPixels 获得的是像素点大小 

无论是搞2d还是3d开发,最需要搞清楚的就是坐标系,这部分混乱的话就没啥奔头了。
所以玩cocos2d,一上来就先把各种与坐标有关的东西搞清楚。

基本的两个坐标系:屏幕坐标系和GL坐标系。
屏幕坐标系x轴朝右,y轴朝下。默认原点在左上角。这个和as一样。
GL坐标系x轴朝右,y轴朝上。默认原点在左下角。

在调用任何需要设置位置的函数,或从函数获取位置信息前,必须要明确这个函数使用哪个坐标系。

比如调用CCNode类的setPosition函数, 它使用的就是GL坐标系。
比如在处理触摸事件时CCTouch对象中的坐标就是  屏幕坐标系。(左上角的)


另一个重要的坐标系就是和Node相关的本地坐标系。

这个结构和一般做3D用的场景树的概念是一样的。

所以从Node拿到的位置是该节点的本地坐标,需要通过特定的函数才能把本地坐标转换为世界坐标。
而且这里的坐标都用的是GL坐标系。在CCNode对象中有几个方便的函数可以做坐标转换。

convertToWorldSpace方法可以把基于当前node的本地坐标系下的坐标转换到世界坐标系中。
convertToNodeSpace方法可以把世界坐标转换到当前node的本地坐标系中。

另一个关键的问题就是在cocos2d里面就是各种对象的大小问题。
因为在cocos2d里CCNode对象有缩放的方法setScaleX和setScaleY。
所以在获取对象大小的时候就必须根据情况明确指定获取对象原始大小,还是缩放后的大小。
当然cocos2d里提供了对应的函数来完成这些操作。

getContentSize 函数用来获得节点原始的大小。
boundingBox 函数用来获得经过缩放和旋转之后的外框盒大小。

举个简单的例子:
bool ret = CCRect::CCRectContainsPoint(
this->boundingBox() , this->getParent()->convertTouchToNodeSpace( pTouch ));
这个例子的功能是来判定当前的触摸操作是否发生在自己的node对象上。其中pTouch是CCTouch对象的指针,包含了当前触摸事件发生点的坐标。

CCRectContainsPoint这个函数用来判断一个点是否在一个矩形范围内。我们就想用这个函数来判断当前触摸操作的这个点是否在当前node的范围内。
this->boundingBox() 方法获得了当前节点对象在父节点对象下的缩放之后的本地坐标大小,并且是用GL坐标系表示的。

pTouch对象中的坐标是屏幕坐标系,所以必须转换到GL坐标系,再转换到父节点的本地坐标下。
好在convertTouchToNodeSpace这个函数一次完成了这两个转换,可以参考该库的源码,其中有具体的计算过程。

所有数据都转换到同一个坐标系下了以后,就可以通过CCRectContainsPoint函数完成最终的判定操作。

最后想说的一点是,尽可能用相对坐标。换句话说,程序中所有对象在设置大小和位置时,都应该以父对象的大小和位置为依据。
这样程序发布在以各种不同的分辨率发布时,只需要调整根对象的大小就可以了。




比如你的node scale是2
那么点击你的node 坐标是多少?
坐标是未放大的。。。
比如你点的x 200 
但给你的是100 明白?

双手缩放

CCSetIterator iter1 = pTouches->begin();//第一个点
CCPoint p1  = ((CCTouch*)(*iter1))->getPreviousLocation(); //getPreviousLocationInView();
CCPoint p11 = ((CCTouch*)(*iter1))->getLocation(); //getLocationInView();
别用注释的那个 y是反的 坐标系很重要
iter1++;
//第二个点
CCPoint p2  = ((CCTouch*)(*iter1))->getPreviousLocation();
CCPoint p22 = ((CCTouch*)(*iter1))->getLocation();

float dis1 = p1.getDistance(p2);  //旧的距离
float dis2 = p11.getDistance(p22);//新的距离

float olds = node->getScale();

//旧的中点
float oldx = ( p1.x + p2.x ) / 2;
float oldy = ( p1.y + p2.y ) / 2;

CCPoint oldp = node->convertToNodeSpace( ccp(oldx,oldy) );

float news = dis2/dis1 * olds;
node->setScale( news );

//新的中点
float newx = ( p11.x + p22.x ) / 2;
float newy = ( p11.y + p22.y ) / 2;

//偏移了多少
//我需要知道 缩放的是 地图里的哪个点
//想让变大后的图的 oldp点 显示在 newWorldP位置上

float ax = -( oldp.x * news - newx );
float ay = -( oldp.y * news - newy );

node->setPosition(ax,ay);

拼接45度角地图时,会出现缝隙 或者拼接小图时也会有缝,咋办?

sb = CCSpriteBatchNode::create("1.png");
1.sb->getTexture()->setAliasTexParameters();
node->addChild(sb);
char *abc = "ca*.png";
CCSprite *t2d = CCSprite::createWithSpriteFrameName(abc);

2.t2d->getTexture()->setAliasTexParameters();

在 1 和 2 任意一个地方设置都可以。 这句话的意思是 设置贴图无锯齿的属性。
不过这个方法设置的图在拖动的时候会有缝隙,比之前的更恶劣。
然后用了这个

修改 ccConfig.h  将
    #define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 0 
    改为
    #define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 1
这样就完美解决了(至少我们游戏是搞定了)


还有其他方法 请看这  http://blog.csdn.net/yuanhong2910/article/details/7163539


2dx四大缓存区

CCTextureCache; 图片纹理

CCSpriteFrameCache; 精灵
CCAnimationCache; 动画
CCShaderCache; 着色器

Cocos2D-x中的单例如下:
CCDirector, CCTextureCache, CCSpriteFrameCache, CCAnimationCache, CCUserDefault,CCNotificationCenter,CCShaderCache,CCScriptEngineManager,CCFileUtils,SimleAudioEngie。

cocos2d-x中的事件机制
这个和puremvc那个一样。相当好用。

//发送事件
CCNotificationCenter::sharedNotificationCenter()->postNotification(CLICK_TEST_MSG, (CCObject*)data);

//监听事件
void GameManager::initListener()
{
    CCNotificationCenter::sharedNotificationCenter()->
    addObserver( this, callfuncO_selector(GameManager:nClickTest), CLICK_TEST_MSG, NULL);
}

//处理事件
void GameManager:nClickTest(CCObject* obj)
{
   CCMessageBox("onClickTest", "Title");
  //移除监听事件
   CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, CLICK_TEST_MSG);
} 

http://blog.csdn.net/crayondeng/article/details/11677457 

为什么用 do while
http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html 

如果要用gettimer()
那就在update里 累计加delta

关于定时器:也就是timer
单位都是秒
this->scheduleOnce(schedule_selector(HelloWorld::MutUpdate), 5.0f); 只执行一次  
this->unscheduleAllSelectors(); 停止所有的计时器
this->unscheduleUpdate(); 取消默认的update调用
this->unschedule(schedule_selector(HelloWorld::MutUpdate));  取消自定义的


this->schedule(schedule_selector(HelloWorld::MutUpdate), 1.0f); 1秒执行一次
this->schedule(schedule_selector(HelloWorld::MutUpdate));

this->scheduleUpdate();

void HelloWorld::update( float fDelta )

我不需要知道你有多少帧之动画创建辅助类
http://www.benmutou.com/blog/archives/59

今天遇到的问题 11.25日

声明了一个  CCDictionary *di;  属性




在menu点击事件里死活得不到。。
经过义青老师指导,发现原来是忘记 retain(); 

以后记住。。数据类型的要retain呀
别忘了释放啊~

最恶心的数据转换
在做数据转换时,最好包含以下头文件
#include <iostream>
#include <cmath>
#include <string> 
#include <sstream>
USING_NS_CC;
using namespace std;

在2d-x中,也有一个格式刷:CCString ( 数据转换常常找她做中间人 )
那么我们要转换类型,
可先将起始数据类型刷成CCString然后再转成目的数据类型,
这个方法比较方便且实用。

int 转 CCstring
int num = 5;
CCString* ns = CCString::createWithFormat("%d",num);

CCstring 转 int
int px = ns->intValue();//将CCString 转换为int的方法,转成float类型有 floatValue()

CCString 转  char
const char *string= ns->getCString();

char 转  CCString
CString.Format(”%s”,char *)//char 转cstring 
CCString* ns=CCString::createWithFormat("%s",char *);

string 转  char
const char *string = std::string("STRING").c_str();

char 转 string

string s(char *);

string  转 int
std::string s("1234");
int n = std::atoi(s.c_str());//函数原型int atoi(const char *);

int 转 string
int a = 3;
CCString* ns = CCString::createWithFormat("%d",a);
string s = ns->m_sString;

string 转 CCString
std::string str = "123";
CCString* ns = CCString::createWithFormat("%s",str.c_str());

CCString 转 string
std::string s = ns->m_sString;//ns是一个CCString*类型

char 转  int
char *buf = "1122";
int n = std::atoi(buf);

int 转 char
int a = 3;
CCString* ns = CCString::createWithFormat("%d",a);
const char* s = ns->getCString();

看了这么多 我只想说 转你妹夫啊。。。

action的用法
CCScaleTo *scale1 = CCScaleTo::create( 0.1f , 1.2f );
CCScaleTo *scale2 = CCScaleTo::create( 0.1f , 0.8f);
CCScaleTo *scale3 = CCScaleTo::create( 0.1f , 1.1f );
CCScaleTo *scale4 = CCScaleTo::create( 0.1f , 0.9f );
CCScaleTo *scale5 = CCScaleTo::create( 0.1f , 1.0f );
CCFiniteTimeAction* action = CCSequence::create(scale1,scale2,scale3,scale4,scale5,NULL);
bu->runAction(action);

CCScaleTo *scale0 = CCScaleTo::create( 0.2f , 1.2f );CCScaleTo *scale1 = CCScaleTo::create( 0.2f , 1.0f );
CCActionInterval *a1 = CCEaseElasticOut::create(scale0);
CCActionInterval *a2 = CCEaseElasticOut::create(scale1);
CCFiniteTimeAction* action1 = CCSequence::create(a1,a2,NULL);
bu->runAction(action1); 

cocos2dx中一个action结束后想正确使用回调函数
CCFiniteTimeAction *actionOne = CCSequence::create(  
    CCScaleTo::create(1.0f,0.5f,1.5f),  
    CCFadeIn::create(1.0f),  
    CCCallFunc::create(this,callfunc_selector(xx::menuSetVisableFalse)),  
    NULL  
);  

11.26日的bug
CCDictionary的setObject 传入的是  const std::string& key 
然后我传进去的是char *
用 allKeysForObject 方法往外倒这些key 用std::string 和 char 都接不对。妈蛋的 是我语法不对?来回试了好几次。
进源码一看,返回的数组里存的是CCString.....
妈蛋的 api 你倒是说一声啊 每个方法都让我看源码啊?

关于menu 
menu->alignItemsHorizontally();
这个一开始就设置

然后每插入一个对象都要设置这句
menu->alignItemsHorizontallyWithPadding(tabWid);





CCPointZero 这是0,0点 不用你ccp(0,0)了

关于CCTexture2D的问题
starling里的texture 都是独立的 无论你是从纹理集里拿出来的 还是单独的
但,你永远不要高估2dx的作者的设计能力。
他们把CCSpriteFrame和CCSprite里的纹理概念不一样。
CCSpriteFrame里得到的是整个plist里加载的纹理。

所以,你要这样设置

CCSpriteFrame *spriteFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("ying1.jpg");

CCSprite *s = (CCSprite *)cell->getChildByTag(9001);
s->setDisplayFrame( spriteFrame ) 
2dx 你也有脸叫自己引擎
好好跟人家starling学学吧

CCControlButton

CCControlButton *btn1 = CCControlButton::create();
CCSpriteFrame *a10 = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("ying2.jpg");


btn1->setBackgroundSpriteFrameForState( CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("ying1.jpg") , CCControlStateNormal );


btn1->setBackgroundSpriteFrameForState( CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("ying2.jpg") , CCControlStateHighlighted );


this->addChild(btn1);
btn1->setPosition(ccp(300,300));
btn1->setPreferredSize( a10->getOriginalSizeInPixels() );
btn1->addTargetWithActionForControlEvents(this,cccontrol_selector(MoneyPanel::click1),CCControlEventTouchUpInside);

void MoneyPanel::click1(CCObject* pSender, CCControlEvent event)
{
    CCLog("aaaaaaaaaaaa");
}


触摸的封装
cocos2dx的封装和as3完全不是一个级别的。
所以最好自己封装一下。
http://mayingchen003.blog.163.com/blog/static/1626818420138442507/
这个没测试过


有时你想用组件,必须导入类库。
方法就在这
http://blog.csdn.net/pomme_qixiaohu/article/details/8838162
初学者容易绊在这里

addChild 方法的坑
里面介绍的明白。
Adds a child to the container with z-order as 0. 
不像as3一样加到最后面,而是加到最前面。。。
而且 你把他加到一个现实列表里 再加到另一个里会报错 因为他不会自动移除 一点不智能

遇到这个报错时。。 
一定是类名 或者 命名空间名 
就是没导入.h文件顺便说一句,头文件只需要在.h里include一遍就可以了 

单例的写法


h里 
static MoneyPanel* getInstance(); 

cpp里

static MoneyPanel* instance;
MoneyPanel* MoneyPanel::getInstance()
{
    if( instance == NULL )
    {
        instance = MoneyPanel::create();
    }
    return instance;
} 
static是用::访问的 包括静态变量

关于全局静态变量的区别
在h里写静态变量是不行的
static bool aaa;
这样会报错 得用其他方法 暂时没看见 乖乖用方法吧

今天遇到一个问题

d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.h(7): error C2011: “MoneyPanel”:“class”类型重定义
1>          d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.h(7) : 参见“MoneyPanel”的声明
1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(24): error C2027: 使用了未定义类型“MoneyPanel”
1>          d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.h(7) : 参见“MoneyPanel”的声明
1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(24): error C2062: 意外的类型“void”
1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(25): error C2143: 语法错误 : 缺少“;”(在“{”的前面)
1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(25): error C2447: “{”: 缺少函数标题(是否是老式的形式表?)
1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(237): error C2027: 使用了未定义类型“MoneyPanel”
1>          d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.h(7) : 参见“MoneyPanel”的声明
1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(241): error C2027: 使用了未定义类型“MoneyPanel”
1>          d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.h(7) : 参见“MoneyPanel”的声明

1>d:cocos2d-x-2.2projectsfarmgameclassesmoneypanel.cpp(241): error C3861: “create”: 找不到标识符

百思不得其解
后来查出来是因为没加   #pragma once
我戳~~

局部变量如果是new出来的 需要delete吗?他占用的内存会在方法结束时释放吗?
答案是必须delete ,内存不会自动释放
具体看这个
http://bbs.csdn.net/topics/10426927

返回局部new的对象怎么样呢?答案是最好不要~请看 
不要返回局部变量的引用,也不要返回new生成的对象的引用
http://blog.sina.com.cn/s/blog_40965d3a0101eaiq.html

所以2dx的create方法得到的数据能够返回还是很不错的

char*  和 char[ ] 有什么区别?
http://blog.csdn.net/yahohi/article/details/7427724

char *c1 = "abc";  实际上先是在文字常量区分配了一块内存放"abc",然后在栈上分配一地址给c1并指向

这块地址,然后改变常量"abc"自然会崩溃
然而char c2[] = "abc",实际上abc分配内存的地方和上者并不一样

一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于

数据结构中的栈。
2、堆区(heap)— 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据

结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态

变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统
释放。
4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。
5、程序代码区

printf,sprintf,vsprintf 区别?
http://blog.csdn.net/anye3000/article/details/6593551

函数指针

void (*p[10])(void(*)());//我了个去,谁能告诉我这句话什么意思?

正解:*p[10]是一个指针数组,数组中的指针指向的是一些函数,这些函数参数为void(*)(),返回值为空。参数部分的void(*)()是一个指向无参数,返回值为空的函数的函数指针。

上面的声明可以分步完成:
首先,声明一个无参数,返回值为空的函数指针
typedef void (*pfv)();

接着,声明一个函数指针,该函数指针指向一个参数为pfv,返回值为空的函数指针
typedef void (*pFunc_taking_pfv)(pfv);

最后,声明一个含有10个这样的函数指针的数组
pFunc_taking_pfv arrayFunc[10];

C/C++之回调函数
http://www.cnblogs.com/chenyuming507950417/archive/2012/01/02/2310114.html

指针函数与函数指针的区别
http://www.cnblogs.com/gmh915/archive/2010/06/11/1756067.html


typedef 的 define 区别
http://www.cnblogs.com/kerwinshaw/archive/2009/02/02/1382428.html

说下define的特殊用法,他还可以这么用,里面可以传参数
#define max(x,y) (x)>(y)?(x)y); 
具体看这个
http://blog.163.com/wk_technology/blog/static/13078835920091158041771/ 
http://blog.csdn.net/sanmaofly/article/details/4164308

typedef void (CCObject::*SEL_CallFunc)(); //声明一个函数指针 SEL_CallFunc就是指向函数的指针 他两边的圆括号是必须的
这个东西就相当于int a 里的int 一旦需要你就要写一遍那么长的玩意儿 太麻烦 所以用typedef给他简化下
所以以后直接用SEL_CallFunc来表示这个指针


#define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR) 

SEL_CallFunc action;
CCObject *target;
void Tabnavigator::setTabChangeFun( CCObject *_target , SEL_CallFunc action_ )
{
    target = _target;//这个是监听方法
    action = action_;
}

(target->*action)(); //这个是调用

tab->setTabChangeFun( this  ,  callfunc_selector( MoneyPanel::tabChangeFun )  ); //这个就是监听了



所以 2dx里的函数回调展开其实是这样的
当你传入的时候 其实是
tab->setTabChangeFun(this, callfunc_selector(MoneyPanel::tabChangeFun) );
( SEL_CallFunc ) ( &MoneyPanel::tabChangeFun )

函数指针怎么用呢?
一般来说是这样
char (*pFun)(int); 



char glFun(int a){ return;} 
void main() 
{
    pFun = glFun; 
    (*pFun)(2); 
}

先声明一个 空着扔那儿就行了,然后给他赋值调用。搞定! 


如果你重写了父类的方法 那么必须调用一下

今天就发生了一个超级诡异的玩意儿

void Tabnavigator:nEnter()
{
    CCNode::onEnter();
}

一开始没写CCNode的onEnter ,结果鼠标事件消失了。。  

今天的bug 12.12 
新建了一个类,vs提示 构造函数不能有返回类型
找了半天才发现,头文件的最后没加分号。。
class Cangku : public cocos2d::CCNode
{
};  

装插件的话,写起来比较简单,开头class 后面的都帮你搞定

筛选器和文件夹的区别
筛选器只是看起来放到里面了,其实他还在原来的位置。
所以include的时候不要看错(include需要包含文件夹),或者自己手动创建文件夹。
创建筛选器之后,要注意工程目录下的“*.filters”文件一定不能删掉,因为这个文件就是用来记录筛选器的。
这个和fb不一样。
关于筛选器看这个 
http://www.zhuyanfeng.com/archives/1692

#include到底该写在哪 
http://blog.csdn.net/cppyin/article/details/6121010

原文地址:https://www.cnblogs.com/chenhongyu/p/3487230.html