어느 순간 갑자기 cygwin에서 ndk로 빌드할 때 다음과 같은 경고가 나타나기 시작했습니다.

경고 
Android NDK: WARNING: Unsupported source file extensions in /cygdrive/d/Dev/cocos2d/IronAge/android/jni/../../Classes/Android.mk for module game_logic
Android NDK:   \

에러 
/Android.mk:11: *** recipe commences before first target.  Stop.

원인은 공백이었습니다.

 
Classes\Android.mk
 

LOCAL_SRC_FILES := AppDelegate.cpp \
                                CuTiledMap.cpp \
                                MapUnit.cpp \
                                CuSprite.cpp \
                                PointConvert.cpp \
                                CCLayerPanZoom.cpp \ [이곳에 공백이 있으면 에러를 뱉음!]
                                CuLayerPanZoom.cpp \ [이곳에 공백이 있으면 경고를 뱉음!]

 






 




참조1 
CCPoint tilePosFromLocation(CCPoint location, CCTMXTiledMap* tileMap)
{
// Tilemap position must be subtracted, in case the tilemap position is scrolling
CCPoint pos = ccpSub(location, tileMap->getPosition());
float halfMapWidth = tileMap->getMapSize().width * 0.5f;
float mapHeight = tileMap->getMapSize().height;
float tileWidth = tileMap->getTileSize().width;
float tileHeight = tileMap->getTileSize().height;
CCPoint tilePosDiv = CCPointMake(pos.x / tileWidth, pos.y / tileHeight);
float inverseTileY = mapHeight - tilePosDiv.y;
// Cast to int makes sure that result is in whole numbers
float posX = (int)(inverseTileY + tilePosDiv.x - halfMapWidth);
float posY = (int)(inverseTileY - tilePosDiv.x + halfMapWidth);
// make sure coordinates are within isomap bounds
posX = MAX(0, posX);
posX = MIN(tileMap->getMapSize().width - 1, posX);
posY = MAX(0, posY);
posY = MIN(tileMap->getMapSize().height - 1, posY);
return CCPointMake(posX, posY);
}


참조2 
-(CGPoint)touchToXY:(CGPoint)touch map:(CCTMXTiledMap *)_map mapsize:(int)_mapsize
{
touch = [[CCDirector sharedDirector] convertToGL:touch];
touch = [_map convertToNodeSpace:touch];
CGSize ts = [_map tileSize];
int isoy = (((touch.y/ ts.height) + (touch.x - (_mapsize * ts.width/2)) / ts.width) - _mapsize) *-1;
int isox = (((touch.y/ ts.height) - (touch.x - (_mapsize * ts.width/2)) / ts.width) -_mapsize) *-1;
return ccp(isox,isoy);
}

dynamic_cast가 NULL을 리턴하는 문제 발생 
원도우에서는 잘 돌아가는데 안드로이드폰에 삽입하면 
dynamic_cast가 NULL을 리턴한다.

\cocos2d\cocos2dx\include\CCString.h

        virtual bool isEqual(const CCObject* pObject)
        {
            bool bRet = false;
            const CCString* pStr = dynamic_cast<const CCString*>(pObject);
            if (pStr != NULL)
            {
                if (0 == m_sString.compare(pStr->m_sString))
                {
                    bRet = true;
                }
            }
            return bRet;
        } 

아래와 같이 강제 형변환으로 수정해 주면 된다.
이와 같이 수정해서 정상동작하는걸 보면  
dynamic_cast 가 변환될 때 뭔가 문제 인거 같은데... 힐끔 찾아봤는데 문제점이 안나와서 패스... 아시는 분 댓글 달아주세욤~
 
        virtual bool isEqual(const CCObject* pObject)  
        {
            bool bRet = false;
            const CCString* pStr = (CCString*)(pObject);
            if (pStr != NULL)
            {
                if (0 == m_sString.compare(pStr->m_sString))
                {
                    bRet = true;
                }
            }
            return bRet;
        }


 

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

CCMutableArray<CCSpriteFrame*>* animFrames = new CCMutableArray<CCSpriteFrame *>();
for( int i = 1; i < 15; ++i )
{
char cBuf[256] = {0, };
sprintf(cBuf, "grossini_dance_gray_%02d.png", i );

CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(cBuf);
animFrames->addObject(frame);
}

CCSprite* man = CCSprite::spriteWithSpriteFrame( animFrames->getObjectAtIndex(0) );
man->setPosition(ccp(100, 100));
this->addChild(man);

CCAnimation *animation = CCAnimation::animationWithFrames(animFrames,0.3f);
CCAnimate* animate = CCAnimate::actionWithAnimation(animation);
man->runAction( CCRepeatForever::actionWithAction(animate) );
 

cocos2d에 타일 기능이 있는데, 맵 크기를 정하기 위해서 최소프레임과 평균프레임을 구해봤다.

조건: 디버깅 모드, 앱 구동시 1분간 구동 후 계산
디바이스: 갤럭시s2

타일의 가로세로 개수 타일의 가로세로 픽셀 최소프레임 최대프레임 평균프레임
128*128 128*128 27 61.3 50.2
128*128 32*32 25.9 62.2 49.5
64*64 128*128 44.7 61.1 53.3
64*64 32*32 47.2 61.9 53.8
32*32 128*128 55.1 63.9 59.3
32*32 32*32 52.3 63.7 59.3


비교적 스프라이트의 크기는 프레임에 미치는 영향이 적었고, 타일의 개수에 따라서 프레임에 큰 영향을 미친다는 것을 알아냈다.

실제 게임에서는 타일위에 더 많은 스프라이트를 사용 할 예정이니까 안정적인 프레임이 출력 타일로 사용해야 될꺼같다.

기획적으로 더 많은 타일을 원한다면 소스 내부로 들어가서 타일에 관련된 부분을 좀 더 최적화 시켜야하겠다. 
cygwin에서 ndk를 이용해서 빌드했는데 다음과 같은 에러를 토해냈다.

StaticLibrary  : libstdc++.a
Prebuilt       : libstlport_static.a <= <NDK>/sources/cxx-stl/stlport/libs/armeabi/
SharedLibrary  : libcocos2d.so
D:/Dev/android-ndk-r6b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/b                                 in/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe: cannot find -lpng
collect2: ld returned 1 exit status
/cygdrive/d/Dev/android-ndk-r6b/build/core/build-binary.mk:286: recipe for target `/cygdrive/d/Dev/cocos2d/IronAge/android/obj/local/armeabi/libcocos2d.so' failed
make: *** [/cygdrive/d/Dev/cocos2d/IronAge/android/obj/local/armeabi/libcocos2d.so] Error 1
make: Leaving directory `/cygdrive/d/Dev/cocos2d/IronAge/android'

문제는 cocos2d-x 폴더에 *.a, *.so 파일이 없어서 발생한 문제였다.

 왜 이러한 문제가 발생했냐하면 cocos2d-x 소스를 SVN으로 관리 할려고  cocos2d 폴더 자체를 커밋하는 과정에서 *.a *.so 파일이 제대로 svn에 커밋되지 않았다.

이유는 svn에서 이 파일들은 아예 버전관리를 하지 않았다. 그래서 일일이 하나씩 추가해줘서 해결했다.
svn에서 관리하는 파일 확장자명을 설정하는 방법이 있을꺼 같긴한데... 그건 패스~




이것저것 프레임 테스트를 하다보면 순간 프레임도 순간 프레임이지만 어플실행 이후 평균 프레임을 측정해야 할 때가 있습니다. 그럴 때 사용하는 코드입니다.


CCDirector.cpp 
bool CCDirector::init(void)
{
...
// FPS
m_bDisplayFPS = false;
m_uTotalFrames = m_uFrames = 0;
m_pszFPS = new char[50];
m_pLastUpdate = new struct cc_timeval();
...

 
CCDirector.cpp

void CCDirector::showFPS(void)
{
m_uFrames++;
m_fAccumDt += m_fDeltaTime;

if (m_fAccumDt > CC_DIRECTOR_FPS_INTERVAL)
{
m_fFrameRate = m_uFrames / m_fAccumDt;
m_uFrames = 0;
m_fAccumDt = 0;

static ccTime fAllFrameRate = 0;
static int    nFrameCnt = 0;
static ccTime nMax = 0;
static ccTime nMin = 60;

if( nMax < m_fFrameRate )
nMax = m_fFrameRate;

if( nMin > m_fFrameRate )
nMin = m_fFrameRate;

fAllFrameRate += m_fFrameRate;
nFrameCnt++;

// 실시간, 최소, 최대, 평균, 흐른시간
sprintf(m_pszFPS, "R:%.1f MIN:%.1f MAX:%.1f AVG:%.1f SEC:%d", m_fFrameRate, nMin, nMax, fAllFrameRate / nFrameCnt, nFrameCnt / 2);
m_pFPSLabel->setString(m_pszFPS);
}

    m_pFPSLabel->draw();
}
 

지금 사용중인 개발 환경
cocos2d-1.0.1-x-0.11.0 @ Jan 13, 2012
android-ndk-r7-crystax-4-windows.zip 

cocos2d-x 11버전과 ndk7 버전으로 세팅을 완료 했는데, vs2008로 작업하고 cygwin으로 빌드해서 이클립스로 넘기고 안드로이드에 삽입하면 화면을 터치하면 앱이 뻑나서 죽는 문제가 발생한다.

처음에는 cocos2d-x문제인줄 알고 다른 버전으로 계속 바꾸다가...
혹시나 싶어서 ndk를 6b로 바꾸니까 문제가 해결되었다.

참고

D:\Dev\cocos2d\cocos2dx\Android.mk 열어서 아래를 추가
LOCAL_CFLAGS := -DUSE_FILE32API -DGL_GLEXT_PROTOTYPES = 1


이전 블로그를 정확하게 정독했다는 가정하에 설명합니다.

1. cocos2d\create-android-project.bat 로 안드로이드 프로젝트를 만듭니다.

2. 내가 작업했던 폴더에 있는 Resources, Classes 폴더에 있는 것을 전부 1번에서 생성한 프로젝트 폴더안에 복사합니다.

3. 1번에서 생성한 폴더안  \Classes\Android.mk 파일을 열어서  LOCAL_SRC_FILES에 내가 사용한 모든 cpp를 넣어줍니다.

Android.mk 파일
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_logic

LOCAL_SRC_FILES := AppDelegate.cpp \
                   HelloWorldScene.cpp \
                   여기에 삽입!

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../cocos2dx \
                    $(LOCAL_PATH)/../../cocos2dx/platform \
                    $(LOCAL_PATH)/../../cocos2dx/include \
                    $(LOCAL_PATH)/../../CocosDenshion/include \
                    $(LOCAL_PATH)/../../cocos2dx/lua_support 

LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../android/libs/$(TARGET_ARCH_ABI)) \
                -lcocos2d -lcocosdenshion \
                -L$(call host-path, $(LOCAL_PATH)/../../cocos2dx/platform/third_party/android/libraries/$(TARGET_ARCH_ABI)) -lcurl
            
include $(BUILD_SHARED_LIBRARY) 

4. cygwin실행하고 해당 폴더로 가셔서 "sh build_native.sh" 명령을 내리면 됩니다.






 

+ Recent posts