안드로이드/cocos2d-x2016. 1. 17. 04:39

지난 시간에

터치를 통해 블록이 정상적으로 선택됨을 확인했다.

이재 블록을 터치->드래그->릴리즈를 통해 블록을 교환하는 기능을 구현할 것이다.

 

터치->드래그->릴리즈 구현하기

CGameLayer.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
26
27
28
29
30
31
32
#ifndef PuzzleGame_GameLayer
#define PuzzleGame_GameLayer
 
#include "Common.h"
#include "GameObject.h"

 

 
class CGameLayer : public cocos2d::Layer {
public:
    static cocos2d::Scene* createScene();
 
    virtual bool init();
 
    void startGame();
 
    bool isAdjacent(int x1, int y1, int x2, int y2);    // 두 블록이 서로 인접한 블록인지
    void swapObjects(int x1, int y1, int x2, int y2);    // 두 블록의 위치를 서로 교환
 
    void onTouchesBegan(const std::vector<cocos2d::Touch*>&pTouches, cocos2d::Event* pEvent);
    void onTouchesMoved(const std::vector<cocos2d::Touch*>&pTouches, cocos2d::Event* pEvent);
    void onTouchesEnded(const std::vector<cocos2d::Touch*>&pTouches, cocos2d::Event* pEvent);
 
    CREATE_FUNC(CGameLayer);
 
protected:
    CGameObject* m_pBoard[COLUMN_COUNT][ROW_COUNT];
    Size m_winSize;
 
    bool m_bTouchStarted;    // 터치가 시작되었는지
    int m_gestureStartBoardX; 
    int m_gestureStartBoardY; // 터치가 시작된 블록이 어느 블록인지
};
 
#endif
cs

 빨간 색으로 표시된 부분이 변경된 부분이다.

 초록색으로 표시된 부분은 추가로 발견된 실수한 부분이다.

 

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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "GameLayer.h"
#include "GameObject.h"
#include <stdio.h>
#include <string.h>
 
 
#define COCOS2D_DEBUG 1
USING_NS_CC;
 
cocos2d::Scene* CGameLayer::createScene() {
    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);
 
    
    // 터치 초기화
    EventListenerTouchAllAtOnce* listener = EventListenerTouchAllAtOnce::create();
    listener->onTouchesBegan = CC_CALLBACK_2(CGameLayer::onTouchesBegan, this);
    listener->onTouchesMoved= CC_CALLBACK_2(CGameLayer::onTouchesMoved, this);
    listener->onTouchesEnded = CC_CALLBACK_2(CGameLayer::onTouchesEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
 
 
    m_winSize = Director::sharedDirector()->getWinSize();
    startGame();
    return true;
}
 
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(x, y));
            label->setPosition(pos);
            // end of debug -------------------------------------------------------
            
 
            pGameObjectBack->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObjectBack->setPosition(Common::ComputeXY(x, y));
            pGameObject->setAnchorPoint(ccp(0.5f, 0.5f));
            pGameObject->setPosition(Common::ComputeXY(x, y));
            
 
            addChild(pGameObjectBack, 1);
            addChild(pGameObject, 2);
            addChild(label, 3);
        }
    }
    m_bTouchStarted = false;
 
}
 
 
// [터치 관련 ]
// ==============================================================================================================
void CGameLayer::onTouchesBegan(const std::vector<cocos2d::Touch*>&pTouches, cocos2d::Event* pEvent) {
    if (!m_bTouchStarted) {
        Touch* pTouch = (Touch*)pTouches.back();
        Point point = pTouch->getLocation();
 
        m_gestureStartBoardX = Common::ComputeBoardX(point);
        m_gestureStartBoardY = Common::ComputeBoardY(point);
 
        m_bTouchStarted = true;
    }
}
 
void CGameLayer::onTouchesMoved(const std::vector<cocos2d::Touch*>&pTouches, cocos2d::Event* pEvent) {
    if (m_bTouchStarted) {
        Touch* pTouch = (Touch*)pTouches.back();
        Point point = pTouch->getLocation();
    }
}
 
void CGameLayer::onTouchesEnded(const std::vector<cocos2d::Touch*>&pTouches, cocos2d::Event* pEvent) {
    if (m_bTouchStarted) {
        Touch* pTouch = (Touch*)pTouches.back();
        Point point = pTouch->getLocation();
 
        m_bTouchStarted = false;
 
        int boardX = Common::ComputeBoardX(point);
        int boardY = Common::ComputeBoardY(point);
 
        if (m_gestureStartBoardX != boardX || m_gestureStartBoardY != boardY)
        if (isAdjacent(m_gestureStartBoardX, m_gestureStartBoardY, boardX, boardY))
            swapObjects(m_gestureStartBoardX, m_gestureStartBoardY, boardX, boardY);
    }
}
 
// 두 블록이 서로 인접한 블록인지 검사
bool CGameLayer::isAdjacent(int x1, int y1, int x2, int y2) {
    if (y1 % 2 == 0) {
        if ((x1==x2) && (y1 - 2 == y2 || y1 - 1 == y2 || y1 + 1 == y2 || y1 + 2 == y2))
            return true;
        if ((x1 - 1 == x2) && (y1 - 1 == y2 || y1 + 1 == y2))
            return true;
    }
    else {
        if ((x1 == x2) && (y1 - 2 == y2 || y1 - 1 == y2 || y1 + 1 == y2 || y1 + 2 == y2))
            return true;
        if ((x1 + 1 == x2) && (y1 - 1 == y2 || y1 + 1 == y2))
            return true;
    }
    return false;
}
 
// 두 블록의 위치를 서로 교환
void CGameLayer::swapObjects(int x1, int y1, int x2, int y2) {
    CGameObject* pTemp = m_pBoard[x1][y1];
    m_pBoard[x1][y1] = m_pBoard[x2][y2];
    m_pBoard[x2][y2] = pTemp;
 
    m_pBoard[x1][y1]->setPosition(Common::ComputeXY(x1, y1));
    m_pBoard[x2][y2]->setPosition(Common::ComputeXY(x2, y2));
}
// ==============================================================================================================
cs

 빨간 색으로 표시된 부분이 추가된 부분이다.

 

80행 - '터치가 시작되었는지' 변수 초기화

87~97행 - 터치가 시작되었을 때 호출되는 이벤트 함수

              터치가 시작되었는지와 터치가 시작된 위치를 기억하게 한다.

106~120행 - 터치가 종료되었을 때호출되는 이벤트 함수

                 터치가 종료되면

                 해당 위치의 블록이 처음 블록과 인접한 블록인지를 검사하고

                 맞다면 두 블록의 위치를 바꾼다.

 

123~137행 - 두 블록이 인접한 블록인지를 검사하는데

                 블록을 그릴 때와 마찬가지로 y가 홀수일 때와 짝수일 때를 구분지어서 구현한다.

위 사진을 분석해보면

 y1이 짝수인 2,2를 기준으로 인접한 여섯블록의 공통점을 보면

x1==x2일 때는 y1과 y2가 1~2의 차이가 나고

x1-1==x2일 때는 y1과 y2가 1 차이난다는 것을 알 수 있다.

 마찬가지로 y1이 홀수일 때를 기준으로 3,3을 보면

x1==x2일 때는  y1과 y2가 1~2의 차이가 나고

x1+1==x2일 때는 y1과 y2가 1 차이난다는 것을 알 수 있다.

 

 이렇게 분석한 값을 바탕으로 구현한 것이다.

 

139~140행 - 두 블록의 위치를 바꾸는 함수로

                 일반적인 swap함수처럼 temp변수를 활용해 배열의 두 값을 변경하고

                 두 블록의 화면 상 위치에 적용한다.

 

 

Posted by gharlic