zoukankan      html  css  js  c++  java
  • cocos2d-x 3.2 之 2048 —— 第五篇

    ***************************************转载请注明出处: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********************************************

  • 相关阅读:
    MySQL基础语句【学习笔记】
    减一技术应用:生成排列与幂集
    Java实现动态规划法求解0/1背包问题
    LODOP中ADD_PRINT_TABLE、HTM、HTML表格自动分页测试
    LODOP设置判断后执行哪个
    Lodop删除语句Deleted只能内嵌设计维护可用
    Lodop、c-lodop注册与角色简短问答
    LODOP暂存、应用、复原 按钮的区别
    JS判断语句 注意多句时加大括号 回调函数LODOP兼顾写法
    LODOP、C-Lodop简短排查语句
  • 原文地址:https://www.cnblogs.com/lytwajue/p/6999136.html
Copyright © 2011-2022 走看看