Cocos2dx学习之-----别踩白块V1.0

学了点COCOS2DX,一直感觉也没什么大意思,所以就找个教程做个小游戏出来,反正国庆在校也没啥事,自娱自乐。

PS;我用的版本是cocos2dx3.2

一、创建项目

cocos new -p com.donttouchwhiteblock.xuran -l cpp -d .


二、创建block类

因为别猜白块里面最重要的一个元素就是“块”,所以我们要为这个元素创建一个类,然后实例化一些方法,以便完成游戏中的诸多行为

首先是gameblock.h文件

#pragma once
#include <iostream>
#include <cocos2d.h>
USING_NS_CC; 
class Block:public Sprite
{
public:
	static GameBlock* CreateWithArgs(Color3B color,Size size,std::string label,float fontsize,Color3B textcolor);
	virtual bool initWithArgs(Color3B color,Color3B textcolor);
	void removeblock();

private:
	static Vector<GameBlock*> *blocks;
};

头文件里面定义了三个成员函数:

第一个是创建一个block,根据所获取到的参数

第二个是初始化一个新的块根据参数。

第三个是移除一个块

还有创建了一个block指针类型的数组,用于存储我们创建的block的对象。

其次是GameBlock.cpp文件


#include "GameBlock.h"

Vector<GameBlock*> *GameBlock::blocks = new Vector<GameBlock*>();

GameBlock* GameBlock::CreateWithArgs(Color3B color,Color3B textcolor)
{
	auto b = new GameBlock();
	b->initWithArgs(color,size,label,fontsize,textcolor);
	b->autorelease();
	blocks->pushBack(b);
	return b;
	
}

void GameBlock::removeblock()
{
	removeFromParent();
	blocks->eraseObject(this);   //删除向量中特定的对象
}

bool GameBlock::initWithArgs(Color3B color,Color3B textcolor)
{

	Sprite::init();
	setContentSize(size);
	setAnchorPoint(Point::ZERO);
	setTextureRect(Rect(0,size.width,size.height));
	setColor(color);

	auto l = Label::create();
	l->setString(label);
	l->setSystemFontSize(fontsize);
	l->setColor(textcolor);
	addChild(l);
	l->setPosition(size.width/2,size.height/2);
	return true;
}

有对block数组的初始化,一个块的初始化函数,包括各种参数的设置以及一个创建函数,一个释放删除函数。


三、添加开始条

创建了块对应的类和相应的方法之后,我们就要开始真正的一步一步来做了。首先,别踩白块的游戏在开始的时候是有一条黄色的部分,代表着起点。那么首先就来为我们的游戏添加这个黄色的起点块。


很简单,从HelloWorldScene文件里面添加一个新的函数叫做AddStartLine,函数的实现很简单,就是通过CreateWithArgs函数创建一个块,然后添加进来即可。


bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    visibleSize = Director::getInstance()->getVisibleSize();
	AddStartLine();
    return true;
}

void HelloWorld::AddStartLine()
{
	auto b = GameBlock::CreateWithArgs(Color3B::YELLOW,Size(visibleSize.width,visibleSize.height/8),"Start",20,Color3B::BLACK);
	addChild(b);
}
既然开始条是这么添加的,那么结束条应该也是同理,再次就不再多做介绍了。
添加完开始和结束之后,我们要添加的就是普通的黑白块。


四、添加黑白块


首先我们要在类里面加入一个添加黑白块的方法叫做AddNormal

我们一般玩的别踩白块的版本的游戏通常一排有四个块,黑快是随机的出现在这四块中的其中一块,其余的都是白块。

既然是随机的,那么我们很自然的就要用到随机数。

利用rand函数产生一个0-4之间的随机数用来确定黑块的位置。

我们要有这样的一个概念,程序现在面对着一块白色的画布,我们要按着行的顺序,在按照列的顺序依次把每一行的白块和黑块都画好。

那么首先,我们需要创建一个块,究竟创建的是黑快还是白块,由上面的随机数来确定

void HelloWorld::AddNormal(int lineindex)
{
	int blackindex = rand()%4;
	GameBlock *b;

	for(int i = 0; i < 4; i++)
	{
		auto b = GameBlock::CreateWithArgs(blackindex == i?Color3B::BLACK:Color3B::WHITE,Size(visibleSize.width/4-1,visibleSize.height/4-1),"",Color3B::BLACK);
		addChild(b);
		b->setPosition(i*visibleSize.width/4,lineindex*visibleSize.height/4);
		b->setlineindex(lineindex);
	}
}

每排有四个块,我们是一排一排的进行设置。传进来的参数代表的是排数。

设置一个for循环,用来设定一行中的四个快。

首先创建一个块,因为上面生成一个blackindex的随机数,所以黑块的位置也就相应的指定了。添加到场景中之后,就要设置这个黑块的准确位置。

首先我们要把我们的屏幕宽度分为四部分,设置哪一部分是靠i来决定的,随意每一块的x坐标是用i来乘上一个块的宽度大小,纵坐标呢,当然是要设置第几行的黑白块,所以是靠我们传进来的要设置第几行来决定的。

void HelloWorld::StartGame()
{
	AddStartLine();
	AddNormal(1);
	AddNormal(2);
	AddNormal(3);
}

最后我们直接再添加一个开始游戏的函数,里面调用添加这些块的方法,在init函数里面运行这个即可看到效果。


五、事件交互

事件交互实际上就是你对这个游戏,或者对屏幕上的事务做出了点击,那么这个事务理应给一些一些反馈。

别再白块中的时间交互其实只有一个,就是你点黑快,游戏继续,你点白块游戏结束。就是这样。

我们以第一行为例,首先如果是要对一些操作做出反应的话,那么我们就需要一个监听器,来监听动作的发生,你可以选择监控一个控件是否被操作了,或者是监控整个场景是否被操作了。


首先我们要创建一个触摸事件的监听器

auto listener = EventListenerTouchOneByOne::create();

如果这个监听器接受到了触摸信号,那么他肯定要对这个触摸的动作做出反应,调用一个函数进行反应操作。

listener->onTouchBegan = [this](Touch *t,Event *e){
		log("xuran is winner");
		GameBlock *b;
		auto bs = GameBlock::getBlocks();
		for(auto it = bs->begin(); it != bs->end(); it++)
		{
			b = *it;
			if(b->getlineindex() == 1 && b->getBoundingBox().containsPoint(t->getLocation()))
			{
				if(b->getColor() == Color3B::BLACK)
				{
					b->setColor(Color3B::GRAY);
					this->movedown();
				}
				else
				{
					MessageBox("游戏失败","GameOver");
				}
			}
		}
		return false;
	};

所以在这里用了一个闭包函数。

这个闭包函数里面出现了一些新的函数,比如getblocks。这个函数是在GameBlock类里面进行定义的,他的作用就是返回存储块的vector,因为假如我创建了第一层,那么第一层肯定会创建四个块,其中一个黑块,三个白块,这些块里面都会有一个lineindex的属性,可以表明他们是第几行的块,这些块也都会加入到这个数组里面,所以在交互的时候,肯定要判断是触摸了白块还是触摸了黑块,所以要利用迭代器的遍历来进行确认。

listener->onTouchBegan
也表明了这是对触碰事件的一个回调函数。

在遍历数组中的块时,因为是游戏开始,为了能够正常的让游戏开始,我们首先要确定,vector中的第一个块是第一行的,并且这个块的范围是包含我们的触点的,由于这个if已经能够确定我们的手指触碰到了游戏中的块时,接下来要判断的就是触摸的是白块还是黑块。

如果是黑快,那么按下的黑块会变为黑色,并且把这一行下移,如果是白块的话,那么提示游戏失败。


bool HelloWorld::init()
{
	//////////////////////////////
	// 1. super init first
	if ( !Layer::init() )
	{
		return false;
	}
	visibleSize = Director::getInstance()->getVisibleSize();
	StartGame();
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [this](Touch *t,"GameOver");
				}
			}
		}
		return false;
	};
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this); //对当前场景进行监听
	return true;
}

六、设计游戏逻辑

这个游戏的逻辑很简单,不比2048.无非就是点击黑快所有的块向下移动,一直到结束,点击白块游戏失败。

所以说,主要实现的一个函数就是movedown。movedown的功能其实也很简单,就是把所有的块都要向下移动。首先在helloworldscene里面的movedown函数里面要遍历整个块的数组,依次让这些块执行下移的动作,至于这个具体的下移方法,要在块类的内部实现,因为这毕竟是一个块的行为。


首先,每个移动的块的所在行数,也就是lineindex都会随着移动的发生而减掉1.

其次便是要为每一个块执行一个下移动作

void GameBlock::moveon()
{
	Size visable = Director::getInstance()->getVisibleSize();
	this->lineindex--; //可以向下移动的行,移动之后所在的行会减去1
	runAction(Sequence::create(MoveTo::create(0.1f,Point(getPositionX(),lineindex*visable.height/4)),CallFunc::create([this]()
	{
		if(lineindex < 0)
		{
			this->removeblock();
		}
	}
	),NULL));  //执行一个移动的动作,把一个块移动到对应的位置上,间隔0.1
}


这里面的runaction函数将执行一个系列动作,执行完块的移动之后还要调用一个函数,如果这个块被移出了屏幕,那么他就应该被销毁,调用removeblock函数实现。

其次,我们要设置一个游戏的终点,也就是说游戏过程中如果一直没有踩到白块,那么究竟什么时候停止呢。

一般来说踩50个黑快之后应该游戏就停止了。

所以说要在helloworldscene类里面设置一个linecount,每次添加一行的普通块时都要加1,在所有的块向下移动的时候也是要判断,如果已经踩了50块了,那么再添加到屏幕顶部的就不应该是正常的 黑白块而是最终结束的绿色的游戏界面。


并且,在下移块的函数中,如果已经添加了一个游戏结束的绿色块,那么下次就不用添加了,直接下移就可以,因为一个游戏结束块的尺寸是整个屏幕,不用再多添加几个。

bool HelloWorld::init()
{
	//////////////////////////////
	// 1. super init first
	if ( !Layer::init() )
	{
		return false;
	}
	visibleSize = Director::getInstance()->getVisibleSize();
	StartGame();
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [this](Touch *t,Event *e){
		//log("xuran is winner");
		GameBlock *b;
		auto bs = GameBlock::getBlocks();
		for(auto it = bs->begin(); it != bs->end(); it++)
		{
			b = *it;
			if(b->getlineindex() == 1 && b->getBoundingBox().containsPoint(t->getLocation()))
			{
				if(b->getColor() == Color3B::BLACK)
				{
					b->setColor(Color3B::GRAY);
					this->movedown();
				}
				else if (b->getColor() == Color3B::GREEN)
				{
					this->movedown();
				}
				else
				{
					MessageBox("游戏失败","GameOver");
				}
				break;
			}
		}
		return false;
	};
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this); //对当前场景进行监听
	return true;
}

void HelloWorld::movedown()
{
	if(linecount < 50)
	{
		AddNormal(4); //在屏幕最上面添加一行,因为设置了屏幕内一次最多存在四行的块
	}
	else if(!showend)
	{
		showend = true;
		AddEndLine();
	}
	auto bs = GameBlock::getBlocks();
	for(auto it = bs->begin(); it != bs->end(); it++)
	{
		(*it)->moveon();	
	}
}

七、添加计时器

http://www.jb51.cc/article/p-qgpvjury-be.html关于计时器的使用我这里应该写了一些。

我是用的是scheduleupdate这个计时器,所以自己先定义一个update函数 。

之后我们要定义两个函数,一个是启动计时器的函数,一个是终止计时器的函数,无论是开始计时器还是终止计时器都只需要做一次,所以用一个bool变量来控制他的运行。

void HelloWorld::update(float dt)
{
	long offet = clock()-gametime;
	timelabel->setString(StringUtils::format("%g",((double)offet)/1000));
}
void HelloWorld::starttime()
{
	if(!timerrunning)
	{
		gametime = clock();    //获取当前系统运行这个程序的时间。
		scheduleUpdate();   //开始执行计时器
		timerrunning = true;
	}
}
void HelloWorld::endtime()
{
	if(timerrunning)
	{
		unscheduleUpdate();  //停止执行计时器
		timerrunning = false;
	}

}
scheduleupdate这个计时器会根据每一帧的变化调用update函数。

因为我们要在游戏界面中添加一个计时器,这个计时器是不断变化的,但是随着块的移动很可能会覆盖掉计时器,所以我们就想能够把游戏和计时器分开,把他们分别存在两个层中,这样一来两这就都不影响了。

gamelayer = Node::create();
	addChild(gamelayer);
	timelabel = Label::create();
	timelabel->setColor(Color3B::RED);
	timelabel->setSystemFontSize(38);
	timelabel->setPosition(visibleSize.width/2,visibleSize.height-50);
	timelabel->setString("0.000\"");
	addChild(timelabel);

创建一个新的层叫做gamelayer,之后再创建一个label标签,用于时刻显示时间,并添加到我当前的层里,把之前所有的游戏里面添加开始快结束快的函数里面的addchild都变成gamelayer->addchild(b),也就是说把游戏当中的元素都添加到游戏层里面,计时器添加到当前的层里面。


if(b->getlineindex() == 1 && b->getBoundingBox().containsPoint(t->getLocation()))
			{
				if(b->getColor() == Color3B::BLACK)
				{
					if(!timerrunning)
					{
						this->starttime();
					}
					b->setColor(Color3B::GRAY);
					this->movedown();
				}
				else if (b->getColor() == Color3B::GREEN)
				{
					this->movedown();
					this->endtime();
				}
				else
				{
					MessageBox("游戏失败","GameOver");
				}
				break;
			}

最后根据踩的是黑快还是绿快要确定计时器的停止和开始。




PS:第一版基本就是这样了,算是可以玩了,但是还是有很多需要改进完善的地方,以后有心情再搞

https://github.com/Harkphoenix/DontTouchWhiteBlock 源码在这里,我是用vs写的

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是