[cocosBuilder]Android端無法使用sub-ccb

文章撰寫日期︰2013/08/15 15:00
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

遇到了sub-ccb資源無法在Android讀取,
embeddedNode->setPosition(ccbFileNode->getPosition());這句報BAD_ACCESS的問題。

遇到這個問題幾乎可以說ccbReader沒有在Resources資源下找到欲使用的sub-ccb資源。

解釋一下我的資料結構,
右圖是我目前cocosBuilder的路徑狀況。

Brain.ccb裡面用了Cursor.ccb當成sub ccb,
但在Android裡卻因為這個路徑結構,
而導致無法找到Cursor.ccb,
IOS則是執行正常。


二、解決辦法

仔細與TestCpp示範專案比對後,
發現有一個核取方塊我打了勾(見下圖)︰
Flatten paths when publishing這個選項在官方文件的註釋如下︰
cocosBuilder的專案路徑預設是在Resources根目錄下,也就是說,倘若今天你有mySubDirectory/myImage.png要被cocosBuilder使用,在放置檔案時,你也不能放在mySubDirectory目錄底下,而是要直接放在Resources根目錄下。
如果要用相對位置的方法取得資源,那麼這個核取方塊要取消,而且在Xcode專案中,要使用藍色資料夾引用圖檔資源(如右)。

這麼做以後,Android也能找到Resources裡根目錄的資源了。

[cocos2dx]製作有邊框文字/圖片(Stroke Font)

文章撰寫日期︰2013/08/14 14:01
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、前言

想要將CCSpirte或CCLabelTTF增加邊框,
該怎麼做?

二、本文開始

爬文至cocos2dx討論版後,
發現網友Alexandr Gerasimov熱心地將另一位網友cocos2d的code改成c++語法,
供我們使用。
但是我在使用時,
發現物件一旦被設定過AnchorPoint,
這個繪製岀來的邊框就會跑掉。
因此加了AnchorPoint的判斷,
更改的源碼如下︰

    static CCRenderTexture* createStroke(CCSprite* label, int size, ccColor3B color, GLubyte opacity)
    {
        
        CCRenderTexture* rt = CCRenderTexture::create(label->getTexture()->getContentSize().width + size * 2,
                                                      label->getTexture()->getContentSize().height+size * 2);
        CCPoint originalPos = label->getPosition();
        
        ccColor3B originalColor = label->getColor();
        
        GLubyte originalOpacity = label->getOpacity();
        
        label->setColor(color);
        
        label->setOpacity(opacity);
        
        bool originalVisibility = label->isVisible();
        
        ccBlendFunc originalBlend = label->getBlendFunc();
        
        ccBlendFunc bf = {GL_SRC_ALPHA, GL_ONE};
        
        label->setBlendFunc(bf);
        
        CCPoint bottomLeft = ccp(
                                 label->getTexture()->getContentSize().width * label->getAnchorPoint().x + size,
                                 label->getTexture()->getContentSize().height * label->getAnchorPoint().y + size);
        
        //原來沒有判斷AnchorPoint的寫法
        //  CCPoint positionOffset= ccp(   - label->getTexture()->getContentSize().width / 2,
        //                                  - label->getTexture()->getContentSize().height / 2);
        
        //SetAnchorPoint會影響到positionOffset,所以要做判斷
        CCPoint positionOffset = CCPointZero;
        if(label->getAnchorPoint().x == 0.5f){
            positionOffset.x = 0;
        }else if(label->getAnchorPoint().x == 0.0f){
            positionOffset.x =- label->getTexture()->getContentSize().width / 2;
        }else{
            positionOffset.x = label->getTexture()->getContentSize().width/2;
        }
        if(label->getAnchorPoint().y == 0.5f){
            positionOffset.y = 0;
        }else if(label->getAnchorPoint().y == 0.0f){
            positionOffset.y =- label->getTexture()->getContentSize().height / 2;
        }else{
            positionOffset.y =  label->getTexture()->getContentSize().height/2;
        }
        
        CCPoint position = ccpSub(originalPos, positionOffset);
        
        rt->begin();
        
        for (int i=0; i<360 data-blogger-escaped-for="" data-blogger-escaped-i="" data-blogger-escaped-label-="" data-blogger-escaped-needs="" data-blogger-escaped-optimize="" data-blogger-escaped-should="" data-blogger-escaped-that="" data-blogger-escaped-you="" data-blogger-escaped-your="">setPosition(
                               ccp(bottomLeft.x + sin(CC_DEGREES_TO_RADIANS(i))*size, bottomLeft.y + cos(CC_DEGREES_TO_RADIANS(i))*size)
                               );
            label->visit();
        }
        rt->end();
        
        label->setPosition(originalPos);
        label->setColor(originalColor);
        label->setBlendFunc(originalBlend);
        label->setVisible(originalVisibility);
        label->setOpacity(originalOpacity);
        
        rt->setPosition(position);
        //反踞齒
        rt->getSprite()->getTexture()->setAntiAliasTexParameters();
        
        return rt;
    }

結果如下

[cocos2dx]使用virtual關鍵字

文章撰寫日期︰2013/08/13 12:30
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、前文

今天想要使用virtual關鍵字宣告抽象實作函式,
發現了一些狀況。

二、文章開始

遇到了什麼狀況?

1.cocos2dx官網已經明確的告訴我們不要隨便使用virtual關鍵字。


2.稍微理解一下virtual這個關鍵字在cocos2dx裡的被使用狀態︰

CCNode裡如virtual void onEnter()等抽象實作函式之所以能呼叫到子CCNode的onEnter()是因為CCNode的onEnter()使用了一個宏/巨集︰
void CCNode::onEnter()
{
    //就是這個
    arrayMakeObjectsPerformSelector(m_pChildren, onEnter, CCNode*);

    this->resumeSchedulerAndActions();

    m_bIsRunning = true;

    if (m_eScriptType != kScriptTypeNone)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->executeNodeEvent(this, kCCNodeOnEnter);
    }
}

這個宏/巨集被宣告在CCArray.h中︰

#define arrayMakeObjectsPerformSelector(pArray, func, elementType)    \
do {                                                                  \
    if(pArray && pArray->count() > 0)                                 \
    {                                                                 \
        CCObject* child;                                              \
        CCARRAY_FOREACH(pArray, child)                                \
        {                                                             \
            elementType pNode = (elementType) child;                  \
            if(pNode)                                                 \
            {                                                         \
                pNode->func();                                     \
            }                                                         \
        }                                                             \
    }                                                                 \
}                                                                     \
while(false)

當每一個CCLayer向CCScene添增子節點(this->addChild(node))後,
這個宏會將所有收到的子節點
都跑一次onEnter這個被強制規範要實作的函式。
也因此,
我們客製化的CCLayer::onEnter()能夠被呼叫到。

如果要這樣使用,
你的架構需改寫。

3.你宣告岀來的class需要繼承CCObject,
否則會遇到
CCAssert(0, "not implement");

這個錯誤。

三、結論

以上種種原因,
寫了這篇部落格打消使用virtual的念頭。

[cocosBuilder篇]找不到cocosBuilder裡宣告的Tag值

文章撰寫日期︰2013/08/12 19:33
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

遇到了找不到在cocosBuilder裡一個CCLabelTTF宣告的tag值的問題。






二、解決辦法

後來才發現CCBReader無法讀取到CocosBuilder裡CCNode底下的tag值。
如果要抓到tag,必須讓CCLabelTTF脫離CocosBuilder的CCNode架構。


[cocos2dx篇]CCLayerColor沒有顯示

文章撰寫日期︰2013/08/08 17:51
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

今天遇到在cocosBuilder裡使用CCLayerColor,
但在畫面上卻沒有顯示的問題。

二、解決辦法

經爬文後發現cocos2dx\layers_scenes_transitions_nodes\CCLayer.cpp底下
init()有問題。

原本的Code︰
bool CCLayerColor::init()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    return initWithColor(ccc4(0,0,0,0), s.width, s.height);
}
需改成
bool CCLayerColor::init()
{
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    return initWithColor(ccc4(0,0,0,255), s.width, s.height);
}
問題解決。

[Android-JNI篇]Fatal signal 11,找不到JNI函式

文章撰寫日期︰2013/07/17 11:42
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

今天在寫JNI試圖從C++ call JAVA時,
遇到了
Fatal signal 11 (SIGSEGV) xxxx
的問題,
告訴我找不到JAVA層的某個static函式。


二、解決辦法

JAVA端的Code如下
package com.simon.utility;
public class DataManager {
 public static void test(){
  
  Log.i("tag", "into test");
 }
}
 
C++端使用JNI呼叫上面的Java函式
void FileOperator::getAndroidTest(){
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    CCLog("into FileOperator::getAndroidTest(), Involking JNI...");
    
    JniMethodInfo t;
    
    if (JniHelper::getStaticMethodInfo(t, "com/simon/utility/DataManager","test","()V;"))
    {
        CCLog("classID: %d",t.classID);
                CCLog("methodID: %d",t.methodID);
        t.env->CallStaticBooleanMethod(t.classID,t.methodID);
        
    }
#endif
}
 
程式一直跟我報找不到test這個函式,
後來才知道()V;那邊
V後面不用打分號!

題外話︰
()是JAVA端接收參數的值
V是這隻JAVA函式是否有回傳值。

[Android篇]無法使用GET/POST

文章撰寫日期︰2013/07/05 15:37
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

今天使用cocos2dx提供的CCHttpRequest跟伺服器發出GET/POST請求時,
Android端一直無法取得到正確資料,出現以下的LOG︰
response failed
error buffer: Couldn't resolve host 'xxxxxxx.amazonaws.com'

二、解決辦法

這是因為沒有開啟Android端的用戶權限。

註︰
Google對於每一隻APP需要使用到的權限,
都要求開發者必須在AndroidMenifest.xml裡註冊,
這是為了讓Google Play可以在提供使用者下載的地方,
show出這隻APP需要哪些資訊。

如︰這隻APP需要有上網能力、需要讀取您的通訊錄、需要讀取您的外部SD卡等等⋯

Android端的User-Permission需要加入Internet這個Permission。
〈uses-permission android:name="android.permission.INTERNET"/〉

加入後,就能在Android端GET/POST取到資料了。