COCOS2D-X 블럭 파괴 게임 완성 코드

마스터피스·2024년 6월 13일
0

COCOS2D-X

목록 보기
11/11
post-thumbnail

클래스들 :

https://workupload.com/file/qVsEwCD9wn9

배경음악 소스파일 :

https://workupload.com/file/DmVnedRhKZ7

리소스 파일 :

https://workupload.com/file/SAhBBRCfAVJ

완성 파일 :
https://workupload.com/file/dxwVDNjmYUh

상세 코드 )

cpp 파일

  1. AppDelegate
/****************************************************************************
 Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
 
 http://www.cocos2d-x.org
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/
#include "stdafx.h"
#include "AppDelegate.h"
#include "HelloWorldScene.h"
#include "SceneIngame.h"
#include "SceneHome.h"


// #define USE_AUDIO_ENGINE 1

#if USE_AUDIO_ENGINE
#include "audio/include/AudioEngine.h"
using namespace cocos2d::experimental;
#endif

USING_NS_CC;

static cocos2d::Size designResolutionSize = cocos2d::Size(720, 1280);
static cocos2d::Size smallResolutionSize = cocos2d::Size(720, 1280);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(720, 1280);
static cocos2d::Size largeResolutionSize = cocos2d::Size(720, 1280);

AppDelegate::AppDelegate()
{
}

AppDelegate::~AppDelegate() 
{
#if USE_AUDIO_ENGINE
    AudioEngine::end();
#endif
}

// if you want a different context, modify the value of glContextAttrs
// it will affect all platforms
void AppDelegate::initGLContextAttrs()
{
    // set OpenGL context attributes: red,green,blue,alpha,depth,stencil,multisamplesCount
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8, 0};

    GLView::setGLContextAttrs(glContextAttrs);
}

// if you want to use the package manager to install more packages,  
// don't modify or remove this function
static int register_all_packages()
{
    return 0; //flag for packages manager
}

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
        glview = GLViewImpl::createWithRect("GameProject", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
        glview = GLViewImpl::create("GameProject");
#endif
        director->setOpenGLView(glview);
    }

    // turn on display FPS
    //director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0f / 60);

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::SHOW_ALL);
    auto frameSize = glview->getFrameSize();
    // if the frame's height is larger than the height of medium size.
    if (frameSize.height > mediumResolutionSize.height)
    {        
        director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
    }
    // if the frame's height is larger than the height of small size.
    else if (frameSize.height > smallResolutionSize.height)
    {        
        director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
    }
    // if the frame's height is smaller than the height of medium size.
    else
    {        
        director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
    }

    register_all_packages();

    // create a scene. it's an autorelease object
    //auto scene = HelloWorld::createScene();
    //auto scene = SceneIngame::create();
    auto scene = SceneHome::create();

    director->getOpenGLView()->setFrameZoomFactor(0.8);

    // run
    director->runWithScene(scene);

    return true;
}

// This function will be called when the app is inactive. Note, when receiving a phone call it is invoked.
void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

#if USE_AUDIO_ENGINE
    AudioEngine::pauseAll();
#endif
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();

#if USE_AUDIO_ENGINE
    AudioEngine::resumeAll();
#endif
}
  1. Environment.cpp
#include "stdafx.h"
#include "Environment.h"

Global* instance = nullptr;

Global* Global::getInstance(){
	if (instance == nullptr) instance = new Global();
	return instance;
}

void Global::setScore(long long value){
	this->score = value;

}

long long Global::getScore(){
	return score;
}

void Global::addScore(long long value){
	this->score += value;
}

void Global::playPop(){
	AudioEngine::play2d("res/pop.mp3");
}

void Global::playBackgroundMusic(){
	// 음악 Id를 지정해줘서 컨트롤 할수 있게해줌 True 는 반복 루프.
	this->BackgroundMusicId = AudioEngine::play2d("res/River Meditation.mp3", true , 0.5);
}

void Global::stopBackgroundMusic(){
	if (BackgroundMusicId == -1) return;
	AudioEngine::stop(this->BackgroundMusicId);
}

void Global::Breakblock(){
	AudioEngine::play2d("res/pop2.mp3");
}
  1. HelloWorldScene.cpp
/****************************************************************************
 Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
 
 http://www.cocos2d-x.org
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/
#include "stdafx.h"
#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    return HelloWorld::create();
}

// Print useful error message instead of segfaulting when files are not there.
static void problemLoading(const char* filename)
{
    printf("Error while loading: %s\n", filename);
    printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Scene::init() )
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

    if (closeItem == nullptr ||
        closeItem->getContentSize().width <= 0 ||
        closeItem->getContentSize().height <= 0)
    {
        problemLoading("'CloseNormal.png' and 'CloseSelected.png'");
    }
    else
    {
        float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2;
        float y = origin.y + closeItem->getContentSize().height/2;
        closeItem->setPosition(Vec2(x,y));
    }

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label

    auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
    if (label == nullptr)
    {
        problemLoading("'fonts/Marker Felt.ttf'");
    }
    else
    {
        // position the label on the center of the screen
        label->setPosition(Vec2(origin.x + visibleSize.width/2,
                                origin.y + visibleSize.height - label->getContentSize().height));

        // add the label as a child to this layer
        this->addChild(label, 1);
    }

    // add "HelloWorld" splash screen"
    auto sprite = Sprite::create("HelloWorld.png");
    if (sprite == nullptr)
    {
        problemLoading("'HelloWorld.png'");
    }
    else
    {
        // position the sprite on the center of the screen
        sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

        // add the sprite as a child to this layer
        this->addChild(sprite, 0);
    }
    return true;
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
    //Close the cocos2d-x game scene and quit the application
    Director::getInstance()->end();

    /*To navigate back to native iOS screen(if present) without quitting the application  ,do not use Director::getInstance()->end() as given above,instead trigger a custom event created in RootViewController.mm as below*/

    //EventCustom customEndEvent("game_scene_close_event");
    //_eventDispatcher->dispatchEvent(&customEndEvent);


}
  1. LayerIngameUI.cpp
#include "stdafx.h"
#include "LayerIngameUI.h"

LayerIngameUI* LayerIngameUI::create(){
	auto ret = new LayerIngameUI();
	if (ret && ret->init()) ret->autorelease();
	else CC_SAFE_DELETE(ret);
	return ret;
}

bool LayerIngameUI::init(){
	if (!Node::init()) return false;

	addChild(lbScore = Label::createWithTTF("asdf", FONT_NAME, 48.0f));
	lbScore->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);
	lbScore->setPosition(Vec2(30, 1280 - 70));
	

	addChild(btnPause = Button::create("res/btn_pause_normal.png", "res/btn_pause_pressed.png", "res/btn_pause_disabled.png"));
	btnPause->setPosition(Vec2(780 - 70, 1280 - 70));

	const Size PANEL_SIZE(600, 400);
	const float SPACING = 170;
	const float BUTTON_BOTTOM_SAPCING = 100;


	addChild(dnCurtain = DrawNode::create());
	dnCurtain->drawSolidRect(Vec2::ZERO, Vec2(720, 1280), Color4F(0,0,0,0.8));



	//Scale9Sprite 는 가로나 세로로 늘어나도 이미지 그래픽이 깨지지 않게 해준다. 배율을 늘린다.
	addChild(pausePanel = Scale9Sprite::create("res/panel.png"));
	pausePanel->setPosition(Vec2(720 / 2, 1280 / 2));
	// 이미지를 9등분 해서 크기에 맞게 늘려준다.
	pausePanel->setScale9Enabled(true);
	// 가로크기와 세로크기를 지정해서 편리하게 사용가능함.
	pausePanel->setContentSize(Size(600, 400));

	pausePanel->addChild(btnRestart = Button::create("res/btn_restart_normal.png", "res/btn_restart_pressed.png", "res/btn_restart_disabled.png"));
	pausePanel->addChild(btnHome = Button::create("res/btn_home_normal.png", "res/btn_home_pressed.png", "res/btn_home_disabled.png"));
	pausePanel->addChild(btnResume = Button::create("res/btn_play_normal.png", "res/btn_play_pressed.png", "res/btn_play_disabled.png"));

	btnResume->setPosition(Vec2(PANEL_SIZE.width / 2, BUTTON_BOTTOM_SAPCING));
	btnHome->setPosition(Vec2(PANEL_SIZE.width / 2 - SPACING, BUTTON_BOTTOM_SAPCING));
	btnRestart->setPosition(Vec2(PANEL_SIZE.width / 2 + SPACING, BUTTON_BOTTOM_SAPCING));


	Label* lbPaused = Label::createWithTTF("PAUSED!!!", FONT_NAME, 64.0f);
	pausePanel->addChild(lbPaused);
	lbPaused->setColor(Color3B(0, 0, 0));
	lbPaused->setPosition(Vec2(PANEL_SIZE.width / 2, 300));

	setScore(0);
	hidePausePanel();

	return true;
}

void LayerIngameUI::setScore(long long score){
	sprintf(scoreString, "Score : %ld", score);
	lbScore->setString(scoreString);
}

long long LayerIngameUI::getScore(){
	return score;
}

void LayerIngameUI::showPausePanel(){
	pausePanel->setVisible(true);
	dnCurtain->setVisible(true);

	dnCurtain->setOpacity(0);
	dnCurtain->runAction(FadeIn::create(0.125));

	auto pos = pausePanel->getPosition();
	pausePanel->setPosition(pos - Vec2(0, 1000));
	pausePanel->runAction(EaseExponentialInOut::create(MoveTo::create(0.125f, pos)));

}

void LayerIngameUI::hidePausePanel(){
	

	auto pos = pausePanel->getPosition();
	pausePanel->runAction(Sequence::create(
		EaseExponentialOut::create(MoveTo::create(0.25f, pos - Vec2(0, 1000))),
		CallFunc::create([=]() {
			pausePanel->setPosition(pos);
			pausePanel->setVisible(false);
			dnCurtain->setVisible(false);
		
		}),
		nullptr));

}
  1. SceneHome.cpp
#include "stdafx.h"
#include "SceneHome.h"
#include "Environment.h"
#include "SceneIngame.h"

SceneHome* SceneHome::create(){
	auto ret = new SceneHome();
	if (ret && ret->init()) ret->autorelease();
	else CC_SAFE_DELETE(ret);
	return ret;
}

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

	Sprite* img = Sprite::create("res/title_girl.png");
	addChild(img);
	img->setOpacity(0);
	img->runAction(FadeIn::create(0.25));
	img->setPosition(Vec2(720/2, 800));

	Sprite* title = Sprite::create("res/title.png");
	addChild(title);
	title->setPosition(Vec2(720/2, -100));
	title->runAction(EaseSineOut::create(MoveTo::create(0.25f, Vec2(720/2 ,600))));

	addChild(btnStart = Button::create("res/btn_normal.png", "res/btn_pressed.png", "res/btn_disabled.png"));
	addChild(btnQuit = Button::create("res/btn_normal.png", "res/btn_pressed.png", "res/btn_disabled.png"));

	btnStart->setPosition(Vec2(720 / 2, 400));
	btnQuit->setPosition(Vec2(720 / 2, 250));

	btnStart->setTitleFontName(FONT_NAME);
	btnQuit->setTitleFontName(FONT_NAME);

	btnStart->setTitleFontSize(40.0f);
	btnQuit->setTitleFontSize(40.0f);

	btnStart->setTitleColor(Color3B(0,50,50));
	btnQuit->setTitleColor(Color3B(0, 50, 50));

	btnStart->setTitleText("Start Game");
	btnQuit->setTitleText("Quit Game");

	Global::getInstance()->stopBackgroundMusic();


	btnStart->addClickEventListener([=](Ref* r) {
		auto scene = SceneIngame::create();
		auto transit = TransitionSlideInR::create(0.125f, scene);
		Director::getInstance()->replaceScene(transit);
		Global::getInstance()->playPop();
	});

	btnQuit->addClickEventListener([=](Ref* r) {
		Director::getInstance()->end();
		Global::getInstance()->playPop();

	});

	return true;
}
  1. SceneIngame.cpp
#include "stdafx.h"
#include "SceneIngame.h"
#include "SceneHome.h"



void SceneIngame::createBlock(int x, int y, int type) {
    auto cache = Director::getInstance()->getTextureCache();
    //Rect 는 이미지를 자르는 기준은 좌상단이 기준이다.
    // 게임엔진만 좌하단을 기준으로 잡는다.
    auto spr = Sprite::createWithTexture(
        cache->getTextureForKey("res/match3_tiles_px.png"), 
        Rect(0 + (type*40), 0, 40, 40));
    spr->setScale(2);
    addChild(spr);
    setBlockData(x, y, type);
    setBlockSprite(x, y, spr);

}

int SceneIngame::getBlockData(int x, int y) {
    return blockData[y][x];
}

void SceneIngame::setBlockData(int x, int y, int type) {
    blockData[y][x] = type;

}

Sprite* SceneIngame::getBlockSprite(int x, int y) {
    return blockSprite[y][x];
}

void SceneIngame::setBlockSprite(int x, int y, Sprite* s) {
    blockSprite[y][x] = s;
}

void SceneIngame::destroyBlock(int x, int y) {
    if(blockData[y][x] != 0) {
        state = GameState::BLOCK_MOVING;

        blockSprite[y][x]->runAction(Sequence::create(
            FadeOut::create(0.125f),
            FadeIn::create(0.125f),
            FadeOut::create(0.125f),
            FadeIn::create(0.125f),
            FadeOut::create(0.125f),
            Spawn::create(ScaleTo::create(0.125f, 0.0), FadeOut::create(0.125f), nullptr),
            RemoveSelf::create(),
            nullptr));

        blockSprite[y][x] = nullptr;
        blockData[y][x] = 0;

        this->runAction(Sequence::create(
            DelayTime::create(0.625f),
            CallFunc::create([=]() {dropBlocks(x);}),
            nullptr
            ));
    }
}

//좌표변환 중요함.
Vec2 SceneIngame::convertGamecoordToBlockCoord(const Vec2& gameCoord){
    Vec2 blockOrigin = BLOCK_OFFSET 
        - Vec2((BLOCK_HORIZONTAL * BLOCK_WIDTH)/2, (BLOCK_VERTICAL*BLOCK_HEIGHT)/2)
        + Vec2(BLOCK_WIDTH, BLOCK_HEIGHT)/2;
    Vec2 delta = gameCoord - blockOrigin;
    //인티저로 형변환 하면서 반올림하는 게 0.5를 더하는 것이다.
    Vec2 pos = Vec2((int)(delta.x / BLOCK_WIDTH + 0.5), (int)(delta.y / BLOCK_HEIGHT + 0.5));

    return pos;
}

Vec2 SceneIngame::convertBlockcoordToGameCoord(const Vec2& blockCoord){
    Vec2 blockOrigin = BLOCK_OFFSET 
        - Vec2((BLOCK_HORIZONTAL * BLOCK_WIDTH) / 2, (BLOCK_VERTICAL * BLOCK_HEIGHT) / 2) 
        + Vec2(BLOCK_WIDTH, BLOCK_HEIGHT) / 2;

    return blockOrigin + Vec2(BLOCK_WIDTH * blockCoord.x, BLOCK_HEIGHT * blockCoord.y);
    
}


int SceneIngame::findEmptyBlockYIndex(int x, int y){
    for (int i = y; i < BLOCK_VERTICAL;i++) {
        if (getBlockData(x, i) == 0) return i;
    }
    return -1;
}

int SceneIngame::findFilledBlockYIndex(int x, int y){
    for (int i = y;i < BLOCK_VERTICAL; i++) {
        if (getBlockData(x, i) != 0) return i;
    }
    return -1;
}

void SceneIngame::dropBlocks(int x){
    bool isDrop = false; // 최상단 블록이 추가되지 않을 경우에 유효함
    for (int i = 0; i < BLOCK_VERTICAL; i++) {

        int empty_y = findEmptyBlockYIndex(x, i);
        if (empty_y == -1) continue;
        int filled_y = findFilledBlockYIndex(x, empty_y + 1);
        if (filled_y == -1) {
            createBlock(x, empty_y, rand() % BLOCK_VAR + 1);
            blockSprite[empty_y][x]->setPosition(convertBlockcoordToGameCoord(Vec2(x,BLOCK_VERTICAL + 1)));
            blockSprite[empty_y][x]->runAction(MoveTo::create(0.125f, convertBlockcoordToGameCoord(Vec2(x, empty_y))));
            isDrop = true;
            continue;
        }
        {
            int a = getBlockData(x, empty_y);
            int b = getBlockData(x, filled_y);
            SWAP(int, a, b);
            setBlockData(x, empty_y, a);
            setBlockData(x, filled_y, b);
        } {
            Sprite* a = getBlockSprite(x, empty_y);
            Sprite* b = getBlockSprite(x, filled_y);
            SWAP(Sprite*, a, b);
            setBlockSprite(x, empty_y, a);
            setBlockSprite(x, filled_y, b); 

            a->stopAllActions();
            a->runAction(MoveTo::create(0.125f, convertBlockcoordToGameCoord(Vec2(x, empty_y))));

        }
        isDrop = true;

        

    }
    if (isDrop) {
        for (int i = 0; i < BLOCK_VERTICAL; i++) {
            this->runAction(Sequence::create(DelayTime::create(0.1), CallFunc::create([=]() {judgeMatch(x, i);}), nullptr));
        }
    }
    else {
        state = GameState::PLAYING;
    }

    //alignBlockSprite();
    
}

void SceneIngame::stackPush(const Vec2& value){
    if (judgeData[(int)value.y][(int)value.x] != 0) return;
    judgeStack[judgeStackCount++] = value;
    judgeData[(int)value.y][ (int)value.x ] = 1;

}

const Vec2& SceneIngame::stackPop(){
    auto ret = judgeStack[--judgeStackCount];
    judgeData[(int)ret.y][(int)ret.x] = 0;
    return ret;
}

void SceneIngame::stackEmpty(){
    judgeStackCount = 0;
    for (int i = 0; i < BLOCK_HORIZONTAL; i++) {
        for (int k = 0; k < BLOCK_VERTICAL; k++) {
            judgeData[k][i] = 0;
        }
    }

}

bool SceneIngame::stackFind(const Vec2& value){
    return judgeData[(int)value.y][(int)value.x] == 1;

}

void SceneIngame::judgeMatch(int x, int y){
    int blockData = getBlockData(x, y);

    if (blockData == 0) return;

    stackPush(Vec2(x, y));
    int push_cnt = 0;
    for (int i = 0; i < 4; i++) {
        int next_x = x;
        int next_y = y;
        int inc_x;
        int inc_y;

        switch (i) {
        case 0: inc_x = 1; inc_y = 0; push_cnt = 0; break;
        case 1: inc_x = -1; inc_y = 0; break;
        case 2: inc_x = 0; inc_y = 1; push_cnt = 0; break;
        case 3: inc_x = 0; inc_y = -1; break;

        }
        while (true) {
            next_x += inc_x;
            next_y += inc_y;
            if (next_x < 0 || next_x >= BLOCK_HORIZONTAL) break;
            if (next_y < 0 || next_y >= BLOCK_VERTICAL) break;
            if (getBlockData(next_x, next_y) == blockData) {
                stackPush(Vec2(next_x, next_y));
                push_cnt++;
            }
            else break;
        }

        if (i % 2 == 0) continue;
        if (push_cnt < 2) {
            for (int k = 0; k < push_cnt;k++) {
                stackPop();
            }
        }
    }
    if (judgeStackCount > 1) {
        Global::getInstance()->addScore(judgeStackCount * 10);
        ui->setScore(Global::getInstance()->getScore());
        while (judgeStackCount > 0) {
            Vec2 p = stackPop();
            destroyBlock(p.x, p.y);
            Global::getInstance()->Breakblock();

        }
        
    }
    else {
        state = GameState::PLAYING;
    }
    stackEmpty();
}




SceneIngame* SceneIngame::create() {
    auto ret = new SceneIngame();
    if (ret && ret->init()) ret->autorelease();
    else CC_SAFE_DELETE(ret);
    return ret;
}


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

    srand(time(0));

    //Director 은 전체 관리자
    //이미지를 이미지 관리자에서 빼와서 사용 가능
    // 자동으로 이미지를 해주는걸 수동으로 가져와 자르려 한다.
    Director::getInstance()->getTextureCache()->addImage("res/match3_tiles_px.png");

    auto touch = EventListenerTouchOneByOne::create();
    touch->onTouchBegan = std::bind(&SceneIngame::onTouchBegan, this, std::placeholders::_1, std::placeholders::_2);
    touch->onTouchMoved = std::bind(&SceneIngame::onTouchMoved, this, std::placeholders::_1, std::placeholders::_2);
    touch->onTouchEnded = std::bind(&SceneIngame::onTouchEnded, this, std::placeholders::_1, std::placeholders::_2);
    touch->onTouchCancelled = touch->onTouchEnded;

    getEventDispatcher()->addEventListenerWithSceneGraphPriority(touch, this);
    return true;
}


void SceneIngame::onEnter() {
    Scene::onEnter();

    
    this->initUI();
    this->initGame();
    this->startGame();

}




void SceneIngame::initUI() {
    addChild(ui = LayerIngameUI::create());
    ui->setLocalZOrder(1);

    ui->btnPause->addClickEventListener([=](Ref* r) {
        if (state == GameState::PLAYING) {
            ui->showPausePanel();
            state = GameState::PAUSED;
            Global::getInstance()->playPop();
        }
       
    });

    ui->btnResume->addClickEventListener([=](Ref* r) {
        if (state == GameState::PAUSED) {
            ui->hidePausePanel();
            state = GameState::PLAYING;
            Global::getInstance()->playPop();
        }
     });

    ui->btnRestart->addClickEventListener([=](Ref* r) {
        if (state == GameState::PAUSED) {
            ui->hidePausePanel();
            ui->setScore(0);
            this->destroyGame();
            this->initGame();
            this->startGame();
            state = GameState::PLAYING;
            Global::getInstance()->playPop();
        }

     });

    ui->btnHome->addClickEventListener([=](Ref* r) {
        if (state == GameState::PAUSED) {
            auto scene = SceneHome::create();
            auto transit = TransitionSlideInL::create(0.125f, scene);
            Director::getInstance()->replaceScene(transit);
            Global::getInstance()->playPop();
        }

     });
}

void SceneIngame::initGame() {
    Global::getInstance()->setScore(0);
    for (int i = 0; i < BLOCK_HORIZONTAL; i++) {
        for (int k = 0; k < BLOCK_VERTICAL; k++) {
            createBlock(i, k, rand()%BLOCK_VAR + 1);
        }
    }
    this->alignBlockSprite();
}

void SceneIngame::destroyUI() {
}

void SceneIngame::destroyGame() {
    Global::getInstance()->setScore(0);
    for (int i = 0; i < BLOCK_HORIZONTAL; i++) {
        for (int k = 0; k < BLOCK_VERTICAL; k++) {
            setBlockData(i, k, 0);
            getBlockSprite(i, k)->removeFromParent();
            setBlockSprite(i, k, nullptr);
        }
    }
}

void SceneIngame::alignBlockSprite(){
    for (int i = 0; i < BLOCK_HORIZONTAL; i++) {
        for (int k = 0; k < BLOCK_VERTICAL; k++) {
            auto s = getBlockSprite(i, k);
            if (s != nullptr) s->setPosition(convertBlockcoordToGameCoord(Vec2(i, k)));
        }
    }
}


bool SceneIngame::onTouchBegan(Touch* t, Event* e){
    Vec2 p = convertGamecoordToBlockCoord(t->getLocation());

    if (state == GameState::PLAYING) {

        if (p.x >= BLOCK_HORIZONTAL || p.x < 0) return true;
        if (p.y >= BLOCK_VERTICAL || p.y < 0) return true;

        CCLOG("%f, %f", p.x, p.y);
        destroyBlock(p.x, p.y);
        Global::getInstance()->Breakblock();

    }

    return true;
}


void SceneIngame::onTouchMoved(Touch* t, Event* e){
}


void SceneIngame::onTouchEnded(Touch* t, Event* e){
}

void SceneIngame::startGame() {
    Global::getInstance()->playBackgroundMusic();
}

void SceneIngame::pauseGame() {
}

void SceneIngame::winGame() {
}

void SceneIngame::loseGame() {
}


  1. stdafx.cpp
#include "stdafx.h"

해더파일 )

  1. AppDelegate.h
****************************************************************************
 Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
 
 http://www.cocos2d-x.org
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/
#include "stdafx.h"
#include "AppDelegate.h"
#include "HelloWorldScene.h"
#include "SceneIngame.h"
#include "SceneHome.h"


// #define USE_AUDIO_ENGINE 1

#if USE_AUDIO_ENGINE
#include "audio/include/AudioEngine.h"
using namespace cocos2d::experimental;
#endif

USING_NS_CC;

static cocos2d::Size designResolutionSize = cocos2d::Size(720, 1280);
static cocos2d::Size smallResolutionSize = cocos2d::Size(720, 1280);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(720, 1280);
static cocos2d::Size largeResolutionSize = cocos2d::Size(720, 1280);

AppDelegate::AppDelegate()
{
}

AppDelegate::~AppDelegate() 
{
#if USE_AUDIO_ENGINE
    AudioEngine::end();
#endif
}

// if you want a different context, modify the value of glContextAttrs
// it will affect all platforms
void AppDelegate::initGLContextAttrs()
{
    // set OpenGL context attributes: red,green,blue,alpha,depth,stencil,multisamplesCount
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8, 0};

    GLView::setGLContextAttrs(glContextAttrs);
}

// if you want to use the package manager to install more packages,  
// don't modify or remove this function
static int register_all_packages()
{
    return 0; //flag for packages manager
}

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
        glview = GLViewImpl::createWithRect("GameProject", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
        glview = GLViewImpl::create("GameProject");
#endif
        director->setOpenGLView(glview);
    }

    // turn on display FPS
    //director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0f / 60);

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::SHOW_ALL);
    auto frameSize = glview->getFrameSize();
    // if the frame's height is larger than the height of medium size.
    if (frameSize.height > mediumResolutionSize.height)
    {        
        director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
    }
    // if the frame's height is larger than the height of small size.
    else if (frameSize.height > smallResolutionSize.height)
    {        
        director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
    }
    // if the frame's height is smaller than the height of medium size.
    else
    {        
        director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
    }

    register_all_packages();

    // create a scene. it's an autorelease object
    //auto scene = HelloWorld::createScene();
    //auto scene = SceneIngame::create();
    auto scene = SceneHome::create();

    director->getOpenGLView()->setFrameZoomFactor(0.8);

    // run
    director->runWithScene(scene);

    return true;
}

// This function will be called when the app is inactive. Note, when receiving a phone call it is invoked.
void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

#if USE_AUDIO_ENGINE
    AudioEngine::pauseAll();
#endif
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();

#if USE_AUDIO_ENGINE
    AudioEngine::resumeAll();
#endif
}
  1. Environment.h
#ifndef __ENVIRONMENT_H__
#define __ENVIRONMENT_H__

#include "stdafx.h"

enum class GameState {
	PLAYING, PAUSED, WIN, LOSE, BLOCK_MOVING
};


#define BLOCK_HORIZONTAL 7
#define BLOCK_VERTICAL 9
//블록 위치
#define BLOCK_OFFSET Vec2(720/2, 1280/2)
//블록 가로길이
#define BLOCK_WIDTH 80
//블록 세로길이
#define BLOCK_HEIGHT 80

#define BLOCK_VAR 4

#define SWAP(TYPE, A, B){TYPE t = A; A = B; B= t;}



#define FONT_NAME "fonts/SDSamliphopangcheTTFBasic.ttf"

class Global {
private:
	Global() {}
	long long score = 0;
	int BackgroundMusicId = -1;

public:
	static Global* getInstance();

	void setScore(long long value);
	long long getScore();
	void addScore(long long value);

	void playPop();
	void playBackgroundMusic();
	void stopBackgroundMusic();
	void Breakblock();

};

#endif 
  1. HelloWorldScene.cpp
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"


class HelloWorld : public cocos2d::Scene
{
public:
    static cocos2d::Scene* createScene();

    virtual bool init();
    
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__
  1. LayerIngameUI.h
#ifndef __LAYER_INGAME_UI_H__
#define __LAYER_INGAME_UI_H__

#include "stdafx.h"
#include "Environment.h"

class LayerIngameUI : public Node{
private:
	long long score;
	char scoreString[128];

public:

	// 화면에 스코어 출력
	Label* lbScore;
	// 일시정지버튼
	Button* btnPause;
	// pause 버튼을 눌렀을때 나오는 배경
	Scale9Sprite* pausePanel;
	// 일시정지 해제
	Button* btnResume;
	// 재시작
	Button* btnRestart;
	// 메인화면으로 가기
	Button* btnHome;
	// 화면 뒷배경 흐릿하게 만들기
	DrawNode* dnCurtain;



	static LayerIngameUI* create();
	virtual bool init() override;

	void setScore(long long score);
	long long getScore();


	void showPausePanel();
	void hidePausePanel();

};

#endif
  1. SceneHome.h
#ifndef __SCENE_HOME_H__
#define __SCENE_HOME_H__

#include "stdafx.h"

class SceneHome : public Scene {
public:
	Button* btnStart;
	Button* btnQuit;

	static SceneHome* create();
	virtual bool init() override;
};

#endif // !__SCENE_HOME_H__
  1. SceneIngame.h
#ifndef __SCENE_INGAME_H__
#define __SCENE_INGAME_H__

#include "stdafx.h"
#include "Environment.h"
#include "LayerIngameUI.h"

class SceneIngame : public Scene {
private:
	GameState state;
	// blockData는 0 값일 경우 비어있는 블록, 0이 아닐 양수값일 경우 블록
	int blockData[BLOCK_VERTICAL][BLOCK_HORIZONTAL];
	
	// blockSprite는 nullptr일 경우 비어있음,
	Sprite* blockSprite[BLOCK_VERTICAL][BLOCK_HORIZONTAL];

	// 유니크 스택을 위한 자료구조
	Vec2 judgeStack[128];
	// 스택에 있는 자료의 수
	int judgeStackCount = 0;
	// 0 이라면 스택에 자료가 없음, 그게 아니라면 자료가 있음.
	int judgeData[BLOCK_VERTICAL][BLOCK_HORIZONTAL];

	void createBlock(int x, int y, int type);
	int getBlockData(int x, int y);
	void setBlockData(int x, int y, int type);
	Sprite* getBlockSprite(int x, int y);
	void setBlockSprite(int x, int y, Sprite* s);
	void destroyBlock(int x, int y);

	//게임의 현재 좌표를 블록의 좌표로만들어주는것
	Vec2 convertGamecoordToBlockCoord(const Vec2& gameCoord);
	//블록의 좌표를 게임의 좌표로 바꿔주는 것.
	Vec2 convertBlockcoordToGameCoord(const Vec2& blockCoord);

	//아래에서부터 찾아 올라가면서 비어있는 블록을 찾고
	// -1이 리턴에 되면 비어있는 블록이 없다는 뜻이다.
	int findEmptyBlockYIndex(int x,int y);

	//y위치부터 찾아 올라가면서 비어있지 않은 블록을 찾고
	//-1이 리턴이 되면 비어있지 않은 블록이 없다는 뜻이다.
	int findFilledBlockYIndex(int x, int y);

	//블록을 떨어뜨리는 함수
	void dropBlocks(int x);

	void stackPush(const Vec2& value);
	const Vec2& stackPop();
	void stackEmpty();
	bool stackFind(const Vec2& value);
	void judgeMatch(int x, int y);

	LayerIngameUI* ui;


public:
	static SceneIngame* create();
	virtual bool init() override;
	//override 로 알아서 몸체만 만들면 불러준다
	virtual void onEnter() override;

	//UI 만드는 함수
	void initUI();
	//게임을 초기화 하는 함수
	void initGame();
	//게임의 UI 삭제
	void destroyUI();
	// 게임의 스프라이트를 없애는것
	void destroyGame();

	void alignBlockSprite();

	bool onTouchBegan(Touch* t, Event* e);
	void onTouchMoved(Touch* t, Event* e);
	void onTouchEnded(Touch* t, Event* e);

	//게임시작
	void startGame();
	//일시정지
	void pauseGame();
	//이겼을때
	void winGame();

	void loseGame();
};

#endif // !__SCEN_INGAME_H__
  1. stdafx.h
#ifndef __STDAFX_H__
#define __STDAFX_H__

#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "audio/include/AudioEngine.h"

using namespace cocos2d;
using namespace cocos2d::ui;


#endif
profile
코딩 일지

0개의 댓글