1. 程式人生 > >cocos2d-x 3.2 之 2048 —— 第五篇

cocos2d-x 3.2 之 2048 —— 第五篇

能夠 urn onf 平臺 restart getch ring article dia

***************************************轉載請註明出處:http://blog.csdn.net/lttree******************************************




不知不覺。都10月5號了,

十一大假期快結束了技術分享

不開心啊,技術分享 有木有。。!


算了,接著發 2048 吧,這是第五篇了,

也非常快了呀,2048系列。立即就要結束了。

這篇文章主要講述:

—— 對於遊戲相關移動和遊戲結束的判定

—— 遊戲音效的加入

—— 遊戲分數的加入


直接正文:

1. 遊戲方向是否能移動 和 遊戲結束的判定

這倆為什麽放一塊呢?

我的方法是在.h建立4個bool變量:是否能向上移動、是否能向下移動、。。。

這樣。假設四個方向都不能移動,即為遊戲結束了。


為這個判定,單獨建立一個函數:

<span style="font-family:Comic Sans MS;">void GameScene::judgeMove()
{
	int r , c;
	isMoveUp = false;
	isMoveDown = false;
	isMoveRight = false;
	isMoveLeft = false;

	// 向上能否移動
	for( r = 0 ; r < GAME_ROWS - 1 ; ++r )
	{
		for( c = 0 ; c < GAME_COLS ; ++c )
		{
			if( map[r+1][c] == 0 )
			{
				if( map[r][c] != 0 )	{	isMoveUp = true;	break;	}
			}
			else
			{
				if( map[r][c] != 0 )
				{
					if(	m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r+1][c] - 1 ) -> m_number )
					{	isMoveUp = true;	break;	}
				}
			}
		}
		if( isMoveUp == true )	break;
	}

	// 向下能否移動
	for( r = GAME_ROWS-1 ; r > 0 ; --r )
	{
		for( c = 0 ; c < GAME_COLS ; ++c )
		{
			if( map[r-1][c] == 0 )
			{
				if( map[r][c] != 0 )	
				{	isMoveDown = true;	break;	}
			}
			else
			{
				if( map[r][c] != 0 )
				{
					if(	m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r-1][c] - 1 ) -> m_number )
					{	isMoveDown = true;	break;	}
				}
			}
		}
		if( isMoveDown == true  )	break;
	}

	// 向左能否移動
	for( c = 0 ; c < GAME_COLS-1 ; ++c )
	{
		for( r = 0 ; r < GAME_ROWS ; ++r )
		{
			if( map[r][c+1] == 0 )
			{
				if( map[r][c] != 0 )	{	isMoveRight = true;	break;	}
			}
			else
			{
				if( map[r][c] != 0 )
				{
					if(	m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r][c+1] - 1 ) -> m_number )
					{	isMoveRight = true;	break;	}
				}
			}
		}
		if( isMoveRight == true )	break;
	}

	// 向右能否移動
	for( c = GAME_COLS-1 ; c > 0  ; --c )
	{
		for( r = 0 ; r < GAME_ROWS ; ++r )
		{
			if( map[r][c-1] == 0 )
			{
				if( map[r][c] != 0 )	{	isMoveLeft = true;	break;	}
			}
			else
			{
				if( map[r][c] != 0 )
				{
					if(	m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r][c-1] - 1 ) -> m_number )
					{	isMoveLeft = true;	break;	}
				}
			}
		}
		if( isMoveLeft == true )	break;
	}
}</span>


以是否能向上移動來解析一下這種方法:

從最以下一行第一列到倒數第二行最後一列,進行兩層循環:

——首先推斷同列的上面那一行,是否為0(即是否是空的格子,沒有數字塊)

————假設為空,推斷這一行是否為空

——————不為空。則能夠向上移動

——————為空。則不能移動

————假設不為空,推斷本行對應列是否為空

——————為空,則不能移動

——————不為空,推斷本行與上一行同列的是否同樣

————————同樣。則能夠移動

————————不同。不能移動

依據前面“——”長短,能夠看出,推斷等級。


然後,建立遊戲結束界面的類~GameOverScene:

<span style="font-family:Comic Sans MS;font-size:12px;">#ifndef __test2048_GameOverScene_H__
#define __test2048_GameOverScene_H__

#include "cocos2d.h"

USING_NS_CC;

class GameOver: public Layer
{
public:
	virtual bool init();
	static Scene * createScene();
	CREATE_FUNC(GameOver);

	// 又一次開始遊戲 的回調函數
	void menuRestartCallback( Ref * pObject );
	// 退出 的回調函數
	void menuExitCallback( Ref * pObject );
};


#endif</span>

.cpp:

<span style="font-family:Comic Sans MS;font-size:14px;">#include "GameOverScene.h"
#include "GameDefine.h"
#include "GameScene.h"

Scene * GameOver::createScene()
{
	auto scene = Scene::create();
	auto * layer = GameOver::create();
	
	scene -> addChild( layer );

		return scene;
}

bool GameOver::init()
{
	if( !Layer::init() )
	{
		return false;
	}


	// 又一次開始遊戲
	auto restartItem = MenuItemFont::create(" Restart ",CC_CALLBACK_1(GameOver::menuRestartCallback,this));
	restartItem -> setPosition( Point( GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT/2));
	
	// 退出遊戲
	auto exit = MenuItemFont::create(" Exit ",CC_CALLBACK_1(GameOver::menuExitCallback,this));
	exit -> setPosition( Point( GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT/3 ));

	auto menu = Menu::create(restartItem,exit,NULL);
	menu -> setPosition(Point::ZERO);
	this -> addChild(menu);

    
	return true;
}

void GameOver::menuRestartCallback(Ref * pObject)
{
	auto scene = GameScene::createScene();
	Director::getInstance() -> replaceScene(CCTransitionProgressRadialCCW::create(1,scene));
}

void GameOver::menuExitCallback(Ref * pObject)
{
	Director::getInstance()->end();
}</span><span style="font-size:18px;">
</span>

Ok,遊戲結束界面已經搞定技術分享,能夠改一下AppDelegate.cpp ,讓遊戲直接進入 GameOver界面,看看什麽樣子:

技術分享


遊戲結束界面,就是這樣子的~

做到這裏。你們會不會 非常嫌棄,臥XXXX,這麽醜。

好吧,是非常醜,

可是,這系列教程主要是,說明怎樣開發一款 2048 。

詳細自己做的東東,能夠自己DIY的~

選擇一個自己喜歡的背景圖片,選擇圖片button神馬的,

包裝一下,就相當美麗啦~

但這些的前提是,要會怎麽做2048,要知道 ,我想增加什麽。應該在哪裏改變什麽,加什麽。

而這系列教程,就是在說明。2048的制作及解析~


廢話不多說。繼續下去,要將GameScene中 moveAllTiled函數改變一下啦~:

<span style="font-family:Comic Sans MS;font-size:14px;">void GameScene::moveAllTiled( MOVE_DIR dir )
{
	// 推斷 並 移動全部塊  消除
	judgeMove();

	// 假設上下左右都不能移動,則遊戲結束~
	if( !isMoveLeft  && !isMoveRight && !isMoveUp && !isMoveDown )
	{
		auto * scene = Scene::create();
		GameOver * layer = GameOver::create();
		scene -> addChild( layer );
		
		Director::sharedDirector() -> replaceScene(CCTransitionFadeDown::create(1.5f,scene));

	}

	// 依據方向移動,可是要先推斷能否夠向那個方向移動
	switch ( dir )
	{
	case MOVE_DIR::UP:
		if( !isMoveUp )	return;
		moveUp();
		break;
	case MOVE_DIR::DOWN:
		if( !isMoveDown )	return;
		moveDown();
		break;
	case MOVE_DIR::LEFT:
		if( !isMoveLeft )	return;
		moveLeft();
		break;
	case MOVE_DIR::RIGHT:	
		if( !isMoveRight )	return;
		moveRight();
		break;
	default:	break;
	}


	// 產生新塊
	newNumberTiled();
}</span>

對於,遊戲結束方面,到這裏就結束啦~


2.加入音效

對於2048,我認為還是不要加入背景音樂了。非常突兀的感覺的說,

我僅僅是簡單加了兩個音效,假設有數字合並。一個成功的小音效。

假設沒有數字合並,則是滑動的音效。

當然。先把對應文件放到Resource目錄下。並在VS2012中加入現有項。加入進來,


然後在程序中,也須要進行載入。

我選擇是在主界面跳到遊戲界面之前,進行載入:

<span style="font-family:Comic Sans MS;font-size:14px;">// 載入音效
	SimpleAudioEngine::getInstance() -> preloadEffect("move.wav");
	SimpleAudioEngine::getInstance() -> preloadEffect("move1.wav");</span>

當然,之前要加入音效的頭文件:

<span style="font-family:Comic Sans MS;font-size:14px;">#include "SimpleAudioEngine.h"

using namespace CocosDenshion;</span>

然後。在遊戲移動全部塊函數中。加入聲音播放:

如今。頭文件加入兩個bool變量:

<span style="font-family:Comic Sans MS;font-size:14px;">	// 播放哪個音樂
	bool m_sound_clear;</span>

GameScene.cpp——moveAllTiled:

<span style="font-family:Comic Sans MS;font-size:12px;">void GameScene::moveAllTiled( MOVE_DIR dir )
{
	// 推斷 並 移動全部塊  消除
	judgeMove();

	// 假設上下左右都不能移動,則遊戲結束~
	if( !isMoveLeft  && !isMoveRight && !isMoveUp && !isMoveDown )
	{
		auto * scene = Scene::create();
		GameOver * layer = GameOver::create();
		scene -> addChild( layer );
		
		Director::sharedDirector() -> replaceScene(CCTransitionFadeDown::create(1.5f,scene));

	}
</span>
<span style="font-family:Comic Sans MS;font-size:12px;"><span style="white-space:pre">	</span>m_sound_clear = false;</span>
<span style="font-family:Comic Sans MS;font-size:12px;">	// 依據方向移動。可是要先推斷能否夠向那個方向移動
	switch ( dir )
	{
	case MOVE_DIR::UP:
		if( !isMoveUp )	return;
		moveUp();
		break;
	case MOVE_DIR::DOWN:
		if( !isMoveDown )	return;
		moveDown();
		break;
	case MOVE_DIR::LEFT:
		if( !isMoveLeft )	return;
		moveLeft();
		break;
	case MOVE_DIR::RIGHT:	
		if( !isMoveRight )	return;
		moveRight();
		break;
	default:	break;
	}

	// 播放音樂
	if( m_sound_clear )
	{
		SimpleAudioEngine::getInstance() -> playEffect("move.wav");
	}
	else
	{
		SimpleAudioEngine::getInstance() -> playEffect("move1.wav");
	}

	// 產生新塊
	newNumberTiled();
}</span>

然後,在對應移動函數中。要設置m_sound_clear的值:

就是在moveUp,moveDown,moveLeft,moveRight對應位置。進行設置

在數字合並的推斷語句下(推斷numNow==numObj處),進行:

m_sound_clear = true;

Ok,我們能夠執行技術分享。感受一下啦~

假設對於,音效,還有什麽疑問,能夠看我之前寫的文章,專門說音效的博文:戳我~


接下來。就是關於分數的設置啦~


3.分數的加入

首先,在遊戲界面,頭文件設置。整型的分數變量

然後在初始化函數設定分數的位置:

GameScene.cpp——init:

<span style="font-family:Comic Sans MS;font-size:12px;">	TTFConfig config("HelloKitty.ttf",40);

	// 分數
	score = 0;
	auto labelScore = Label::createWithTTF(config, "Score  :  0  ");  
	labelScore -> setPosition( Point(GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT - 1.5*labelScore->getContentSize().height));
	this->addChild(labelScore);
	labelScore -> setTag(105);</span>


我們分數的添加是,每合成一個新數字,加上所生成的數字,

比方兩個2生成了一個4。則分數+4。

兩個512 生成了一個 1024,則分數+1024,

所以,分數改變的位置 和 設置音樂的位置一樣,

由於僅僅有合成成功的時候,分數才會添加:

<span style="font-family:Comic Sans MS;font-size:14px;">if( numNow == numObj )
{
	m_sound_clear = true;
	score += numObj * 2;</span>


然後,還要在移動全部塊以後,更新分數:

GameScene.cpp——moveAllTiled:

<span style="font-family:Comic Sans MS;font-size:14px;">// 分數更新
Label *labelScore = (Label *)this -> getChildByTag(105);
labelScore -> setString( StringUtils::format(" Score : %d  ",score));</span>

好的啦~。~ 分數也更新完了。

執行一下。技術分享看看效果~

技術分享


正常執行喲~

嘿嘿。第五篇就到這裏了。

下一篇就是終於章了

安卓平臺移植~

這系列真的要結束了呢技術分享



第五篇代碼:http://pan.baidu.com/s/1mgHWcyO



***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************

cocos2d-x 3.2 之 2048 —— 第五篇