[C++] cocos2d-x를 활용한 드래곤 플라이트 게임 만들기 (1)
2021. 5. 21. 05:44

안녕하세요. 라이트코드(Light Code) 입니다.

 

이번에는 C++을 공부하시면서 머리를 식히면서 재미있는 게임을 만들어보시라고 cocos2d-x 라는 오픈 소스 2D 게임엔진으로 간단한 게임을 만들 수 있는 방법을 소개할 예정입니다.

이 엔진은 기본적으로 Windows, macOS, Linux, Android, iOS 등 다양한 플랫폼을 지원하고 있으며, 이 cocos2d-x를 기반으로 만든 게임들은 흔히 알려진 AFK 아레나, 쿠키런, 모두의마블 등 유명한 게임들이 있습니다.

 

지금부터는 cocos2d.h 파일을 include해서 게임을 만들어보겠습니다.

1탄에서는 간략하게 조작키 방식으로 버튼을 누르면 캐릭터를 조작할 수 있게 만들어보고, 2~3탄에서부터는 본격적으로 한단계씩 게임의 완성도를 높이는 방향으로 구성하겠습니다.

 

먼저 각종 변수들을 선언할 헤더파일과 게임의 기능적인 부분을 담당하게 될 cpp파일을 만들어서 게임을 간단하게 만들어보겠습니다. 각 헤더파일과 cpp파일에서의 변수와 돌아가는 기능적인 함수 부분에 대해서는 밑 소스코드 내에서 설명되어있으니 참고 바랍니다.

(cocos2d-x가 설치 안되신분들은 [바로가기] 클릭하여 설치하시고 밑에 소스파일을 참고하시길 바랍니다)

 


<ProjectOneScene.h>

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

enum Items //enum 과 setTag 로 매칭(setTag 로 알아보기 쉽게 문자열로 간편화)
{
    MOVE, ROTATE, COME, JUMP, BLANK, QUIT, };
class ProjectOne:public cocos2d::Scene {
    private: cocos2d::Sprite* dragon; // 스프라이트 고정변수
    public: static cocos2d::Scene* createScene();
    virtual bool init();
    void menuStartCallback(cocos2d::Ref* pSender);
    CREATE_FUNC(ProjectOne);
};
#endif// __HELLOWORLD_SCENE_H__

<ProjectOneScene.cpp>

bool ProjectOne::init()
{
    
if (!Scene::init())
{
return false;
}

auto layer = Layer::create();
Size winSize = Director::getInstance()->getVisibleSize();
this->addChild(layer);
auto mainImage = Sprite::create("images/background.png"); //이미지 파일을 바로
붙히는 방법은 없어서 스프라이트로 렌더링 → 배경화면 설정
mainImage->setAnchorPoint(Vec2(0, 0));
mainImage->setPosition(0, 0);
layer->addChild(mainImage);
auto menu_1 = Label::createWithSystemFont("MOVE UP RIGHT", "Cooper Std
Black", 21);
auto menu_2 = Label::createWithSystemFont("ROTATE", "Cooper Std Black", 21);
auto menu_3 = Label::createWithSystemFont("COME AND GO", "Cooper Std Black",
21);
auto menu_4 = Label::createWithSystemFont("JUMP", "Cooper Std Black", 21);
auto menu_5 = Label::createWithSystemFont("BLANK", "Cooper Std Black", 21);
auto menu_6 = Label::createWithSystemFont("QUIT", "Cooper Std Black", 21);
menu_1->setColor(Color3B(245, 27, 0));
menu_2->setColor(Color3B(245, 27, 0));
menu_3->setColor(Color3B(245, 27, 0));
menu_4->setColor(Color3B(245, 27, 0));
menu_5->setColor(Color3B(245, 27, 0));
menu_6->setColor(Color3B(0, 20, 255));

auto MOVE = MenuItemLabel::create(menu_1,
CC_CALLBACK_1(ProjectOne::menuStartCallback, this));
MOVE->setTag(Items::MOVE);
auto ROTATE = MenuItemLabel::create(menu_2,
CC_CALLBACK_1(ProjectOne::menuStartCallback, this));
ROTATE->setTag(Items::ROTATE);
auto COME = MenuItemLabel::create(menu_3,
CC_CALLBACK_1(ProjectOne::menuStartCallback, this));
COME->setTag(Items::COME);
auto JUMP = MenuItemLabel::create(menu_4,
CC_CALLBACK_1(ProjectOne::menuStartCallback, this));
JUMP->setTag(Items::JUMP);
auto BLANK = MenuItemLabel::create(menu_5,
CC_CALLBACK_1(ProjectOne::menuStartCallback, this));
BLANK->setTag(Items::BLANK);
auto QUIT = MenuItemLabel::create(menu_6,
CC_CALLBACK_1(ProjectOne::menuStartCallback, this));
QUIT->setTag(Items::QUIT);

auto menu = Menu::create(MOVE, ROTATE, COME, JUMP, BLANK, QUIT, NULL);
menu->alignItemsVerticallyWithPadding(15);
menu->setPosition(110, 765);
layer->addChild(menu, 1);
dragon = Sprite::create("images/dragon.png"); //각종 액션을 표현할 대상 →
스프라이트 객체
dragon->setScale(1.7f);
dragon->setPosition(300, 150);
layer->addChild(dragon,1);
return true;
}

void ProjectOne::menuStartCallback(Ref* pSender) //전체액션함수
{
ActionInterval* result;
auto backup = Place::create(Vec2(300, 150));
auto delay = DelayTime::create(1.5);
auto left = MoveBy::create(2, Vec2(-240, 0));
dragon->stopAllActions();
dragon->setPosition(300, 150);
dragon->setScale(1.7f);
dragon->setRotation(0);
dragon->setColor(Color3B::WHITE);
dragon->setVisible(true);
switch (((Node*)pSender)->getTag())
{
    
case Items::MOVE: //곡선 이동액션
{
ccBezierConfig bezierConfig;
bezierConfig.controlPoint_1 = Vec2(350, 650);
bezierConfig.controlPoint_2 = Vec2(450, 750);
bezierConfig.endPosition = Vec2(520, 850);
auto action = BezierTo::create(3.0, bezierConfig);
result = Sequence::create(action, delay->clone(), backup->clone(),
nullptr);
dragon->runAction(result);
break;
}

case Items::ROTATE: //회전하면서 작아지는 액션
{
auto spin = RotateBy::create(3.0f, 1080);
auto size = ScaleTo::create(3.0, 0.1f);
auto start = ScaleTo::create(0, 1.7f);
auto total = Spawn::create(spin, size, nullptr);
result = Sequence::create(total, delay->clone(), start, backup->clone(), nullptr);
dragon->runAction(result);
break;
}

case Items::COME: //3 번 왕복 액션
{
auto right = MoveBy::create(1.0, Vec2(480, 0));
auto round = MoveBy::create(1.0, Vec2(-480, 0));
auto repeat = round->reverse();
auto req = Sequence::create(round, repeat, nullptr);
auto myReq = Repeat::create(req, 2);
result = Sequence::create(left, right, myReq, backup->clone(), nullptr);
dragon->runAction(result);
break;
}

case Items::JUMP: //왼쪽 이동 -> 20 번점프하는 액션
{
Vector<FiniteTimeAction*> actions;
for (int i = 0; i < 20; i++) {
auto avg = JumpBy::create(1.0 - i*0.05, Vec2(22, 0), 550 - i *
15, 1);
actions.pushBack(avg);
}
auto total = Sequence::create(actions);
result = Sequence::create(left->clone(), total, delay->clone(),
backup->clone(), nullptr);
dragon->runAction(result);
break;
}

case Items::BLANK: //빨간색 변하고 깜빡하는 액션
{
auto setColor = TintTo::create(0, Color3B::WHITE);
auto getColor = TintTo::create(0, 204, 0, 0);
auto blink = Blink::create(3, 10);
auto size = ScaleBy::create(0.5, 2.0f);
auto reset = size->reverse();
auto avg = Sequence::create(size, reset, nullptr);
auto myAvg = Repeat::create(avg, 3);
auto myAction = Spawn::create(getColor, blink, myAvg, nullptr);
result = Sequence::create(myAction, delay->clone(), setColor,
backup->clone(), nullptr);
dragon->runAction(result);
break;
}

case Items::QUIT: //프로그램 종료
{
Director::getInstance()->end();
}
}
}

<코드실행 데모영상>

 

 

BELATED ARTICLES

more