[cocos2d-x] Makeschool 강좌 (4) Xcode를 이용해 코딩하기 2편

     



지난시간에 이어 Touch 이벤트 코드를 작성해 보겠습니다.




Grid.cpp에 위 메소드를 추가합니다.

터치이벤트 코드인데, 여태까지 해왔던 터치이벤트와 다르게 처리하는군요..? 여태까지 해왔던 방법은 메인 메소드에 Touch메소드를 전부 선언하고 사용하는 거였는데, 여기서는 필요한 터치 이벤트만 그때 그때 선언하는 방법입니다. 


안드로이드에 비유해보면 onClickListener 를 상속받아 한꺼번에 onClick메소드를 호출하는 것이 아니라 중간중간에 새롭게 onClickListener를 선언하고 그안에 onClick메소드를 정의하는 방법과 같습니다.


여기서는 TouchOneByOne을 선언하고 onTouchBegan만 선언했습니다. 터치관련 메소드에는 Began말고도 Moved, Ended, Canceled가 있지만, 여기서는 Began만 사용한다는 군요.

여기서 상당히 특이한? 표현법이 있는데 [&](parameter)입니다.


C++ 11버전 이후에 추가된 표현법이라고 하는군요. 자세한 설명은 링크를 클릭.


이렇게 선언한 onTouchBegan은 터치가 일어날때마다 자동으로 실행됩니다.

실행코드에는 가장먼저 grid 스프라이트를 불러옵니다. 그리고는 입력 파라메터에서 touch값을 이용해 사용자가 어디를 눌렀는지 좌표를 Vec2값으로 받습니다. 그 다음 포인터를 사용해 터치한 지점에 있는 Creature를 가르키는 변수를 만듭니다. 그리고 만약 터치된 곳에 Creature가 있으면 상태를 반대로 바꿔주는 조건문을 넣습니다.


마지막으로 EventDispatcher에 touchListener를 등록하고 마무리합니다.




선택한 좌표의 Creature를 어떻게 감지할까요? creatureForTouchLocation 함수를 이용해 판단합니다. 터치된것이 grid 안인지 우선 판단하고 grid 밖이면 null포인터를 반환합니다. 터치된 좌표를 cell 높이와 넓이로 나누면 어느 칸에 있는 cell인지 알 수 있겠죠?


이제 isValidIndex 와 indexForRowColumn 메소드를 만들어서 터치한곳이 올바른 좌표이고, 해당 좌표의 Creature를 반환하는 메소드를 만듭니다.




저번에 주석처리 했던 this->setupTouchHandling();의 주석을 지우고 실행하면 터치한 곳의 cell이 나타났다 사라졌다 하는 것을 볼 수 있습니다.





자 이제 게임을 돌아가게 하기 위해 몇가지 메소드를 추가합니다. (타이머나 점수카운트 등..)




먼저 HelloWorldScene.h에 가서 private: 변수와 메소드를 추가합니다. 헤더파일도 추가됬다는거 참고하세요.


HelloWorldScene.cpp에서는 코코스 스튜디오에서 만들었던 객체들을 전부 받아오는 코드를 추가합니다. 점수 텍스트나 버튼 같은거를 객체로 받아와야 사용할 수 있겠죠?




rootNode를 선언하는 곳과 addChild(rootNode) 사이에 위와같이 객체를 받아오는 코드를 추가합니다. getChildByName을 이용해 코코스 스튜디오에서 붙였던 이름으로 객체들을 불러올 수 있습니다.


게임의 진행을 하나의 step으로 정의합니다. step이 계속 실행되는 것이 게임이 진행되는 것이지요. 일종의 시간의 단위라고 할까요?




play버튼을 누르면 step을 0.5초마다 실행하게 합니다. pause버튼을 누르면 step이 멈추지요.

step에서는 evolveStep을 실행하고(아마 cell을 증식시키는..?) 각종 상황을 읽어 화면에 표기합니다. 




Grid.cpp에 두 가지 변수를 리턴하는 함수를 만듭니다.


자 이제 하이라이트인 게임이 어떻게 돌아가는지 evolveStep()을 만듭니다.


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
 
 
 
 
 
 
 
 
 
 
 
void Grid::evolveStep()
{
    this->updateNeighborCount();
    
    this->updateCreature();
    
    generationCount++;
    
}
 
void Grid::updateNeighborCount()
{
    for(int row = 0; row < ROWS; ++row)
    {
        for(int col =0; col <COLUMNS; ++col)
        {
            int currentCreatureIndex = this->indexForRowColumn(row, col);
            
            Creature* currentCreature = gridArray.at(currentCreatureIndex);
            currentCreature->setLivingNeighborsCount(0);
            
            for(int nRow = row-1; nRow <=row+1++nRow)
            {
                for(int nCol = col-1; nCol<=col+1++nCol)
                {
                    bool indexVaild = this->isValidIndex(nRow, nCol);
                    
                    if(indexVaild && !(nRow == row && nCol == col))
                    {
                        int neighborIndex = this->indexForRowColumn(nRow, nCol);
                        
                        Creature* neighbor = gridArray.at(neighborIndex);
                        
                        if(neighbor->getIsAlive())
                        {
                            int livingNeighbors = currentCreature->getLivingNeighborsCount();
                            currentCreature->setLivingNeighborsCount(livingNeighbors+1);
                        }
                    }
                }
            }
        }
    }
}
 
void Grid::updateCreature()
{
    populationCount = 0;
    
    for (int row = 0; row < ROWS; ++row)
    {
        for (int col = 0; col < COLUMNS; ++col)
        {
            int currentCreatureIndex = this->indexForRowColumn(row, col);
            Creature* currentCreature = gridArray.at(currentCreatureIndex);
            
            int livingNeighbors = currentCreature->getLivingNeighborsCount();
            
            if (livingNeighbors == 3)
            {
                currentCreature->setIsAlive(true);
            }
            else if (livingNeighbors <= 1 || livingNeighbors >= 4)
            {
                currentCreature->setIsAlive(false);
            }
            
            if (currentCreature->getIsAlive())
            {
                populationCount++;
            }
        }
    }
}
 
 
 
cs


이번엔 너무 많아서 텍스트로 복사했습니다. 이 부분은 게임의 로직이 담겨있는 부분인데, 저도 잘 모르겠네요. 뭔가 cell에 배치에 따라 cell이 증식을 하게 되는데 어떤 특정 알고리즘에 따라 증식을 하게됩니다. 터치를 열라게 해서 특정 모양이 갖춰지면 cell이 증식하고 많이 증식하는것이 게임의 목표겠죠?


자세한 알고리즘은 https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Examples_of_patterns 여길 참고하세요.


이제 게임을 실행하면..?! 뭔가 실행이 됩니다. play를 누르면 아무변화가 없지만 generation값이 1씩 증가합니다. 터치를 하면 cell이 생성되고 특정 모양으로 만들면 막 증식해요.




흠 이게 무슨 재미인지는 모르겠습니다만 어째던 다만들었습니다.


몇가지 없는 기능이 있다면 Pause했을때에도 터치를 하면 cell이 생성된다는 점? 이부분은 step이 멈췄을때 touch이벤트가 발생되지 않도록 막는 기능을 추가하면 될 것같습니다. cell증식 알고리즘을 좀 알면 재밌는 게임이 될 수 있겠네요 ^^ 


Game of Life에 대한 포스팅은 이것으로 마칩니다.

반응형

댓글

Designed by JB FACTORY