안드로이드/cocos2d-x2016. 1. 17. 02:30

지난 게시물에 이어서

벌집모양으로 배치한 육각형 테두리 안에 여러가지 색의 블록을 위치시킬 것이다.

 

 

 

 

블록 위치 시키기

CGameLayer.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef PuzzleGame_GameLayer
#define PuzzleGame_GameLayer
 
#include "Common.h"
 
class CGameLayer : public cocos2d::Layer {
public:
    static cocos2d::Scene* createScene();
 
    virtual bool init();
 
    void startGame();
 
    CREATE_FUNC(CGameLayer);
 
protected:
    Sprite* m_pBoard[COLUMN_COUNT][ROW_COUNT];
};
 
#endif
cs

 

CGameLayer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void CGameLayer::startGame() {
    for (int x = 0; x < COLUMN_COUNT; x++) {
        for (int y = 0; y < ROW_COUNT; y++) {
            if (x == COLUMN_COUNT - 1 && y % 2 != 0continue;
 
            Sprite* pGameObjectBack = Sprite::create("blockBack.png");
            Sprite* pGameObject = Sprite::create("blockBlue.png");
            m_pBoard[x][y] = pGameObject;
 
            pGameObjectBack->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObjectBack->setPosition(Common::ComputeXY((float)x, (float)y));
            pGameObject->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObject->setPosition(Common::ComputeXY((float)x, (float)y));
            
 
            addChild(pGameObjectBack, 1);
            addChild(pGameObject, 2);
        }
    }
}
cs

빨간 줄로 표시한 부분이 추가된 부분이다.

4행 - 짝수 열의 가장 오른쪽 블록을 생성하지 않게 한다.

8행 - m_pBoard[][]에 불러온 이미지를 저장시키는데

     이 것이 앞으로 블록을 제어할 때 쓸 2차원 배열이다.

12,13행 - 육각형테두리와 동일한 방식으로 동일한 좌표로 설정한다.

17행 - Depth를 2로 설정해 육각형테두리보다 위에 그려지게 한다.

 

 정상적으로 파란 색 블록이 위치된 것을 볼 수 있다.

 

 

 

 

 

 

이제 여러가지 색깔을 나타내보자

CGameObject.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef PuzzleGame_GameObject
#define PuzzleGame_GameObject
 
#include "Common.h"
 
class CGameObject : public Sprite {
public:
    CGameObject();
    ~CGameObject();
 
protected:
    static CGameObject* create(const char* pszFileName, const CCRect& rect);
 
public:
    static CGameObject* Create(int type);
    int GetType();
    void SetType(int type);
 
private:
    int m_type;
};
 
#endif
cs

 

CGameObject.cpp

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
#include "GameObject.h"
 
USING_NS_CC;
 
CGameObject::CGameObject() {}
CGameObject::~CGameObject() {}
 
CGameObject* CGameObject::create(const char* pszFileName, const CCRect& rect) {
    CGameObject* pSprite = new CGameObject();
    if (pSprite && pSprite->initWithFile(pszFileName, rect)) {
        pSprite->autorelease();
        return pSprite;
    }
    CC_SAFE_DELETE(pSprite);
    return NULL;
}
 
CGameObject* CGameObject::Create(int type) {
    static std::string objectNames[TYPE_COUNT] = {
        "blockBlue.png",
        "blockBrown.png",
        "blockGreen.png",
        "blockPink.png",
        "blockGreen.png",
        "blockYellow.png"
    };
    if(type<0 || type>TYPE_COUNT-1return NULL;
    CGameObject* pGameObject = CGameObject::create(objectNames[type].c_str(),
        CCRectMake(0.0f, 0.0f, OBJECT_WIDTH, OBJECT_HEIGHT));
    return pGameObject;
}
 
int CGameObject::GetType() { return m_type; }
void CGameObject::SetType(int type) { m_type = type; }
cs

 게임 오브젝트가 많아지고 있으므로 게임 오브젝트를 제어하기 위한 클래스를 추가하여 분리했다.

8~16행 - protected로 처리되어 있는 CGameObject클래스에서 사용할 블록 생성함수이다.

            파일 이름을 받아와 그에 해당하는 블록을 생성한다.

18~31행 - CGameObject클래스 외부에서 호출하는 블록 생성함수이다.

              int type인자로 받아온 블록 번호를 통해 그에 해당하는 블록을 생성한다.

              24행은 원래 Green이 아닌 White인데 디버깅을 위해서 임시로 바꿔두었다.

              어떤 디버깅인지는 잠시 뒤에 나온다.

33,44행 - 나중에 사용될 get,set함수이다. 블록의 색을 바꿀 수 있고, 블록이 현재 무슨 색인지를 검사한다.

 

 

CGameLayer.cpp 

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
void CGameLayer::startGame() {
    srand(time(NULL));
 
    for (int x = 0; x < COLUMN_COUNT; x++) {
        for (int y = 0; y < ROW_COUNT; y++) {
            if (x == COLUMN_COUNT - 1 && y % 2 != 0continue;
 
            int type = rand() % TYPE_COUNT;
 
            Sprite* pGameObjectBack = Sprite::create("blockBack.png");
            CGameObject* pGameObject = CGameObject::Create(type);
            m_pBoard[x][y] = pGameObject;
 
 
            pGameObjectBack->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObjectBack->setPosition(Common::ComputeXY((float)x, (float)y));
            pGameObject->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObject->setPosition(Common::ComputeXY((float)x, (float)y));
            
 
            addChild(pGameObjectBack, 1);
            addChild(pGameObject, 2);
        }
    }
}
cs

 빨간 줄로 표시한 부분이 추가된 부분이다.

2행 - 랜덤함수 시드 초기화

8행 - 0~TYPE_COUNT-1 사이의 랜덤 값을 선정

11행 - 랜덤으로 정해진 블록 번호로 블록을 생성

 

 

 

 

 

 

 

 

좌표계가 어떻게 되있는지 디버깅해보자

CGameLayer.cpp

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
void CGameLayer::startGame() {
    srand(time(NULL));
 
    for (int x = 0; x < COLUMN_COUNT; x++) {
        for (int y = 0; y < ROW_COUNT; y++) {
            if (x == COLUMN_COUNT - 1 && y % 2 != 0continue;
 
            int type = rand() % TYPE_COUNT;
 
            Sprite* pGameObjectBack = Sprite::create("blockBack.png");
            CGameObject* pGameObject = CGameObject::Create(type);
            m_pBoard[x][y] = pGameObject;
 
            
            // debug --------------------------------------------------------------
            // 각 블록의 좌표를 출력
            std::string str, str2, str3;
            str = std::to_string(x);
            str2 = ",";
            str3 = std::to_string(y);
            str.append(str2);
            str.append(str3);
            auto label = LabelTTF::create(str, "Arial"50);
            Point pos; pos.set(Common::ComputeXY((float)x, (float)y));
            label->setPosition(pos);
            // end of debug -------------------------------------------------------
            
 
 
            pGameObjectBack->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObjectBack->setPosition(Common::ComputeXY((float)x, (float)y));
            pGameObject->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObject->setPosition(Common::ComputeXY((float)x, (float)y));
            
 
            addChild(pGameObjectBack, 1);
            addChild(pGameObject, 2);
            addChild(label, 3);
        }
    }
    
}
cs

빨간 줄로 표시한 부분이 추가된 부분이다.

stdio.h와 string.h를 사용하였다.

17~22행 - 2차원 배열의 좌표값을 "x,y"형태로 string에 저장한다.

23~25행 - 글자를 출력하는 기능을 하는 LabelTTF를 통해 블록과 같은 좌표에 글자를 출력한다.

38행 - 글자가 블록보다 위에 있기 위해 Depth를 3으로 설정했다.

 

 

각 블록이 배열의 어느 좌표에 저장되고 있는지를 확인할 수 있다.

이 디버깅은 당분간 계속 켜 둘 예정이다.

Posted by gharlic
안드로이드/cocos2d-x2016. 1. 17. 01:50

게임화면에 블록 출력하기

 http://gharlic.tistory.com/23

위 게시물에서 CGameLayer.h와 CGameLayer.cpp를 생성하는 것 까지 했을 것이다.

이 번엔 전 게시물에서 만든 리소스를 바탕으로 게임화면에 블록을 출력하도록 하겠다.

 

 

 

 

 

리소스 파일은 어디로?

제작된 리소스 파일들은 위 사진과 같이 프로젝트 폴더\Resources에 위치시키면 된다.

MFC에서 처럼 따로 Visual Studio에서 불러와 ID를 매겨 사용할 필요없이

그냥 저대로 두고 사용할 수 있다.

 

 

 

 

 

먼저 배경 출력하기

 

CGameLayer.cpp

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
#include "GameLayer.h"
#include "GameObject.h"
#include <stdio.h>
#include <string.h>
 
 
#define COCOS2D_DEBUG 1
USING_NS_CC;
 
cocos2d::Scene* CGameLayer::createScene() {
    //cocos2d::Scene* pScene = cocos2d::Scene::create();
    //CGameLayer* pLayer = CGameLayer::create();
 
    auto pScene = Scene::create();
    auto pLayer = CGameLayer::create();
 
    pScene->addChild(pLayer);
 
    return pScene;
}
 
bool CGameLayer::init() {
    if (!Layer::init()) { return false; }
 
    // 배경 이미지 출력
    cocos2d::Sprite* pBackgroundSprite = cocos2d::Sprite::create("background.png");
    pBackgroundSprite->setPosition(cocos2d::CCPointZero);
    pBackgroundSprite->setAnchorPoint(ccp((float)0, (float)0));
    addChild(pBackgroundSprite);
 
    return true;
}
cs

26행 - background.png를 불러오고 있다.

27행 ~ 28행 - 0,0에 이미지가 위치하게 한다. 참고로 cocos2d-x의 좌표계는 좌측하단이 0,0이다.

2행 - addChild함수를 사용해 Sprite를 화면에 출력한다.

 

Ctrl+F5를 눌러 실행해보면 배경이미지가 출력됨을 알 수 있다.

옆에 검은 테두리는 신경쓸 필요없다. 찜찜하면 이클립스로 넘어가 본인 휴대폰으로 출력해볼 수 있다.

방법은 다음 게시물에 있다. http://gharlic.tistory.com/21

 

 

 

 

 

 

 

일단 육각형 테두리 하나 출력해보기

 

CGameLayer.cpp

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
#include "GameLayer.h"
#include "GameObject.h"
#include <stdio.h>
#include <string.h>
 
 
#define COCOS2D_DEBUG 1
USING_NS_CC;
 
cocos2d::Scene* CGameLayer::createScene() {
    //cocos2d::Scene* pScene = cocos2d::Scene::create();
    //CGameLayer* pLayer = CGameLayer::create();
 
    auto pScene = Scene::create();
    auto pLayer = CGameLayer::create();
 
    pScene->addChild(pLayer);
 
    return pScene;
}
 
bool CGameLayer::init() {
    if (!Layer::init()) { return false; }
 
    // 배경 이미지 출력
    cocos2d::Sprite* pBackgroundSprite = cocos2d::Sprite::create("background.png");
    pBackgroundSprite->setPosition(cocos2d::CCPointZero);
    pBackgroundSprite->setAnchorPoint(ccp((float)0, (float)0));
    addChild(pBackgroundSprite);
 
    m_winSize = Director::sharedDirector()->getWinSize();
    startGame();
    
    return true;
}
 
void CGameLayer::startGame() {
    Sprite* pGameObjectBack = Sprite::create("blockBack.png");    
    pGameObjectBack->setAnchorPoint(ccp(0.5f, 0.5f));
    pGameObjectBack->setPosition(ccp(100.0f,100.0f));
    addChild(pGameObjectBack, 1);
}
cs

붉은 색으로 처리된 부분이 추가된 부분이다.

38행 - 육각형 테두리 이미지인 blockBack.png를 불러온다.

39행 - 이미지의 어느 위치를 좌표기준으로 정할지를 선택한다.

         x, y각각 0.0f ~ 1.0f까지 설정할 수 있다. 0.5f면 이미지의 중앙으로 하겠다는 것이다.

40행 - 화면의 좌측하단의 0,0을 기준으로 100,100에 위치시킨다.

41행 - 2번째 인자 '1'은 이미지를 출력하는 Depth값이다.

         배경이미지는 설정하지 않았으므로 '0'이 되고

         배경이미지 보다 위에 위치하기 위해 '1'을 줬다.

 

실행시켜보면 좌측하단에 육각형 테두리가 출력됬음을 볼 수 있다.

 

 

 

 

테두리를 화면에 벌집모양으로 뿌려보자

 

Common.h

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
#ifndef PuzzleTest_Common
#define PuzzleTest_Common
#include "cocos2d.h"
 
USING_NS_CC;
 
#define DESIGN_WIDTH    1080.0f
#define DESIGN_HEIGHT    1920.0f
 
#define ROW_COUNT        18
#define COLUMN_COUNT    5
 
#define TYPE_COUNT        6
 
#define OBJECT_WIDTH    150
#define OBJECT_HEIGHT    130
 
class Common {
public :
    static float ComputeX(Point point);
    static float ComputeY(Point point);
    static CCPoint ComputeXY(float x, float y);
};
 
#endif
cs

 이전에 만들었던 공통선언파일에 내용을 추가했다.

블록의 갯수나 종류, 크기 같은 내용을 자주 사용하게 될 것이기 때문이다.

이렇게 따로 빼 놓으면 유지보수면에서 간편하다.

 

10,11행 - 블록의 가로,세로 갯수

13행 - 블록 종류의 갯수

15,16행 - 블록의 가로,세로 크기

18~23행 - 블록의 좌표를 계산해주는 함수 ( 2차원 배열 -> 화면의 좌표로 위치지정 )

 

 

Common.cpp

1
2
3
4
5
6
7
8
9
10
11
#include "Common.h"
 
// 내부좌표 to 화면좌표
float Common::ComputeX(Point point) { 
    if ((int)point.y % 2 == 0return 90 + point.x*OBJECT_WIDTH*1.5;
    else return 90 + OBJECT_WIDTH*0.75 + point.x*OBJECT_WIDTH*1.5;
}
float Common::ComputeY(Point point) { return CCDirector::sharedDirector()->getWinSize().height - 535.0f - point.y*OBJECT_HEIGHT / 2; }
CCPoint Common::ComputeXY(float x, float y) { return ccp(ComputeX(ccp(x,y)), ComputeY(ccp(x,y))); }
 
 
cs

 Common클래스의 내용을 구현하기 위해 Common.cpp도 Classes폴더에 추가시켰다.

4~7행 - 블록의 가로 좌표를 결정한다.

8행 - 블록의 세로 좌표를 결정한다.

 

 꽤나 복잡한 식을 사용해서 블록의 위치를 결정하고 있다.

각각이 어떤 역할을 하는지는 결과화면을 비교해서 알아보겠다.

 

 

 좌측 : 정상적인 식

 우측 : ComputeX에서 "90 +"가 없을 때

가장 앞에 있는 상수는 블록의 집합이 시작되는 좌표를 결정한다.

 

 

 

 좌측 : 정상적인 식을 2줄까지만 출력

 우측 : ComputeX에서 if문 없이 return 90 + point.x*OBJECT_WIDTH*1.5; 식만 사용

ComputeX에서 if문은 y값이 홀수인 짝수인지를 판별하고 그에 따라 다른 결과를 반환한다.

짝수 행은 + OBJECT_WIDTH*0.75 식으로 블록 길이의 3/4만큼 더 뒤에서부터 출력하면 맞게 된다.

 

 

 

 

 좌측 : 정상적인 식을 3줄까지만 출력

 중앙 : ComputeY에서 CCDirector::sharedDirector()->getWinSize().height - 535.0f - 을 빼고 출력

 우측 : ComputeY에서 /  빼고 출력

 

CCDirector::sharedDirector()->getWinSize().height 식은 현재 구동중인 기기의 화면크기에서 세로길이를 구해오는 함수이다.

cocos2D-x의 좌표계는 좌측하단부터 시작한다. 일반적인 y축과 방향이 반대인 것이다.

일반적인 y축 방향으로 개발하기 위해 '전체길이 - 좌표'식으로 방향을 맞추는 것이다.

 

ComputeY에서 / 2는 블록이 맞물리게 하기 위해서 개행을 반칸 씩만 하게 하는 역할을 한다.

 

 

GameLayer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
void CGameLayer::startGame() {
    for (int x = 0; x < COLUMN_COUNT; x++) {
        for (int y = 0; y < ROW_COUNT; y++) {
 
            Sprite* pGameObjectBack = Sprite::create("blockBack.png")
 
            pGameObjectBack->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObjectBack->setPosition(Common::ComputeXY((float)x, (float)y));
 
            addChild(pGameObjectBack, 1);
        }
    }
}
cs

 

Common.h에서 설정한 내용들을 여기에서 사용하였다.

2,3행 - Common.h에서 설정한 가로,세로 갯수 만큼 반복한다.

8행 - Common.h의 ComputeXY함수에 인자 x,y를 전달해 각각의 좌표를 받아와 적용한다.

9행 - 출력 

 

 

 

 

다음 게시물에서 계속..

 

 

 

 

 

 

 

 

 

 

 

Posted by gharlic
안드로이드/cocos2d-x2016. 1. 17. 00:32

리소스 만들기

프로젝트에서 사용되는 이미지 파일을 제작할 필요가 있다.

결론만 얘기하면 포토샵에서 해상도 고려해서 png파일로 대충 만들어 오면 된다.

디자인 해상도를 고려해 1080x1920으로 제작한다.

 

 

귀찮은 사람은 맨 아래로 내려가면 이 게시물에서 만들 리소스파일을 다운 받을 수 있다.

 

 

 

Backround 배경 이미지

 프렌즈팝을 참고하여 디자인하였다.

상단 : 1080x450

중앙 : 1080x1270

하단 : 1080x200

 

 

 미술에 재능이 없어서 예쁘게는 못만든다.

레이어 분리해서 대충 페인트통으로 색 채운 다음

조금 어두운 색으로 끝 부분에만 그라이데션을 준다.

Shift키를 누르면 마우스를 수직으로만 움직일 수 있다.

 

 상단 하단을 따로 관리하는 것이 유지관리면에서 좋지만

예제 작품이니 간단하게 그냥 통으로 만든다.

background.png로 저장하였다.

 

 

 

 

육각형 테두리 만들기

150x130 Pixel사이즈로 새 이미지를 생성한다.

좌측 툴 바의 다각형 그리기 도구를 사용해 육각형을 그린다.

Shift키를 누른 상태로 드래그하면 위 와 같은 모양으로 만들어진다.

 상단 메뉴에서 칠을 활성화하고 획은 비활성화 한다.

우측의 W 와  H를 설정해 150x130을 꽉 채우도록 한다.

 

레이어를 우 클릭하면 혼합 옵션을 열 수 있다.

탭에서 획을 활성화하고 위치를 안쪽, 색상을 조금 어두운 색으로 설정한다.

 

 

 

 

 

 

블록 만들기

 육각형 테두리 내부에 위치할 블록을 만든다.

육각형 테두리와 동일한 좌표를 사용할 것이므로 같은 크기로

150x130 Pixel사이즈로 새 이미지를 생성한다.

 적당한 위치에 좌측 툴바의 타원 그리기 도구를 사용해 원을 그린다.

Shift키를 누른 상태로 드래그하면 타원이 아닌 원을 그릴 수 있다.

육각형테두리와 마찬가지로 상단 메뉴에서 칠과 획을 설정한다.

 

레이어를 우 클릭하면 혼합 옵션을 열어 경사와 엠보스 탭에서 다음과 같이 설정한다.

경사와 엠보스 기능은 도형을 입체적으로 만들어주는 역할을 한다.

 

색 상 오버레이 탭에서 색상을 변경하여 여러가지 색을 나타낼 수 있다.

원하는 블록의 종류만큼 원하는 색으로 만들어 .png파일로 저장한다.

 

 

 

 

투명도?

 배경을 채우지 않은 상태로 .png파일로 저장하면

cocos2d-x에서 출력했을때 배경이 투명한 상태로 적용이 된다.

배경색을 투명으로 하는 법은 고려하지 않아도 된다는 얘기다.

 

 

일단 여기까지만 만들고 다음 게시물에서 게임화면에 배치해보도록 하겠다.

 

 

지금까지 만든 리소스 파일은 아래 압축파일에서 받을 수 있다.

puzzleTest.zip

Posted by gharlic