VioletaBabel
12일 : 플래피 버드 완성하기 본문
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 | //BackGround.cpp #include "BackGround.h" BackGround::BackGround() { } BackGround::~BackGround() { } bool BackGround::init() { Sprite* pSky1 = Sprite::create("res/sky.png"); Sprite* pSky2 = Sprite::create("res/sky.png"); // 하늘 배경 두 개 생성 addChild(pSky1, 0, 1); addChild(pSky2, 0, 2); // 각자 1, 2라는 태그를 주었다. pSky1->setPosition(0, 360); pSky2->setPosition(Back_X_Size, 360); scheduleUpdate(); return true; } void BackGround::update(float dt) { if (getParent()->getChildByName("Layer")->getChildByTag(0)) { // 플레이어가 살아 있는 경우에만 이동 Node* pSky[2]; for (int i = 0; i < 2; ++i) pSky[i] = getChildByTag(i + 1); for (int i = 1; i > -1; --i) { pSky[i]->setPositionX(pSky[i]->getPositionX() - 500.0f * dt); // 평소엔 그냥 왼쪽 이동 if (pSky[i]->getPositionX() < Back_X_Size / (-2)) // 음수로 해상도의 절반 값으로 갈 경우 이동시킨다. pSky[i]->setPositionX(pSky[i]->getPositionX() + (Back_X_Size * 2)); // 딱 맞아 떨어질 해당 위치로! } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //Hurdle.h #pragma once #include <cocos2d.h> USING_NS_CC; class Hurdle : public Node { public: const int Back_X_Size = 1280; Hurdle(); ~Hurdle(); bool init(); void update(float dt); CREATE_FUNC(Hurdle); bool p = 1; }; | 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 | //Hurdle.cpp #include "Hurdle.h" #include "GameLayer.h" Hurdle::Hurdle() { } Hurdle::~Hurdle() { } bool Hurdle::init() { int term = 360, down = rand() % 540 - 435, up = down + term + 675; Sprite *pHd1 = Sprite::create("res/hurdle.png"); Sprite *pHd2 = Sprite::create("res/hurdle.png"); addChild(pHd1, 0, "UP"); addChild(pHd2, 0, "DOWN"); pHd1->setPosition(0, up); // 스프라이트의 X좌표가 허들의 원점에 오도록 수정하자. pHd2->setPosition(0, down); setPositionX(1312); // 허들을 통째로 옮겨준다.(1280+32) 이러면 무브가 필요가 없다!! scheduleUpdate(); return true; } void Hurdle::update(float dt) { auto pPlayer = getParent()->getChildByTag(0); // 주인공 객체를 부모(게임레이어)부터 얻어옴 auto pScore = (GameLayer*)getParent(); auto u = getChildByName("UP"); auto d = getChildByName("DOWN"); if (pPlayer && u && d) {//플레이어나 u나 d가 없으면 에러가 나고 튕기는 걸 막음 Rect pRect = pPlayer->getBoundingBox(); // 주인공의 직사각형을 가지고 옴. Rect uRect = u->getBoundingBox(); // 위 장애물 사각형을 가져옴 Rect dRect = d->getBoundingBox(); // 아래 장애물 사각형을 가져옴 uRect.origin += getPosition(); dRect.origin += getPosition(); // 현재 스프라이트는 허들에 속하여 상대좌표를 가지고 있다. 그래서 이렇게 해준다. if (pRect.intersectsRect(uRect) || pRect.intersectsRect(dRect))// 캐릭터가 장애물에 부딪히면 서거한다. pPlayer->removeFromParent(); if (pScore->getChildByTag(0) && p) if (pPlayer->getPositionX() > uRect.origin.x) { // 플레이어가 장애물을 넘어가면 1점 씩 추가 pScore->po++; p = 0; } setPositionX(getPositionX() - 500.0f * dt); // 왼쪽으로 이동 if (getPositionX() < -32) // 화면 밖으로 나가면 삭제 this->removeFromParent(); } else // 플레이어가 죽었다 싶으면 그냥 장애물 다 삭제 this->removeFromParent(); } | 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 | //GameLayer.h #pragma once #include <cocos2d.h> USING_NS_CC; class GameLayer : public Layer { private: int jump; double move; float t; char s[4]; // 점수 출력용 bool gameover = 0; // 게임 오버 판단 int po; public: GameLayer(); ~GameLayer(); bool init(); void poplus(); 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); CREATE_FUNC(GameLayer); void makePlayer(); }; | 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 | //GameLayer.cpp #include "GameLayer.h" #include "Hurdle.h" GameLayer::GameLayer() { jump = 1; t = 0; move = 0; po = 0; srand(time(NULL)); } GameLayer::~GameLayer() { } bool GameLayer::init() { //인터넷에 다운받아 프로젝트 폴더의 Resources 폴더의 res 폴더에 넣은 이미지파일을 스프라이트로 만든다. makePlayer(); //터치를 받으면 연결해주는 것을 만들어야 한다. auto listener = EventListenerTouchOneByOne::create(); // 멀티터치가 아닌 손가락 하나 전용 리스너 생성 listener->setSwallowTouches(true); //그냥 터치하는건 이렇게 생겨먹었으니 이해보다는 이런 식이구나~ 하자 listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan, this); listener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved, this); listener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded, this); listener->onTouchCancelled = CC_CALLBACK_2(GameLayer::onTouchCancelled, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto label = LabelTTF::create("Score : ", "arial", 30); label->setPosition(Point(1100, 690)); label->setColor(Color3B::BLACK); addChild(label, 50, 10); auto score = LabelTTF::create(itoa(po, s, 10), "arial", 30); score->setPosition(Point(1170, 689)); score->setColor(Color3B::BLACK); addChild(score, 50, 11); auto over = LabelTTF::create("", "arial", 100); over->setPosition(Point(640, 360)); over->setColor(Color3B::BLACK); addChild(over, 50, 12); scheduleUpdate(); // 이걸 호출해야지만 update 함수가 계속 불리게 된다. //unscheduleUpdate(); //이 함수를 부르면 update 함수가 더 이상 불리지 않는다. return true; } void GameLayer::poplus() { ++po; } bool GameLayer::onTouchBegan(Touch * touch, Event * unused_event) { if (gameover) { // 게임오버 중에 터치 시 makePlayer(); // 캐릭터 생성 gameover = 0; // 변수들 초기화 po = 0; auto pOver = (LabelTTF*)getChildByTag(12); pOver->setString(""); // 게임오버 문구 가리기 } else jump = -8; return false; } void GameLayer::onTouchMoved(Touch * touch, Event * unused_event) { } void GameLayer::onTouchEnded(Touch * touch, Event * unused_event) { } void GameLayer::onTouchCancelled(Touch * touch, Event * unused_event) { } void GameLayer::update(float dt) { Node* pSprite = getChildByTag(0); // 새로 만든 스프라이트. 위에 만든 0을 그대로 받아온다. if (pSprite) // 이걸 해줌으로써 캐릭터가 죽어서 사라졌을 때 에러가 안나게 한다. { if (pSprite->getPositionY() > 660) move = 250.0f*dt; else move = 250.0f * dt * jump; // 점프와 중력대로 pSprite->setPositionY(pSprite->getPositionY() - move); // 초마다 해당 스프라이트의 Y를 move만큼 이동시킨다. if (jump < 1) // 점프하면 값 변환시켜서 대응 jump += 3; t += dt; if (t >= 2.0f) { // 2초마다 장애물 생성 Hurdle *pHd = Hurdle::create(); addChild(pHd, 15); t -= 2.0f; } auto pScore = (LabelTTF*)getChildByTag(11); pScore->setString(itoa(po, s, 10)); // 점수 갱신 } else { gameover = 1; auto pOver = (LabelTTF*)getChildByTag(12); pOver->setString("Game Over\nContinue is Click"); // 게임오버 출력 } if (pSprite) if (pSprite->getPositionY() < 44) // 바닥으로 떨어지면 뒤진다 pSprite->removeFromParent(); } void GameLayer::makePlayer() { // 주인공 만들어주는 함수 Sprite* pSprite = Sprite::create("res/moomint.png"); addChild(pSprite, 0, 0); // 3번째 인수는 id나 이름을 준다. 이제 얘는 0번 아이디를 가짐 pSprite->setPosition(160, 360); pSprite->setScale(0.5f); } | cs |
============================
글자를 이미지로 교체한 최종 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //GameScene.h #pragma once #include<cocos2d.h> //using namespace cocos2d; USING_NS_CC; // using namespace cocos2d; 를 줄여놓은 것. class GameScene : public Scene //씬을 만들 것이므로 씬을 상속받자. { public: GameScene(); ~GameScene(); bool init(); CREATE_FUNC(GameScene); // 크리에이트펑션이란 매크로. // 이닛 해주고 오토릴리즈 해주는 애라고 함. // 매 프레임마다 검사하며 부모 클래스가 없으면 죽임(메모리를 알아서 관리) }; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //GameScene.cpp #include "GameScene.h" #include "GameLayer.h" #include "BackGround.h" GameScene::GameScene() { } GameScene::~GameScene() { } bool GameScene::init() { GameLayer *pLayer = GameLayer::create(); BackGround *pBack1 = BackGround::create(); addChild(pLayer, 10, "Layer"); // 위에 게임레이어헤더를 부르고 이렇게 함으로써 씬에서도 레이어를 갖다붙일 수 있게 됨. addChild(pBack1, 5, "Back"); // 레이어의 z값을 바꿔 레이어마다의 층을 만들어준다. return true; } | 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 | //GameLayer.h #pragma once #include <cocos2d.h> USING_NS_CC; class GameLayer : public Layer { private: int jump; double move; float t; char s[4]; // 점수 출력용 bool gameover = 0; // 게임 오버 판단 public: GameLayer(); ~GameLayer(); bool init(); void poplus(); int po = 0; 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); CREATE_FUNC(GameLayer); void makePlayer(); }; | 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 | //GameLayer.cpp #include "GameLayer.h" #include "Hurdle.h" #include "ShowScore.h" GameLayer::GameLayer() { jump = 1; t = 0; move = 0; po = 0; srand(time(NULL)); } GameLayer::~GameLayer() { } bool GameLayer::init() { //인터넷에 다운받아 프로젝트 폴더의 Resources 폴더의 res 폴더에 넣은 이미지파일을 스프라이트로 만든다. makePlayer(); //터치를 받으면 연결해주는 것을 만들어야 한다. auto listener = EventListenerTouchOneByOne::create(); // 멀티터치가 아닌 손가락 하나 전용 리스너 생성 listener->setSwallowTouches(true); //그냥 터치하는건 이렇게 생겨먹었으니 이해보다는 이런 식이구나~ 하자 listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan, this); listener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved, this); listener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded, this); listener->onTouchCancelled = CC_CALLBACK_2(GameLayer::onTouchCancelled, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto label = LabelTTF::create("Score : ", "arial", 30); label->setPosition(Point(1100, 690)); label->setColor(Color3B::BLACK); addChild(label, 50, 10); auto over = LabelTTF::create("", "arial", 100); over->setPosition(Point(640, 360)); over->setColor(Color3B::BLACK); addChild(over, 50, 12); ShowScore *pShowSc = ShowScore::create();//스코어 보여주는 아이 만듦 addChild(pShowSc, 60, 90); // 태그 90번 scheduleUpdate(); // 이걸 호출해야지만 update 함수가 계속 불리게 된다. //unscheduleUpdate(); //이 함수를 부르면 update 함수가 더 이상 불리지 않는다. return true; } void GameLayer::poplus() { ++po; } bool GameLayer::onTouchBegan(Touch * touch, Event * unused_event) { if (gameover) { // 게임오버 중에 터치 시 makePlayer(); // 캐릭터 생성 gameover = 0; // 변수들 초기화 po = 0; auto pOver = (LabelTTF*)getChildByTag(12); pOver->setString(""); // 게임오버 문구 가리기 ShowScore* pPrint = (ShowScore*)getChildByTag(90); pPrint->print(); // 스코어의 이미지를 다시 0으로 초기화해줌 } else jump = -8; return false; } void GameLayer::onTouchMoved(Touch * touch, Event * unused_event) { } void GameLayer::onTouchEnded(Touch * touch, Event * unused_event) { } void GameLayer::onTouchCancelled(Touch * touch, Event * unused_event) { } void GameLayer::update(float dt) { Node* pSprite = getChildByTag(0); // 새로 만든 스프라이트. 위에 만든 0을 그대로 받아온다. if (pSprite) // 이걸 해줌으로써 캐릭터가 죽어서 사라졌을 때 에러가 안나게 한다. { if (pSprite->getPositionY() > 660) move = 250.0f*dt; else move = 250.0f * dt * jump; // 점프와 중력대로 pSprite->setPositionY(pSprite->getPositionY() - move); // 초마다 해당 스프라이트의 Y를 move만큼 이동시킨다. if (jump < 1) // 점프하면 값 변환시켜서 대응 jump += 3; t += dt; if (t >= 2.0f) { // 2초마다 장애물 생성 Hurdle *pHd = Hurdle::create(); addChild(pHd, 15); t -= 2.0f; } } else { gameover = 1; auto pOver = (LabelTTF*)getChildByTag(12); pOver->setString("Game Over\nContinue is Click"); // 게임오버 출력 } if (pSprite) if (pSprite->getPositionY() < 44) // 바닥으로 떨어지면 뒤진다 pSprite->removeFromParent(); } void GameLayer::makePlayer() { // 주인공 만들어주는 함수 Sprite* pSprite = Sprite::create("res/moomint.png"); addChild(pSprite, 0, 0); // 3번째 인수는 id나 이름을 준다. 이제 얘는 0번 아이디를 가짐 pSprite->setPosition(160, 360); pSprite->setScale(0.5f); } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //Hurdle.h #pragma once #include <cocos2d.h> USING_NS_CC; class Hurdle : public Node { public: const int Back_X_Size = 1280; Hurdle(); ~Hurdle(); bool init(); void update(float dt); CREATE_FUNC(Hurdle); bool p = 1; }; | 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 | //Hurdle.cpp #include "Hurdle.h" #include "GameLayer.h" #include "ShowScore.h" Hurdle::Hurdle() { } Hurdle::~Hurdle() { } bool Hurdle::init() { int term = 360, down = rand() % 540 - 435, up = down + term + 675; Sprite *pHd1 = Sprite::create("res/hurdle.png"); Sprite *pHd2 = Sprite::create("res/hurdle.png"); addChild(pHd1, 0, "UP"); addChild(pHd2, 0, "DOWN"); pHd1->setPosition(0, up); // 스프라이트의 X좌표가 허들의 원점에 오도록 수정하자. pHd2->setPosition(0, down); setPositionX(1312); // 허들을 통째로 옮겨준다.(1280+32) 이러면 무브가 필요가 없다!! scheduleUpdate(); return true; } void Hurdle::update(float dt) { auto pPlayer = getParent()->getChildByTag(0); // 주인공 객체를 부모(게임레이어)부터 얻어옴 auto pScore = (GameLayer*)getParent(); auto pShowScore = (ShowScore*)(pScore->getChildByTag(90)); auto u = getChildByName("UP"); auto d = getChildByName("DOWN"); if (pPlayer && u && d) {//플레이어나 u나 d가 없으면 에러가 나고 튕기는 걸 막음 Rect pRect = pPlayer->getBoundingBox(); // 주인공의 직사각형을 가지고 옴. Rect uRect = u->getBoundingBox(); // 위 장애물 사각형을 가져옴 Rect dRect = d->getBoundingBox(); // 아래 장애물 사각형을 가져옴 uRect.origin += getPosition(); dRect.origin += getPosition(); // 현재 스프라이트는 허들에 속하여 상대좌표를 가지고 있다. 그래서 이렇게 해준다. if (pRect.intersectsRect(uRect) || pRect.intersectsRect(dRect))// 캐릭터가 장애물에 부딪히면 서거한다. pPlayer->removeFromParent(); if (pScore->getChildByTag(0) && p) if (pPlayer->getPositionX() > uRect.origin.x) { // 플레이어가 장애물을 넘어가면 1점 씩 추가 pScore->poplus();//po에 1씩 추가 pShowScore->print();//쇼스코어의 프린트를 불러줌 p = 0; } setPositionX(getPositionX() - 500.0f * dt); // 왼쪽으로 이동 if (getPositionX() < -32) // 화면 밖으로 나가면 삭제 this->removeFromParent(); } else // 플레이어가 죽었다 싶으면 그냥 장애물 다 삭제 this->removeFromParent(); } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //BackGround.h #pragma once #include <cocos2d.h> USING_NS_CC; class BackGround : public Layer { public: const int Back_X_Size = 1280; BackGround(); ~BackGround(); bool init(); void update(float dt); CREATE_FUNC(BackGround); }; | 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 | //BackGround.cpp #include "BackGround.h" BackGround::BackGround() { } BackGround::~BackGround() { } bool BackGround::init() { Sprite* pSky1 = Sprite::create("res/sky.png"); Sprite* pSky2 = Sprite::create("res/sky.png"); // 하늘 배경 두 개 생성 addChild(pSky1, 0, 1); addChild(pSky2, 0, 2); // 각자 1, 2라는 태그를 주었다. pSky1->setPosition(0, 360); pSky2->setPosition(Back_X_Size, 360); scheduleUpdate(); return true; } void BackGround::update(float dt) { if (getParent()->getChildByName("Layer")->getChildByTag(0)) { // 플레이어가 살아 있는 경우에만 이동 Node* pSky[2]; for (int i = 0; i < 2; ++i) pSky[i] = getChildByTag(i + 1); for (int i = 1; i > -1; --i) { pSky[i]->setPositionX(pSky[i]->getPositionX() - 500.0f * dt); // 평소엔 그냥 왼쪽 이동 if (pSky[i]->getPositionX() < Back_X_Size / (-2)) // 음수로 해상도의 절반 값으로 갈 경우 이동시킨다. pSky[i]->setPositionX(pSky[i]->getPositionX() + (Back_X_Size * 2)); // 딱 맞아 떨어질 해당 위치로! } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //ShowScore.h #pragma once #include <cocos2d.h> USING_NS_CC; class ShowScore : public Node { public: ShowScore(); ~ShowScore(); bool init(); void update(float dt); CREATE_FUNC(ShowScore); void print(); char s[10] = "res/0.png"; }; | 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 | //ShowScore.cpp #include "ShowScore.h" #include "GameLayer.h" using namespace std; ShowScore::ShowScore() { } ShowScore::~ShowScore() { } bool ShowScore::init() { Sprite *pScore[3]; for (int i = 0; i < 3; ++i) { // 처음은 000으로 고정 pScore[i] = Sprite::create("res/0.png"); addChild(pScore[i], 60, i); pScore[i]->setPosition(1170 + (i * 16), 689); } return true; } void ShowScore::update(float dt) { } void ShowScore::print() { auto play = (GameLayer*)getParent(); Node *pScore[3]; int num[3]; for (int i = 0, ten = 100, copy = play->po; i < 3; ++i, ten /= 10) { // 점수의 각 자리 수 구함 num[i] = copy / ten; copy %= ten; } for (int i = 0; i < 3; ++i) { pScore[i] = getChildByTag(i); pScore[i]->removeFromParent(); // 기존 점수 삭제 s[4] = (char)(num[i] + 48); // 주소에서 이미지 이름이 숫자 하나만 달라져서.. pScore[i] = Sprite::create(s); // 다시 점수 이미지 만듦 addChild(pScore[i], 60, i); // 다시 태그 맥임 pScore[i]->setPosition(1170 + (i * 16), 689); // 다시 위치를 잡아줘야함 다시 만든거니까.. } } | cs |
'BCA > 2. Cocos2d-x' 카테고리의 다른 글
15일 : 파일 입출력, 오디오, 러닝게임 완성 (0) | 2018.02.28 |
---|---|
14일 : 애니메이션 (0) | 2018.02.27 |
13일 : 복습 겸 아주 자잘한 팁 (0) | 2018.02.26 |
11일 : 터치, 업데이트, 배경, 장애물 등장 (0) | 2018.02.22 |
10일 : cocos2d-x 입문 (0) | 2018.02.21 |
Comments