cocos中如何用砖块画出LED数字

我们可以利用精灵的移动,然后在精灵的移动过程中,通过创建时间线程,逐步创建砖块精灵,这样就达到了用砖块画出图形的目的。该灵感来自于:http://www.jb51.cc/article/p-oyajubhs-vx.html

现在我们具体讲解下如何通过移动实现。首先,移动是一个动作,而一个LED数字,是会拐弯的,因此,这个需要连续N个动作的连接,这个我们可以用Sequence实现。如果是一笔就可以完成的动作,那么一个时间线程就足够了,但是,有些数字,是不能一笔画出的,比如数字3。那么这个时候,就需要再开一个线程了。为了避免节点间的相互独立,因此我们应该将精灵移动并创建砖块的过程封装在一个类中。

我们将精灵的移动,分为上下左右,然后在封装的类中存放每次移动的位置集合,方便我们任意修改移动精灵的起始坐标。

关键代码:

//drawnode.h

class DrawNumberAction : public Node
{
public:
	enum
	{
		tag_brick = 1,tag_move = 2,tag_move3 = 3,};

	DrawNumberAction(std::vector<Vec2> & vct,bool first,float coeff,float pts,int tagval,Layer * pay) : m_pos(vct),isfirst(first),coefficient(coeff),ts(pts),nodetag(tagval),player(pay)
	{}

	~DrawNumberAction();

	void DrawActionMove();

	void DrawBrick(float dt);

	void CreateBrick(const cocos2d::Vec2 & pos);

	void CancelDraw(cocos2d::Object* pSender);

private:
	std::vector<Vec2> & m_pos;
	bool isfirst;
	float coefficient;
	float ts;
	int nodetag;
	Layer * player;
};

//drawnode.cpp

void DrawNumberAction::DrawActionMove()
{
	auto batchnode2 = SpriteBatchNode::create("gray_brick.png");

	cocos2d::Vector<FiniteTimeAction*> vctmove;
	Sequence* seq = NULL;

	if (isfirst && m_pos.size() > 0)
	{
		CreateBrick(m_pos[0]);
	}

	for (int i = 0; i < m_pos.size() - 1; ++i)
	{
		auto actionMove = CCMoveTo::create(ts * coefficient,m_pos[i+1]);
		vctmove.pushBack(actionMove);

		if (i == 0)
		{
//指定移动精灵的起始地址
			batchnode2->setPosition(m_pos[i]);
			//设置runaction
			batchnode2->setTag(nodetag);
		}
	}

	auto actionMoveDone = CallFuncN::create(CC_CALLBACK_1(DrawNumberAction::CancelDraw,this));
	vctmove.pushBack(actionMoveDone);

	seq = Sequence::create(vctmove);

	batchnode2->runAction(seq);
	this->addChild(batchnode2);

	//设置schedule事件
	this->schedule(schedule_selector(DrawNumberAction::DrawBrick),coefficient);
}

void DrawNumberAction::DrawBrick(float dt)
{
	auto container = this->getChildByTag(nodetag);

	CreateBrick(container->getPosition());
}

void DrawNumberAction::CreateBrick(const cocos2d::Vec2 & pos)
{
	//画出砖块
	CCSprite* sprFlowerTmp = CCSprite::create("gray_brick.png");
	sprFlowerTmp->setPosition(pos);

	auto body = PhysicsBody::createBox(sprFlowerTmp->getContentSize());
	body->setContactTestBitmask(0xFFFFFFFF);
	body->setGroup(-1);

	sprFlowerTmp->setPhysicsBody(body);
	sprFlowerTmp->setTag(tag_brick);
	player->addChild(sprFlowerTmp);
}

void DrawNumberAction::CancelDraw(Object* pSender)
{
	DrawBrick(1.0f);

	//取消画砖块的定时线程
	this->unschedule(schedule_selector(DrawNumberAction::DrawBrick));
}

//helloworld.cpp

int HelloWorld::DrawNumeric(int num)
{
	//假设个数字的大小
	//底下必须留30个高度
	auto visibleSize = Director::getInstance()->getVisibleSize();
	auto origin = Director::getInstance()->getVisibleOrigin();

	float xleft = visibleSize.width/2 - 20;
	float yup = visibleSize.height - 20;

	Vec2 startpos(xleft,yup);

	DrawDecomposition3(num,startpos);

	return 0;
}

int HelloWorld::DrawDecomposition3(int num,cocos2d::Vec2 & startpos)
{
	//如何画出数字3?数字3不能一笔搞定,因此,分两个线程去处理
	vector<cocos2d::Vec2> result;

	result.push_back(startpos);

	if (0 == num)
	{
		//0就是一个大矩形
		GetDestPos(draw_right,result[0],result);
		GetDestPos(draw_down,result[1],result[2],result);
		GetDestPos(draw_left,result[3],result);
		GetDestPos(draw_up,result[4],result[5],result);

		float ts = squaresize - 1;

		//画第一部分
		DrawNumberAction * firstmove = new DrawNumberAction(result,true,coefficient,ts,tag_move,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);
	}
	else if (1 == num)
	{
		GetDestPos(draw_down,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);
	}
	else if (2 == num)
	{
		//这是连串的一组
		GetDestPos(draw_right,result);
		GetDestPos(draw_right,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);
	}
	else if(3 == num)
	{
		//这是连串的一组
		GetDestPos(draw_right,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);

		//画第二部分
		vector<cocos2d::Vec2> part2;
		part2.push_back(result[2]);

		GetDestPos(draw_left,part2[0],part2);

		DrawNumberAction * secmove = new DrawNumberAction(part2,false,tag_move3,this);
		secmove->DrawActionMove();
		this->addChild(secmove);
	}
	else if (4 == num)
	{
		//分两部分
		//这是连串的一组
		GetDestPos(draw_down,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);

		//画第二部分
		vector<cocos2d::Vec2> part2;

		//第二部分的起始点有点特殊,需要额外计算
		Vec2 start;
		start.x = result[2].x;
		start.y = result[0].y;

		part2.push_back(start);
		GetDestPos(draw_down,part2);
		GetDestPos(draw_down,part2[1],this);
		secmove->DrawActionMove();
		this->addChild(secmove);
	}
	else if (5 == num)
	{
		GetDestPos(draw_left,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);
	}
	else if (6 == num)
	{
		//是5的结尾后,再加一笔上
		GetDestPos(draw_left,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);
	}
	else if (7 == num)
	{
		GetDestPos(draw_right,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);
	}
	else if (8 == num)
	{
		//画个矩形
		GetDestPos(draw_right,this);
		firstmove->DrawActionMove();

		this->addChild(firstmove);

		//画第二部分
		//以第二步的终点为起点
		vector<cocos2d::Vec2> part2;
		part2.push_back(result[2]);
		GetDestPos(draw_down,part2);
		GetDestPos(draw_left,part2);
		GetDestPos(draw_up,part2[2],this);
		secmove->DrawActionMove();
		this->addChild(secmove);
	}
	else if (9 == num)
	{
		//8与9的区别,就在于没有最后向上的一笔
		GetDestPos(draw_right,this);
		secmove->DrawActionMove();
		this->addChild(secmove);
	}

	return 0;
}

int HelloWorld::GetDestPos(Direction dire,cocos2d::Vec2 & startpos,std::vector<cocos2d::Vec2> & vct)
{
	Vec2 dest(startpos);

	switch (dire)
	{
		case draw_right: dest.x += (squaresize - 1)*bricksize.x;  break;
		case draw_left: dest.x -= (squaresize - 1)*bricksize.x; break;
		case draw_down: dest.y -= (squaresize - 1)*bricksize.y;  break;
		case draw_up: dest.y += (squaresize - 1)*bricksize.y;  break;
		default:  return 0;
	}

	vct.push_back(dest);
}

GetDestPos()函数的功能是根据方向,获取终点的位置坐标。代码大致就是这样。有点小问题的就是,当头和尾都已经存在时,再去画砖块时,会存在精灵重复覆盖。

不知道怎么录制演示过程。只好放几张最终的效果图片了。





源码和资源文件路径可从下面路径下载:

http://git.oschina.net/codessheng/cocoslednumber

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...