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

来源:互联网 发布:python程序的执行原理 编辑:程序博客网 时间:2024/06/03 21:33

记录自己学习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
classCC_DLL Object
{
public:
    /// object id, ScriptSupport need public _ID
    unsignedint       _ID;
    /// Lua reference id
    int                _luaID;
protected:
    /// count of references
    unsignedint       _reference;
    /// count of autorelease
    unsignedint       _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
     */
    inlinevoidrelease()
    {
        CCASSERT(_reference > 0,"reference count should greater than 0");
        --_reference;
 
        if(_reference == 0)
            deletethis;
    }
 
    /**
     * Retains the ownership.
     *
     * This increases the object's reference count.
     *
     * @see release, autorelease
     * @js NA
     */
    inlinevoidretain()
    {
        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
     */
    unsignedintretainCount() 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(constObject* object);
    /**
     * @js NA
     * @lua NA
     */
    virtualvoidacceptVisitor(DataVisitor &visitor);
    /**
     * @js NA
     * @lua NA
     */
    virtualvoidupdate(floatdt) {CC_UNUSED_PARAM(dt);};
     
    friendclassAutoreleasePool;
};
通过以上代码我们可以看出cocos2dx的内存管理机制和objective-c的管理一样。都是当_reference = 0时释放内存。_autoReleaseCount自动释放池的引用计数
?
1
2
3
4
5
6
7
8
9
auto sprite1 = newSprite();
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{ returnvarName; } \
public: virtual voidset##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)



学习的路上,与君共勉。

69 0