在公司的学习

第一步 游戏测评

第二步 小项目练手

遇到的问题:

1. SpringBoard无法启动应用程序  Clean程序,或者注销电脑试试。

2. 当设备变化是,图片资源被拉伸变形。采用合适的屏幕自适应方法。

3. 要创建工具类,将复用次数较多的函数放入工具类中

4. 自定义的CCLayer重写了OnEnter之后,,一定要先调用基类的OnEnter,CCLayer::OnEnter(); 因为在CCLayer和CCNode中的OnEnter之中做了一些初始化工作。我再OnEnter中播放动画,没有反应,原因就是没有调用基类的OnEnter。

5. 头文件尽量用全路径。

e.g. #include "GameTools/GameTools.h"

6. 注释插件

https://github.com/onevcat/VVDocumenter-Xcode 

 下载解压,打开VVDocumenter-Xcode.xcodeproj 编译,成功后重启XCode,即可。按三个/即可快速创建注释。


7. 手机游戏排行

googleplay排行

gamelook

appstore

appannie


8. 使用菜单的时候一般设置menu->setPosition(CCPointZero); ,菜单项的坐标是相对于菜单的父节点的。例如,sprite->addChild(menu),这时,添加坐标如果写menuItem->setPosition(ccp(0,0),则菜单项是在sprite的(0,0)处。 添加菜单项的时候,先添加的在下面,后添加的在上面。

e.g.  create(moreGames,parents,NULL), 如果有交集,则moreGame菜单项在parents之下。

如果想给菜单指定zOrder或者tag则 CCMenu* menu = CCMenu::create();  menu->addChild(menuItem1, zOrder, tag);


9. 节点的锚点

锚点是相对于父节点来说的,不影响其孩子的添加位置。孩子添加还是相对于左下角的点。

e.g.

    CCSize size = CCDirector::sharedDirector()->getWinSize();

    CCSprite* sp1 = CCSprite::create("Default.png",CCRectMake(0,0,200,200));

    sp1->setAnchorPoint(ccp(1,1));

    sp1->setPosition(ccp(size.width, size.height));

    addChild(sp1,1); 

这里,锚点设置为(1,1)所以图片会紧贴着屏幕的右上角

    CCSprite* sp2 = CCSprite::create("CloseNormal.png");

    sp2->setPosition(ccp(0,0));

    sp1->addChild(sp2);

这里sp2添加到sp1中,仍然是在sp1的左下角。


10. 如何屏蔽后端事件:

1). 重写 registerWithTouchDispatcher()函数,

virtual void registerWithTouchDispatcher();

void DialogLayer::registerWithTouchDispatcher()

{

    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128true); //注册并设置当前面板触摸的优先级

}


2). 设置可以触摸

setTouchEnabled(true);


3). ccTouchBegan返回true


11.

http://www.andersriggelsen.dk/glblendfunc.php   CCRenderTexture混合渲染参数在线设置


12.对于CCEditBox和CCLabelTTF默认字色为白色,另外CCEditBox中没有设置对其方式相关的函数。在CCLabelTTF中,可以用 setHorizontalAlignment ( kCCTextAlignmentLeft ); 设置左对齐。


13. 初始化一个层的适合,在Init函数尽量不要写会改变的代码。因为Init在创建层的时候只运行一次。而每次进入界面均要改变的代码在OnEnter中写比较好,但是不要忘了调用基类的OnEnter。

例如,想要在页面2设置一个按钮,点击后会切换中英文(包括图片、文字、语音),此时,在页面1的OnEnter函数中写这些代码比较好。当PopScene到页面1的时候,依然会走OnEnter。

但是在OnEnter中加载的东西,要在OnExit中释放。不然每次都会加载。



14.消息队列实现界面交互。

1). 在Layer1中新建消息队列。 

static MessageQueue* s_messageSqueue; ---Layer1.h

MessageQueueGameLayer::s_messageSqueue =newMessageQueue(); 

2).消息处理函数

void handleMsg(float dt);---Layer1.h

3).开启消息队列 --- 

schedule(schedule_selector(GameLayer::handleMsg));---Layer1.cpp--init()

4).实现消息处理函数

void GameLayer::handleMsg(float dt){

    if(GameLayer::s_messageSqueue->size() !=0){

        Message* m = NULL;

        while ((m = GameLayer::s_messageSqueue->pop()) !=NULL) {

            switch (m->getMesType()) {

                case Message_Type_ScrollScreen_:

                    MoveBackground();

                    break;

                default:

                    break;

            }

            

            delete m;

            m = NULL;

        }

    }

}


5).Layer2中发送消息,并添加到消息队列。

Message* msg = Message::instance();

            msg->setMesType(Message_Type_ScrollScreen_);

            GameLayer::s_messageSqueue->push(msg);


15. 获取点击位置,并转化为对应节点中的坐标


CCSetIterator it = pTouches->begin();

    CCTouch *touch = (CCTouch *)(*it);

    

    //转换到对应节点下的坐标

    CCPoint converNodePoint = node->convertTouchToNodeSpace(touch);




16. 野指针问题 一般是数组越界或者是指针new了没删除


17.做一个东西的时候,先观察他的功能,功能较多的时候,要封装成一个类,方便以后拓展。比如拼图的碎片。当点击拖动的时候,会跟随移动,当松手但是没有拖到合适位置的时候会弹回去,拖到合适位置会嵌进去。


18.今天遇到好多Bug,是一个野指针引起的。不是数组越界,也不是new的问题。自定义了一个Chip类继承自CCSprite,使用的时候,Chip * chip = (Chip*)Chip::createSpriteWithFrameName("XXX.png");出了问题。


野指针形成原因:

一)、数组越界造成非法使用内存

  

 解决方法:

1)、访问数组的时候注意访问的长度是否超过下标


比如:二维数组array[][4],访问的时候

for(int i = 0; i < num; i++){

     array[0][i];           (要确定num一定不能超过4)

}


2)、尽量用链表(stl容器)代替数组;



二)、new出来的东西一定要delete掉、cocos2d的对象保证一个原则:对象create之后要么add child进去,要么retain它,但是后面一定要手动release掉、也可以自己写一个create方法,但是注意:new之后设置它为autorelease


三)、强转类型:

出错实例:


1)、class A{

          }


          class B{

          }


         B* b = new B;

         A* a = (A*)B;      (最无脑的强转方法,程序不报错,但是两个类型没有一点关系,一用a就错)

2)、class A{

          }

          

          class B : public A{

          char* str[100];

         }

        

         A* a = new A;

         B* b = (B*)a;  (这样强转没问题,基类转化成派生类,但是b调用自己的对象str的时候就会出问题,因为你的b没有初始化这个属性,直接从A强转过来的,有野指针的危险。今天上午的bug就是这个问题)


关于强转类型建议不要用上面的c的形式,尽量使用static_cast dynamic_cast方法做类型转换

基类转化与派生类的转化 使用static_cast方法:例: static_cast<B*>A这样避免第一个出错实例的发生,会在编译报错提醒的!

同类型之间的转化使用dynamic_cast方法:例:array->addChild(Menu*)     Menu* menu = dynamic_cast<Menu*>array->anyObject() 如果类型不是menu返回是null,这样更安全,详细查看http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html



四)、变量生命周期结束,还去访问它   (问题不太常见)

例如:

       A* p;

       int a{

A* a;

        p = &a;

      }


      p->func();        (a的内存被释放了)


五)、指针成员变量一定要在构造置成NULL  (编码规范,需要特别注意,如果不初始化就使用它,这是天生的野指针啊!)




19.在程序中尽量少用Tag,因为会很乱。如果一定要用,则要用宏或者枚举定义,而不要直接用数字。同一个节点如果添加了2个一样的tag就容易出问题。因此多个同类的节点可以加到链表或者向量中。而此向量作为一个类的成员。当别的类想要访问的时候,只需要取得此链表即可。

创建 std::vector<Chip*> m_chipV;

判空 if (node-> m_chipV . empty ()) return ;

遍历 std::vector<Chip*>::iterator iter = node->m_chipV.begin();

for (; iter != node->m_chipV.end(); iter++) { }



20. CCPoint pos = a->getPosition()获取的坐标,是相对于父节点以及a的锚点的坐标。因此屏幕自适应的时候,如果锚点与父节点不变,则再次设置a->setPosition(pos);则相对位置不变。 比如当在节点1中拖着一个节点2运动并打印坐标,则打印出来的坐标是相对于节点2锚点在节点1中的坐标。


21.关于retain

一般只有在一个函数中创建cocos2d类型变量,但是脱离了此函数作用域去用这个变量,并且在此函数中没有addChild,此时要在此函数中retain()。 当不用此变量的时候在release掉。

CCSprite* a;

void A(){

    a = CCSprite::createWithTexture();

    a->retain();

}


void B(){

    a->fsaf

    

}


22.关于回调函数

CCCallFuncN::create(CCObject* pSelectorTarget, SEL_CallFuncN selector)

CCCallFuncND::create(CCObject* pSelectorTarget, SEL_CallFuncND selector, void* d)

均可接受一个节点参数,谁掉用这个回调函数,传入的就是谁。

回调函数在CCSequence中使用时要注意,CCSequence中的函数是顺序执行,而CCSequence外面的代码也会执行。

例如:

CCDelayTime* dtime = CCDelayTime::create(0.5);

call1回调函数中 打印 cclog("call1");

call2回调函数中 打印cclog("call2");

CCSequence*  seq = CCSequence ::create(call1,dtime,call2,NULL);

CCLog("abc");

此时执行结果为 call1  

    abc

  call2

在dtime期间就已经开始往下执行了。所以如果在回调函数call2中对指针有所操作,而在CCSequence后面又释放了这个指针或者其他操作,则会对call2产生影响。

23.游戏运行卡死,但是不报错,往往是死循环导致的。检查卡死的附近的代码


24.少用静态变量,用户数据写到UserDefault中。

CCLog("%s",CCFileUtils::sharedFileUtils()->getWritablePath().c_str());可以查到文件存放的路径

在Library中的Preferences文件夹中用plist存储


CCFileUtils::sharedFileUtils()->getWritablePath() 此命令可以获得不同设备中的读写路径。

CCFileUtils::sharedFileUtils()->fullPathForFilename("xxx.xx"); 在Resource中查找文件 xxx.xx,并且返回该文件在库中的路径(不是Resource下文件的路径)。如果xxx.xx在Resource的某个文件夹中, 则需要写出文件夹的名字,如"yy/xxx.xx"


25.关于onEnter、onExit、构造与析构函数

当A进入B,先调用B的构造函数->B的init->A的onExit->B的onEnter->A的析构函数。

若A中有计时器,也是在A的onExit中取消的。例如,如果在B的构造清除缓存,而在A中计时器播放动画,则会出现错误。此时可以将清除缓存、加载缓存、等操作放在B的onEnter中

26.

算法里面出现logA)的时候,一定要判断A为非或者 除法 A/B)这种可能导致没有意义的表达式

除数和指数幂 0判断 有的时候很容易遗漏

造成的后果跟野指针差不多 各种奇怪bug

不过这个还好一点  一旦出现除数为0或者指数幂为0  的出来的值是个这个东西 -1.#IND00000000000   只要输出这个东西 那就是这类问题了


27.关于retain和release

如果创建出来的对象没有在本帧内被addChild(引用计数+1)则,会被释放。例如CCArray,创建出来一般不会被addChild,此时则需要retain。而在不用的时候要记得releas。不然不会被释放。

另一种情况,创建出来的对象,被加入了autorelease。则不需要在手动进行内存管理。比如,对象已经被addchild,则将其removefromparent的时候,会判断引用计数是否为0,为0了就释放了。不需要在做release相关的操作。


28.在使用水波纹的时候,有时候会报错,

#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP

    glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(m_pIndices[0])) );

#else-------这里报错,原因是Ios使用的是VAO,解决方法见下面

    glDrawElements(GL_TRIANGLES, (GLsizei) n*6,GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(m_pIndices[0])) );

#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP


#if CC_REBIND_INDICES_BUFFER

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

#endif


在cocos2dx/include/ccConfiger.h中 将

#ifndef CC_TEXTURE_ATLAS_USE_VAO

    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)

        #define CC_TEXTURE_ATLAS_USE_VAO1-------->改成0

    #else

        /* Some Windows display adapter driver cannot support VAO. */

        /* Some android devices cannot support VAO very well, so we disable it by default for android platform. */

        /* Blackberry also doesn't support this feature. */

#define CC_TEXTURE_ATLAS_USE_VAO0

    #endif

#endif


28. 在xcode编译项目的时候报错 

ld: -pie can only be used when targeting iOS 4.2 or later

clang: error: linker command failed with exit code 1 (use -v to see invocation)

是因为选择的ios版本过低,点击项目->Deployment Info,将Deployment Target改成4.3以上


29.使用STL容器时,尽量不要把同一个元素加入两个容器中,这样当想要删除这个元素的时候,需要在两个容器中分别删除,如果经常需要插入删除,则用链表比用向量好。


30. 今天遇到一个奇葩的问题,在ios真机可以运行的游戏到了安卓下面就闪退,这里总结下闪退的原因:1.掉帧严重 2.死循环 3.plist加密(我遇到的就是这个原因)


31.回调函数的使用

static CCCallFunc * create(CCObject* pSelectorTarget,SEL_CallFunc selector);

参数二:是函数名,参数一:是函数所属的类,所以一般使用this


如果需要在回调函数中对一个不属于此函数的局部变量进行操作,则可以使用带参数的回调函数

 static CCCallFuncND * create(CCObject* pSelectorTarget,SEL_CallFuncND selector,void* d);

参数一、二与CCCallFunc的相同,参数三即为要附带的参数

FuncA(CCNode* pSender)

{

//这里的pSender就是传过来的局部变量

CCCallFuncND* callND_canbeHit =CCCallFuncND::create(this,callfuncND_selector(Tollgate11::callND_canbeHit), (void*)pSender);

}


32. node->boundingBox().containsPoint(pos); 要求pos和node是同一个父节点,在同一个坐标系下。


33. CCOrbitCamera中有7个参数分别为旋转的时间,起始半径,半径差,起始z角,旋转z角差,起始x角,旋转x角差

起始z角如果写0,则认为是与屏幕平行的。旋转z角差,即z轴旋转角度(不是停止的角度)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值