cocos2d-x 错误总结(持续更新)

记录自己学习cocos2d-x路上遇到的种种问题及其解决办法。持续更新。



一.断言 TMX: Only 1 tileset per layer is supported 崩溃:

这个错误发生在我使用tiledmap的时候,其中,tiledmap里面编辑好的地图在同一个层(layer)使用了多个图块。

加载地图时弹出断言失败窗口,跟踪进去发现崩毁地点:

CCAssert( m_uMaxGID >= m_pTileSet->m_uFirstGid &&
    m_uMinGID >= m_pTileSet->m_uFirstGid, "TMX: Only 1 tileset per layer is supported");

从断言中的提示就可以看出:一张图层上只支持一个一个图块集合
就是说编辑器中的每一层只能使用一个图块集合中的图块,不能使用其他图块集合中的图块!

解决办法:(一)将多个图块绘制在同一个图块上使用。  (二)放弃其他图块,使用专一图块。


二.tileGIDAt返回数据异常:

我们用tileGIDAt获取某一层上的某一格对应的图块ID,GID是什么呢?可以理解为全局唯一ID,而我们的图块集合可能会有多个,所以每个的图块的ID不是从该图块集合1,2,3…这样的,而是紧接着上一个图块集合的最后一个ID顺序下来的!

所以我们要获得正确的ID,应该:

cocos2d::CCTMXLayer *towerLayer = map->layerNamed("tower");
cocos2d::CCTMXTilesetInfo *towerSet = towerLayer->getTileSet();
int nGid = towerLayer->tileGIDAt(ccp(0, 0)) - towerSet->m_uFirstGid;
if(nGid >= 0)
{
}

先获取这一层对应的图块集合的首ID,然后相减就获得了正确的ID.



三.多点触控没反应:

具体问题描述参见:http://zhidao.baidu.com/link?url=9NK8OxKou3WUr-dQJs1Wd3fXNHQaFarM9mFzaEVWQlDKm-aVL4ar_WBiYJ3uQ7H9aKg9MksCBBddvzv-YjX6Fa

解决参考:http://blog.csdn.net/crane406/article/details/16825125

如果是ios平台,要在 AppController.mm 中加入 

 //开启多点触控.. 默认是关闭的。
[__glView setMultipleTouchEnabled:YES];


如果是android就不用,因为默认是开启的...

因为这个问题曾经浪费了我大把时间。  mark!


四.iphone真机测试闪屏:

在   bool AppDelegate::applicationDidFinishLaunching() 中加入:

CCDirector::sharedDirector()->setDepthTest(false);//关闭深度测试

CCDirector::sharedDirector()->setProjection(kCCDirectorProjection2D);//使用2D投影(默认3D)


五.reference count should greater than 0


报错原因:

                        removeFood( nowFood );

                        girlItemArr->addObject(nowFood);

其中, nowFood 是个 CCSprite*,   girlItemArr 是个 CCArray*

其中,removeFood实现如下:

//移除食物
void PickScene::removeFood( CCSprite *food_ )
{
    food_->removeFromParentAndCleanup(true);
    foodArr->removeObject(food_);
}

不难看出。我这里先把精灵从父类移除,并且清理了对应内存。再调用这个已经清理的精灵,就会出现内存错误。

解决办法: removeFood 和 addObject这两条语句调换个顺序就可以了。


下面科普下cocos2d-x 的内存管理机制:

cocos2dx 采用引用计数管理自己的内存:

引用计数:

引用计数就是通过给每个对象维护一个引用计数器,记录该对象当前被引用的次数。当对象增加一次引用时,计数器+1.而对象失去一次引用时,计数器-1,当引用计数器为0时。标志着该对象的生命周期结束,自动触发对象的回收释放。 为了实现引用计数器,cocos2dx实现了自己的根类ccobject。引 擎中所有类都派生自ccobject类。一下ccobject的定义
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
class CC_DLL Object
{
public :
     /// object id, ScriptSupport need public _ID
     unsigned int        _ID;
     /// Lua reference id
     int                 _luaID;
protected :
     /// count of references
     unsigned int        _reference;
     /// count of autorelease
     unsigned int        _autoReleaseCount;
public :
     /**
      * Constructor
      *
      * The object's reference count is 1 after construction.
      * @js NA
      */
     Object();
     
     /**
      * @js NA
      * @lua NA
      */
     virtual ~Object();
     
     /**
      * Release the ownership immediately.
      *
      * This decrements the object's reference count.
      *
      * If the reference count reaches 0 after the descrement, this object is
      * destructed.
      *
      * @see retain, autorelease
      * @js NA
      */
     inline void release()
     {
         CCASSERT(_reference > 0 , "reference count should greater than 0" );
         --_reference;
 
         if (_reference == 0 )
             delete this ;
     }
 
     /**
      * Retains the ownership.
      *
      * This increases the object's reference count.
      *
      * @see release, autorelease
      * @js NA
      */
     inline void retain()
     {
         CCASSERT(_reference > 0 , "reference count should greater than 0" );
         ++_reference;
     }
 
     /**
      * Release the ownership sometime soon automatically.
      *
      * This descrements the object's reference count at the end of current
      * autorelease pool block.
      *
      * If the reference count reaches 0 after the descrement, this object is
      * destructed.
      *
      * @returns The object itself.
      *
      * @see AutoreleasePool, retain, release
      * @js NA
      * @lua NA
      */
     Object* autorelease();
 
     /**
      * Returns a boolean value that indicates whether there is only one
      * reference to the object. That is, whether the reference count is 1.
      *
      * @returns Whether the object's reference count is 1.
      * @js NA
      */
     bool isSingleReference() const ;
 
     /**
      * Returns the object's current reference count.
      *
      * @returns The object's reference count.
      * @js NA
      */
     unsigned int retainCount() const ;
 
     /**
      * Returns a boolean value that indicates whether this object and a given
      * object are equal.
      *
      * @param object    The object to be compared to this object.
      *
      * @returns True if this object and @p object are equal, otherwise false.
      * @js NA
      * @lua NA
      */
     virtual bool isEqual( const Object* object);
     /**
      * @js NA
      * @lua NA
      */
     virtual void acceptVisitor(DataVisitor &visitor);
     /**
      * @js NA
      * @lua NA
      */
     virtual void update( float dt) {CC_UNUSED_PARAM(dt);};
     
     friend class AutoreleasePool;
};
通过以上代码我们可以看出cocos2dx的内存管理机制和objective-c的管理一样。都是当_reference = 0时释放内存。_autoReleaseCount自动释放池的引用计数
?
1
2
3
4
5
6
7
8
9
auto sprite1 = new Sprite();
sprite1->initWithSpriteFrameName( "btn_adventure_normal_CN.png" ); //引用计数器+1
CCLOG( "retaincount = %d" ,sprite1->retainCount());
sprite1->retain(); //引用计数器+1
CCLOG( "retaincount = %d" ,sprite1->retainCount());
sprite1->release(); //引用计数器-1
CCLOG( "retaincount = %d" ,sprite1->retainCount());
sprite1->autorelease(); //只是把该sprite放入自动释放池中。引用计数器不变。等待管理器自动释放
CCLOG( "retaincount = %d" ,sprite1->retainCount());

coco2dx 内存管理原则

1.程序段必须成对执行retain()和release()或者执行autorelease()来开始和结束对对象的引用   2.工厂方法返回前,应通过autorelease()结束对该对象的引用   3.对象传值时,应考虑到新旧对象相同的特殊情况   4.尽量使用release()而不是autorelease()来释放对象,以确保性能。   5.保存ccobject的子类对象时,应严格使用cocos2dx提供的容器。

内存管理涉及到的宏:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define CC_SYNTHESIZE_RETAIN(varType, varName, funName)    \
private : varType varName; \
public : virtual varType get##funName( void ) const { return varName; } \
public : virtual void set##funName(varType var)   \
{ \
     if (varName != var) \
     { \
         CC_SAFE_RETAIN(var); \
         CC_SAFE_RELEASE(varName); \
         varName = var; \
     } \
}
 
#define CC_SAFE_DELETE(p)           do { delete (p); (p) = nullptr; } while ( 0 )
#define CC_SAFE_DELETE_ARRAY(p)     do { if (p) { delete[] (p); (p) = nullptr; } } while ( 0 )
#define CC_SAFE_FREE(p)             do { if (p) { free(p); (p) = nullptr; } } while ( 0 )
#define CC_SAFE_RELEASE(p)          do { if (p) { (p)->release(); } } while ( 0 )
#define CC_SAFE_RELEASE_NULL(p)     do { if (p) { (p)->release(); (p) = nullptr; } } while ( 0 )
#define CC_SAFE_RETAIN(p)           do { if (p) { (p)->retain(); } } while ( 0 )



学习的路上,与君共勉。

你可能感兴趣的:(cocos2d-x 错误总结(持续更新))