1. 캐릭터 파일명 의미

캐릭터 애니메이션 인덱스_애니메이션 동작 타입_동작 타입에 사용될 스프라이트들.png
ex1> 000_000_000.png

파일명은 무조건 숫자 하나당 3글자로 해야 한다.

ex2> 1_1_1.png (x)

ex3> 001_001_001.png (o)



캐릭터 애니메이션 인덱스:
게임안에서 각각 캐릭터를 식별할 유니크 값으로 사용된다.

애니메이션 동작 타입:
000 = 위쪽을 보고 가만히 숨쉬기 
001 = 아래쪽  보고 가만히 숨쉬기  
002 = 왼쪽  보고 가만히 숨쉬기  
003 = 오른쪽  보고 가만히 숨쉬기

004 = 위 이동

005 = 아래 이동

006 = 왼쪽 이동

007 = 오른쪽 이동

008 = 위 공격

009 = 아래 공격

010 = 왼쪽 공격

011 = 오른쪽 공격

012 = 위 피격

013 = 아래 피격

014 = 왼쪽 피격

015 = 오른쪽 피격


향후 캐릭터가 웃는다던지 놀란다던지 애니메이션 동작이 늘어날 때 그 애니메이션 동작에 식별할 값으로 사용 된다.
ex> 016 = 캐릭터 웃기
       017 = 캐릭터 울기 
 

동작 타입에 사용될 스프라이트들:
동작 타입에 따른 플레이 해야 될 스프라이트의 모아놓은 것이다. 최대 100개까지 사용 가능하다.
(000_000_000 ~ 000_000_100 까지 사용 가능)

ex>


동작타입이 중복 될 수는 없음..
예를 들어 왼쪽으로 걸으면서 웃는건 안됨...
왼쪽으로 걸으면서 웃을려면 걸으면서 웃는 스프라이트를 만들어서 동작타입에 추가해야 함...




2. 게임에 사용될 데이터로 가공
 

http://zwoptexapp.com/ 
사이트에서 플레쉬 버전으로 들어가서 파일들을 작업하면 된다.
그럼 아웃풋으로 coordinates.plist, coordinates.png 파일을 뽑을 수 있는데 이것으로 게임에 사용된다.


애니메이션 속도는 1프레임당 0.2.초를 사용한다.

애니메이션 속도를 지정할 수 있도록 향후 계획중이다.

현재는 1동작에 대한 애니메이션을 처음부터 끝까지 도는데 1초가 걸린다.

프레임이 만약 2개라면 0.5초에 한번씩 2개의 스프라이트를 뿌리고

프레임이 만약 4개라면 0.25초에 한번씩 4개의 스프라이트를 뿌린다.!




어느 순간 갑자기 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

+ Recent posts