Flappy Bird는 터치할때마다 새가 점프하여 장애물에 박지않고 멀리 가는 게임이다.

(https://namu.wiki/w/Flappy%20Bird?from=%ED%94%8C%EB%9E%98%ED%94%BC%20%EB%B2%84%EB%93%9C)


이때까지 만들었던 기본요소들로 플래피 버드를 만들어보았다.

우선 해상도는 1280 * 720이다.



Scene에서는 게임이 진행될 GameLayer와 배경화면을 나타낼 BgLayer를 자식으로 넣어주었다.

1
2
3
4
5
6
7
8
9
10
bool GameScene::init()
{
    GameLayer* pLayer = GameLayer::create();
    addChild(pLayer, 1"player");
 
    BgLayer* bgLayer1 = BgLayer::create();
    addChild(bgLayer1, 0"bg");
 
    return true;
}
cs



BgLayer는 아래와 같다.

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
bool BgLayer::init()
{
    // 같은 이미지를 2개 생성
    Sprite* pSprite1 = Sprite::create("res/background.png");
    Sprite* pSprite2 = Sprite::create("res/background.png");
 
    addChild(pSprite1, 0100);
    addChild(pSprite2, 0200);
 
    pSprite1->setPosition(640384);
    pSprite2->setPosition(1920384);
 
    scheduleUpdate();
    return true;
}
 
void BgLayer::update(float dt)
{
    Sprite* pSprite1 = (Sprite*)getChildByTag(100);
    Sprite* pSprite2 = (Sprite*)getChildByTag(200);
 
    // 첫 이미지가 화면에서 사라지면 2번째 이미지 뒤로 붙여줌
    if (pSprite1->getPositionX() <= -640)
        pSprite1->setPositionX(pSprite2->getPositionX()+1280);
    else if (pSprite2->getPositionX() <= -640)
        pSprite2->setPositionX(pSprite1->getPositionX()+1280);
 
    // 부모(씬)의 자식 중 Player(GameLayer)를 찾아줌
    auto gl = (GameLayer*)getParent()->getChildByName("player");
 
    // 캐릭터가 죽지않으면 배경화면을 계속 
    if (!gl->getdeath())
    {
        pSprite1->setPositionX(pSprite1->getPositionX() - 200.0f * dt);
        pSprite2->setPositionX(pSprite2->getPositionX() - 200.0f * dt);
    }
}
cs

init()에서 똑같은 배경화면을 2개 생성한 후 이어지게 붙여

배경화면이 왼쪽으로 계속 이동하면서 화면에서 벗어나면 뒤에 붙여주는 식으로 반복하는 것이다.



GameLayer는 아래와 같다.

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
#pragma once
#include <cocos2d.h>
USING_NS_CC;
 
class GameLayer : public Layer
{
private:
    float jump;
    int jumpcount;
    int score;
    int death;
    int start;
    int hiscore;
 
    float t;
public:
    GameLayer();
    ~GameLayer();
 
    bool init();
    virtual bool onTouchBegan(Touch *touch, Event *unused_event);
    virtual void onTouchMoved(Touch *touch, Event *unused_event);
    virtual void onTouchEnded(Touch *touch, Event *unused_event);
    virtual void onTouchCancelled(Touch *touch, Event *unused_event);
 
    void update(float dt);
    void scoreup();
    void hstop();
    void enablestart();
    void sethuddleerase();
    int getdeath();
    int getscore();
    CREATE_FUNC(GameLayer);
};
cs


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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "GameLayer.h"
#include "Huddle.h"
#include "PrintNum.h"
#include "PrintAlpha.h"
#include "menu.h"
#include "json/json.h"
 
// 태그번호 : 캐릭터(105) / 알파벳(601) / 점수(552) / 스타트메뉴(1000) / 노드(700)
 
GameLayer::GameLayer()
{
    jump = 0;                    // 점프를 하기위해 y값을 조정해주기 위한 수치
    t = 0;                        // 1초마다 장애물을 찍어주기 위해 시간을 저장할 변수
    jumpcount = 0;                // 점프횟수 제한을 하기위해 (지금은 해제하여 사용하지않는중)
    score = 0;                    // 점수를 저장할 변수
    death = 0;                    // 죽었는지 확인하는 변수. 1이면 죽음
    start = 0;                    // 시작을 확인하는 변수. 1이면 시작
    hiscore = 0;                // 하이스코어값을 저장하는 변수
}
 
 
GameLayer::~GameLayer()
{
}
 
bool GameLayer::init()
{
    Sprite* pSprite = Sprite::create("res/c1.png");
    pSprite->setPosition(200150);
    pSprite->setScale(0.15f);
    addChild(pSprite,1,105);
 
    // 터치리스너 등록
    auto listener = EventListenerTouchOneByOne::create(); 
    listener->setSwallowTouches(true);
 
    listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
 
    // SCORE 글자를 이미지로 출력
    auto pScore1 = PrintAlpha::create();
    pScore1->print("SCORE");
    addChild(pScore1, 2601);
    
    // SCORE 실제 점수를 표시(초기값 0)
    auto pNum1 = PrintNum::create();
    addChild(pNum1, 2552);
    pNum1->print(0);
 
    // 스타트 메뉴 표시
    auto MenuStart = menu::create();
    addChild(MenuStart, 51000);
    MenuStart->printstart();
 
    // 허들을 동시에 삭제하기 위해 노드의 자식으로 관리하려고 만듬
    Node* pNode = Node::create();
    addChild(pNode, 0700);
 
    // HISCORE 글자 출력
    auto pHiScore = PrintAlpha::create();
    pHiScore->print2("HISCORE");
    addChild(pHiScore, 2602);
 
    // json에서 highscore 읽어와서 변수에넣기
    Json::Value root;
    Data data;
 
    char path[256= {};
    GetCurrentDirectoryA(256, path);
    std::string fileName = path;
    fileName += "/data.json";
 
    data = FileUtils::getInstance()->getDataFromFile(fileName);
    char* pBuffer = (char*)data.getBytes();
    std::string strJson = pBuffer;
    Json::Reader reader;
    reader.parse(strJson.c_str(), root);
    hiscore = root["highscore"].asInt();
 
    // 읽어온 highscore를 이미지로  출력
    auto pHiScore2 = PrintNum::create();
    addChild(pHiScore2, 2553);
    //pHiScore2->print2(0);
    pHiScore2->print2(hiscore);
 
 
    scheduleUpdate();
    return true;
}
 
bool GameLayer::onTouchBegan(Touch * touch, Event * unused_event)
    jump = 650.0f;
 
    return true;
}
 
void GameLayer::update(float dt)
{
    if (start)
    {
        Sprite* pSprite = (Sprite*)getChildByTag(105);
        if (pSprite)
        {
            // 중력이 -400.0f만큼 작용하여 계속 떨어짐
            pSprite->setPositionY(pSprite->getPositionY() + (jump - 400.0f) * dt);
 
            // 캐릭터가 바닥에 떨어지지않게 가상의 바닥을 깔아줌(삭제할것. 테스트위해)
            if (pSprite->getPositionY() < 150)
            {
                pSprite->setPositionY(150.0f);
                //jumpcount = 0;
            }
        }
 
        // 점프값이 점점 줄어들게
        if (jump != 0)
            jump -= 400.0f * dt;
        else
            jump = 0;
 
 
        t += dt;
        // 1초마다 허들생성
        if (t >= 1)
        {
            // 허들을 노드의 자식으로 넣어줌
            auto pNode = getChildByTag(700);
            Huddle* newHuddle = Huddle::create();
            pNode->addChild(newHuddle, 0);
            t -= 1;
        }
    }
}
 
// 점수를 올리는 함수
void GameLayer::scoreup()
{
    score += 521;
    auto pNum = (PrintNum*)getChildByTag(552);        
    pNum->print(score);
}
 
// 게임을 멈추는 함수
void GameLayer::hstop()
{
    death = 1;
    start = 0;
 
    // 리스타트 메뉴를 출력
    auto MenuRestart = menu::create();
    addChild(MenuRestart, 51001);
    MenuRestart->printrestart();
 
    // 하이스코어 검사, 저장
    if (score > hiscore)
        hiscore = score;
    auto pNum = (PrintNum*)getChildByTag(553);
    pNum->print2(hiscore);
 
    Json::Value root;
    root["highscore"= hiscore;
 
    Json::StyledWriter sw;
    std::string jsonString = sw.write(root);
    FILE* pFile = NULL;
    std::string fileName = "";
 
    // 파일이름이 최대길이가 256자라서 최대로 만듬
    char path[256= {};
    // 현재 디렉토리 주소를 가져옴 (path)
    GetCurrentDirectoryA(256, path);
    fileName = path;
    fileName += "/data.json";
 
    fopen_s(&pFile, fileName.c_str(), "wt");
    fwrite(jsonString.c_str(), jsonString.length(), 1, pFile);
    fclose(pFile);
}
 
// 시작을 세팅
void GameLayer::enablestart()
{
    start = 1;
    death = 0;
    score = 0;
 
    // 스코어 출력
    auto pNum = (PrintNum*)getChildByTag(552);
    pNum->print(score);
    // 캐릭터 보이게함
    auto pHero = (Sprite*)getChildByTag(105);
    pHero->setVisible(true);
}
 
// 허들 삭제하는 함수
void GameLayer::sethuddleerase()
{
    // 노드를 찾아 자식을 전부 삭제
    auto pNode = getChildByTag(700);
    pNode->removeAllChildren();
}
 
int GameLayer::getdeath()
{
    return death;
}
 
int GameLayer::getscore()
{
    return score;
}
 
 
cs

GameLayer에는 많은 부분들이 들어가서 설명이 부족한 부분만 다음글에서 설명하겠음.

'프로그래밍 공부 > cocos2d-x' 카테고리의 다른 글

라벨, 메뉴 사용하기  (0) 2018.03.28
Flappy Bird 게임 만들기 - 2  (0) 2018.03.27
충돌체크하기  (0) 2018.03.27
터치, 마우스, 키보드 사용하기  (0) 2018.03.27
오브젝트 삭제하기  (0) 2018.03.26
Posted by misty_
,