cocos2dx 自定义进度条的实现!

前端之家收集整理的这篇文章主要介绍了cocos2dx 自定义进度条的实现!前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

//好久没写博客,本人比较懒,而且没啥技术,所以。。。

进度条,2dx源码的ProgressTimer只有条形进度条和弧形进度条!那么请问,以下


这种图片的进度条要怎么做呢! 然后有人会说,用弧形进度条,进度条的中心点事图片的中心点,那样你会发现在一些地方会出现斜边,并且图片长宽不等的情况下,速度不一样!

那现在问题来了,要怎么解决呢?我们先看源码!

ProgressTimer的核心函数draw()(它又调用ondraw方法),所以!

void ProgressTimer::onDraw(const Mat4 &transform,uint32_t flags)
{

    getGLProgram()->use();
    getGLProgram()->setUniformsForBuiltins(transform);

    GL::blendFunc( _sprite->getBlendFunc().src,_sprite->getBlendFunc().dst );

    GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );

    GL::bindTexture2D( _sprite->getTexture()->getName() );

    glVertexAttribPointer( GLProgram::VERTEX_ATTRIB_POSITION,2,GL_FLOAT,GL_FALSE,sizeof(_vertexData[0]),&_vertexData[0].vertices);
    glVertexAttribPointer( GLProgram::VERTEX_ATTRIB_TEX_COORD,&_vertexData[0].texCoords);
    glVertexAttribPointer( GLProgram::VERTEX_ATTRIB_COLOR,4,GL_UNSIGNED_BYTE,GL_TRUE,&_vertexData[0].colors);

    if(_type == Type::RADIAL)
    {
        glDrawArrays(GL_TRIANGLE_FAN,_vertexDataCount);
        CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_vertexDataCount);
    }
    else if (_type == Type::BAR)
    {
        if (!_reverseDirection) 
        {
            glDrawArrays(GL_TRIANGLE_STRIP,_vertexDataCount);
            CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_vertexDataCount);
        }
        else 
        {
            glDrawArrays(GL_TRIANGLE_STRIP,_vertexDataCount/2);
            glDrawArrays(GL_TRIANGLE_STRIP,_vertexDataCount/2);
            // 2 draw calls
            CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(2,_vertexDataCount);
        }
    }
}
其中_vertexData是一些当前位置的的数组,_vertexDataCount这个数组的大小。

主要看下这个函数glDrawArrays(GL_TRIANGLE_FAN,_vertexDataCount)的GL_TRIANGLE_FAN,可以看以下链接

点击打开链接

就拿GL_TRIANGLE_STRIP来说


		if (!_vertexData) {
			_vertexDataCount = 4;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,"CCProgressTimer. Not enough memory");
		}

		_vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(1,0));
		_vertexData[0].vertices = vertexFromAlphaPoint(Vec2(1,0));

		_vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(0,0));
		_vertexData[1].vertices = vertexFromAlphaPoint(Vec2(0,0));

		_vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(1,1));
		_vertexData[2].vertices = vertexFromAlphaPoint(Vec2(1,1));

		_vertexData[3].texCoords = textureCoordFromAlphaPoint(Vec2(0,1));
		_vertexData[3].vertices = vertexFromAlphaPoint(Vec2(0,1));

然后在onDraw()方法的相应位置:
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,&_vertexData[0].vertices);
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD,&_vertexData[0].texCoords);
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,&_vertexData[0].colors);
	glDrawArrays(GL_TRIANGLE_STRIP,_vertexDataCount);
	CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_vertexDataCount);
就可以画出整张图片(说实在的,opengl我也不懂,只能看源码依葫芦画瓢抄出来!)
现在看我重写的类:MyProgressTimer

MyProgressTimer.h:

#pragma once
#include "cocos2d.h"

#define  kMyProgressTextureCoordsCount 4
const char kMyProgressTextureCoords = 0x4b;
USING_NS_CC;

class MyProgressFromTo : public ActionInterval
{

public:
	static MyProgressFromTo* create(float duration,float fromPercentage,float toPercentage);

	virtual MyProgressFromTo* clone() const override;
	virtual MyProgressFromTo* reverse() const override;
	virtual void startWithTarget(Node *target) override;
	virtual void update(float time) override;

CC_CONSTRUCTOR_ACCESS:
	MyProgressFromTo() {}
	virtual ~MyProgressFromTo() {}

	bool initWithDuration(float duration,float toPercentage);

protected:
	float _to;
	float _from;

private:
	CC_DISALLOW_COPY_AND_ASSIGN(MyProgressFromTo);
};

class MyProgressTimer : public cocos2d::Node
{
public:
	MyProgressTimer(){ m_pSpr = nullptr; _vertexData = nullptr; _vertexDataCount = 0; m_fPercentage = 0.0f; };
	~MyProgressTimer(){
		if (m_pSpr)
		{
			CC_SAFE_RELEASE(m_pSpr);
		}
		if (_vertexData)
		{
			CC_SAFE_FREE(_vertexData);
		}
	};

	enum class ProgressType
	{
		None,Start,Step1,Circle1_1,Circle1_2,Step2,Circle2_1,Circle2_2,Step3,Circle3_1,Circle3_2,Step4,Circle4_1,Circle4_2,Step5,End
	};

	static MyProgressTimer* create(Sprite* sp);

	bool initWithSprite(Sprite* sp);

	void onDraw(const Mat4 &transform,uint32_t flags);
	
	void setSprite(Sprite *sprite);

	void draw(Renderer *renderer,const Mat4& transform,uint32_t flags);

	virtual void updateColor(void) override;

	void updateProgress(void);

	Vec2 boundaryTexCoord(char index);

	Tex2F textureCoordFromAlphaPoint(Vec2 alpha);
	Vec2 vertexFromAlphaPoint(Vec2 alpha);

	void setPercentage(float percentage);

	void setOrigin(Vec2 _vOrigin);
	void setTop(Vec2 _vTop);

	float getPercentage(){ return m_fPercentage; };

	ProgressType percentToStep(float &_pos);

	float m_fPercentage;

	CustomCommand _customCommand;

	Sprite* m_pSpr;

	int _vertexDataCount;
	V2F_C4B_T2F *_vertexData;

	ProgressType m_type;

	Vec2 m_vOrigin;
	Vec2 m_vTop;
};
MyProgressTimer.cpp
#pragma once
#include "MyProgressTimer.h"

USING_NS_CC;

MyProgressTimer* MyProgressTimer::create(Sprite* sp)
{
	MyProgressTimer *progressTimer = new (std::nothrow) MyProgressTimer();
	if (progressTimer->initWithSprite(sp))
	{
		progressTimer->autorelease();
	}
	else
	{
		delete progressTimer;
		progressTimer = nullptr;
	}

	return progressTimer;
}

bool MyProgressTimer::initWithSprite(Sprite* sp)
{
	setSprite(sp);

	setOrigin(Vec2(0.05f,0.05f));
	setTop(Vec2(0.95f,0.95f));

	setAnchorPoint(Vec2(0.5f,0.5f));

	setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));

	m_type = ProgressType::None;

	setPercentage(0.0f);

	ProgressFromTo;

	return true;
}

void MyProgressTimer::onDraw(const Mat4 &transform,uint32_t flags)
{
	getGLProgram()->use();
	getGLProgram()->setUniformsForBuiltins(transform);

	GL::blendFunc(m_pSpr->getBlendFunc().src,m_pSpr->getBlendFunc().dst);

	GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);

	GL::bindTexture2D(m_pSpr->getTexture()->getName());

	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,_vertexDataCount);
}

void MyProgressTimer::draw(Renderer *renderer,uint32_t flags)
{
	if (!_vertexData || !m_pSpr)
		return;

	_customCommand.init(_globalZOrder);
	_customCommand.func = CC_CALLBACK_0(MyProgressTimer::onDraw,this,transform,flags);
	renderer->addCommand(&_customCommand);
}

void MyProgressTimer::setSprite(Sprite *sprite)
{
	if (m_pSpr != sprite)
	{
		CC_SAFE_RETAIN(sprite);
		CC_SAFE_RELEASE(m_pSpr);
		m_pSpr = sprite;
		setContentSize(m_pSpr->getContentSize());

		if (_vertexData)
		{
			CC_SAFE_FREE(_vertexData);
			_vertexDataCount = 0;
		}
	}
}

void MyProgressTimer::updateColor(void)
{
	if (!m_pSpr) {
		return;
	}

	if (_vertexData)
	{
		Color4B sc = m_pSpr->getQuad().tl.colors;
		for (int i = 0; i < _vertexDataCount; ++i)
		{
			_vertexData[i].colors = sc;
		}
	}
}

cocos2d::Tex2F MyProgressTimer::textureCoordFromAlphaPoint(Vec2 alpha)
{
	Tex2F ret(0.0f,0.0f);
	if (!m_pSpr) {
		return ret;
	}
	V3F_C4B_T2F_Quad quad = m_pSpr->getQuad();
	Vec2 min = Vec2(quad.bl.texCoords.u,quad.bl.texCoords.v);
	Vec2 max = Vec2(quad.tr.texCoords.u,quad.tr.texCoords.v);
	//  Fix bug #1303 so that progress timer handles sprite frame texture rotation
	if (m_pSpr->isTextureRectRotated()) {
		CC_SWAP(alpha.x,alpha.y,float);
	}
	return Tex2F(min.x * (1.f - alpha.x) + max.x * alpha.x,min.y * (1.f - alpha.y) + max.y * alpha.y);
}

cocos2d::Vec2 MyProgressTimer::vertexFromAlphaPoint(Vec2 alpha)
{
	Vec2 ret(0.0f,0.0f);
	if (!m_pSpr) {
		return ret;
	}
	V3F_C4B_T2F_Quad quad = m_pSpr->getQuad();
	Vec2 min = Vec2(quad.bl.vertices.x,quad.bl.vertices.y);
	Vec2 max = Vec2(quad.tr.vertices.x,quad.tr.vertices.y);
	ret.x = min.x * (1.f - alpha.x) + max.x * alpha.x;
	ret.y = min.y * (1.f - alpha.y) + max.y * alpha.y;
	return ret;
}

Vec2 MyProgressTimer::boundaryTexCoord(char index)
{
	if (index < kMyProgressTextureCoordsCount) {
		if (true) {
			return Vec2((kMyProgressTextureCoords >> (7 - (index << 1))) & 1,(kMyProgressTextureCoords >> (7 - ((index << 1) + 1))) & 1);
		}
		else {
			return Vec2((kMyProgressTextureCoords >> ((index << 1) + 1)) & 1,(kMyProgressTextureCoords >> (index << 1)) & 1);
		}
	}
	return Vec2::ZERO;
}

void MyProgressTimer::setPercentage(float percentage)
{
	m_fPercentage = clampf(percentage,100);
	updateProgress();
}

void MyProgressTimer::updateProgress(void)
{
	if (!m_pSpr) {
		return;
	}

	Vec2 min = Vec2(0,0);
	Vec2 max = Vec2(1,1);
	Vec2 mid = Vec2(.5,.5);

	float pos = 0.0f;
	auto step = percentToStep(pos);
	if (ProgressType::Start == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,"CCProgressTimer. Not enough memory");
		}

		_vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(min.x,min.y));
		_vertexData[0].vertices = vertexFromAlphaPoint(Vec2(min.x,min.y));

		_vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(max.x,min.y));
		_vertexData[1].vertices = vertexFromAlphaPoint(Vec2(max.x,min.y));

		_vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(min.x,max.y));
		_vertexData[2].vertices = vertexFromAlphaPoint(Vec2(min.x,max.y));

		for (int i = 3; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(max.x,max.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(max.x,max.y));
		}
	}
	else if (ProgressType::Step1 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,"CCProgressTimer. Not enough memory");
		}

		_vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(mid.x,max.y));
		_vertexData[0].vertices = vertexFromAlphaPoint(Vec2(mid.x,max.y));

		_vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(mid.x,m_vTop.y));
		_vertexData[1].vertices = vertexFromAlphaPoint(Vec2(mid.x,m_vTop.y));

		_vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(min.x,max.y));

		_vertexData[3].texCoords = textureCoordFromAlphaPoint(Vec2(m_vOrigin.x,m_vTop.y));
		_vertexData[3].vertices = vertexFromAlphaPoint(Vec2(m_vOrigin.x,m_vTop.y));

		_vertexData[4].texCoords = textureCoordFromAlphaPoint(Vec2(min.x,min.y));
		_vertexData[4].vertices = vertexFromAlphaPoint(Vec2(min.x,min.y));

		_vertexData[5].texCoords = textureCoordFromAlphaPoint(Vec2(m_vOrigin.x,m_vOrigin.y));
		_vertexData[5].vertices = vertexFromAlphaPoint(Vec2(m_vOrigin.x,m_vOrigin.y));

		_vertexData[6].texCoords = textureCoordFromAlphaPoint(Vec2(max.x,min.y));
		_vertexData[6].vertices = vertexFromAlphaPoint(Vec2(max.x,min.y));

		_vertexData[7].texCoords = textureCoordFromAlphaPoint(Vec2(m_vTop.x,m_vOrigin.y));
		_vertexData[7].vertices = vertexFromAlphaPoint(Vec2(m_vTop.x,m_vOrigin.y));

		_vertexData[8].texCoords = textureCoordFromAlphaPoint(Vec2(max.x,max.y));
		_vertexData[8].vertices = vertexFromAlphaPoint(Vec2(max.x,max.y));

		_vertexData[9].texCoords = textureCoordFromAlphaPoint(Vec2(m_vTop.x,m_vTop.y));
		_vertexData[9].vertices = vertexFromAlphaPoint(Vec2(m_vTop.x,m_vTop.y));

		_vertexData[10].texCoords = textureCoordFromAlphaPoint(Vec2(pos,max.y));
		_vertexData[10].vertices = vertexFromAlphaPoint(Vec2(pos,max.y));

		_vertexData[11].texCoords = textureCoordFromAlphaPoint(Vec2(pos,m_vTop.y));
		_vertexData[11].vertices = vertexFromAlphaPoint(Vec2(pos,m_vTop.y));

	}
	else if (ProgressType::Circle1_1 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,m_vTop.y));

		for (int i = 10; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(pos,max.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(pos,max.y));
		}
	}
	else if (ProgressType::Circle1_2 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,pos));
		_vertexData[8].vertices = vertexFromAlphaPoint(Vec2(max.x,pos));

		for (int i = 9; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(m_vTop.x,m_vTop.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(m_vTop.x,m_vTop.y));
		}
	}
	else if (ProgressType::Step2 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,pos));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(m_vTop.x,pos));
		}
	}
	else if (ProgressType::Circle2_1 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,m_vOrigin.y));

		for (int i = 8; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(max.x,pos));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(max.x,pos));
		}
	}
	else if (ProgressType::Circle2_2 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,m_vOrigin.y));

		_vertexData[6].texCoords = textureCoordFromAlphaPoint(Vec2(pos,min.y));
		_vertexData[6].vertices = vertexFromAlphaPoint(Vec2(pos,min.y));

		for (int i = 7; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(m_vTop.x,m_vOrigin.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(m_vTop.x,m_vOrigin.y));
		}
	}
	else if (ProgressType::Step3 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,min.y));

		for (int i = 7; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(pos,m_vOrigin.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(pos,m_vOrigin.y));
		}
	}
	else if (ProgressType::Circle3_1 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,m_vOrigin.y));

		for (int i = 6; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(pos,min.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(pos,min.y));
		}
	}
	else if (ProgressType::Circle3_2 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,pos));
		_vertexData[4].vertices = vertexFromAlphaPoint(Vec2(min.x,pos));

		for (int i = 5; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(m_vOrigin.x,m_vOrigin.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(m_vOrigin.x,m_vOrigin.y));
		}
	}
	else if (ProgressType::Step4 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,pos));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(m_vOrigin.x,pos));
		}
	}
	else if (ProgressType::Circle4_1 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,m_vTop.y));

		for (int i = 4; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(min.x,pos));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(min.x,pos));
		}
	}
	else if (ProgressType::Circle4_2 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,m_vTop.y));

		_vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(pos,max.y));
		_vertexData[2].vertices = vertexFromAlphaPoint(Vec2(pos,max.y));

		for (int i = 3; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(m_vOrigin.x,m_vTop.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(m_vOrigin.x,m_vTop.y));
		}
	}
	else if (ProgressType::Step5 == step)
	{
		if (!_vertexData) {
			_vertexDataCount = 12;
			_vertexData = (V2F_C4B_T2F*)malloc(_vertexDataCount * sizeof(V2F_C4B_T2F));
			CCASSERT(_vertexData,max.y));

		for (int i = 3; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(pos,m_vTop.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(pos,m_vTop.y));
		}
	}
	else if (ProgressType::End == step)
	{
		for (int i = 0; i < _vertexDataCount; i++)
		{
			_vertexData[i].texCoords = textureCoordFromAlphaPoint(Vec2(min.x,min.y));
			_vertexData[i].vertices = vertexFromAlphaPoint(Vec2(min.x,min.y));
		}
	}
}

void MyProgressTimer::setOrigin(Vec2 _vOrigin)
{
	if (m_pSpr)
	{
		float topX = clampf(_vOrigin.x,0.5);
		float topY = clampf(_vOrigin.y,0.5);

		auto thisSize = m_pSpr->getContentSize();
		auto max1 = thisSize.width * topX;
		auto max2 = thisSize.height * topY;
		auto max3 = MAX(max1,max2);
		m_vOrigin = Vec2(max3 / thisSize.width,max3 / thisSize.height);

		updateProgress();
	}
}

void MyProgressTimer::setTop(Vec2 _vTop)
{
	if (m_pSpr)
	{
		float topX = clampf(_vTop.x,0.5,1);
		float topY = clampf(_vTop.y,1);

		auto thisSize = m_pSpr->getContentSize();
		auto max1 = thisSize.width * (1-topX);
		auto max2 = thisSize.height * (1-topY);
		auto max3 = MAX(max1,max2);
		m_vTop = Vec2(1- max3 / thisSize.width,1 - max3 / thisSize.height);

		updateProgress();
	}

}

MyProgressTimer::ProgressType MyProgressTimer::percentToStep(float &_pos)
{
	if (m_fPercentage == 0)
	{
		return ProgressType::Start;
	}
	else if (m_fPercentage == 100)
	{
		return ProgressType::End;
	}
	else if (m_fPercentage > 0 && m_fPercentage < 100)
	{
		auto thisSize = this->getContentSize();
		auto topR1 = thisSize.width * (1 - m_vTop.x);
		auto topR2 = thisSize.height * (1 - m_vTop.y);
		auto originR1 = thisSize.width * m_vOrigin.x;
		auto originR2 = thisSize.height * m_vOrigin.y;

		auto pi = 3.1415926f;

		float posNode[13] = {
			thisSize.width / 2 - topR1,thisSize.width / 2 - topR1 + pi*topR2 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1 + pi*originR2 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1 + pi*originR2 / 4 + pi*originR1 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1 + pi*originR2 / 4 + pi*originR1 / 4 + thisSize.height - originR2 - topR2,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1 + pi*originR2 / 4 + pi*originR1 / 4 + thisSize.height - originR2 - topR2 + pi*originR1 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1 + pi*originR2 / 4 + pi*originR1 / 4 + thisSize.height - originR2 - topR2 + pi*originR1 / 4 + pi*topR2 / 4,thisSize.width / 2 - topR1 + pi*topR1 / 4 + pi*topR2 / 4 + thisSize.height - topR2 - originR2 + pi*topR1 / 4 + pi*originR2 / 4 + thisSize.width - originR1 - topR1 + pi*originR2 / 4 + pi*originR1 / 4 + thisSize.height - originR2 - topR2 + pi*originR1 / 4 + pi*topR2 / 4 + thisSize.width / 2 - originR1
		};

		auto allLength = posNode[12];

		auto nowPosLength = allLength*m_fPercentage / 100;

		if (nowPosLength <= posNode[0])
		{
			_pos = (nowPosLength + thisSize.width / 2) / thisSize.width;

			if (_pos == 0.5f)
				return ProgressType::Start;
			return ProgressType::Step1;
		}
		else if (nowPosLength <= posNode[1])
		{
			auto huchang = nowPosLength - posNode[0];
			auto angle = huchang / topR2;
			_pos = (topR2 * tanf(angle) + thisSize.width - topR1) / thisSize.width;

			return ProgressType::Circle1_1;
		}
		else if (nowPosLength <= posNode[2])
		{
			auto huchang = pi*topR1 / 4 - (nowPosLength - posNode[1]);
			auto angle = huchang / topR1;
			_pos = (topR1 * tanf(angle) + thisSize.height - topR2) / thisSize.height;

			return ProgressType::Circle1_2;
		}
		else if (nowPosLength <= posNode[3])
		{
			_pos = 1 - (nowPosLength - posNode[2] + topR2) / thisSize.height;

			return ProgressType::Step2;
		}
		else if (nowPosLength <= posNode[4])
		{
			auto huchang = nowPosLength - posNode[3];
			auto angle = huchang / topR1;
			_pos = (originR2 - tanf(angle) * topR1) / thisSize.height;

			return ProgressType::Circle2_1;
		}
		else if (nowPosLength <= posNode[5])
		{
			auto huchang = pi*originR2 / 4 - (nowPosLength - posNode[4]);
			auto angle = huchang / originR2;
			_pos = (tanf(angle) * originR2 + thisSize.width - topR1) / thisSize.width;

			return ProgressType::Circle2_2;
		}
		else if (nowPosLength <= posNode[6])
		{
			auto nowPos = nowPosLength - posNode[5] + topR1;
			_pos = 1.0f - nowPos / thisSize.width;

			return ProgressType::Step3;
		}
		else if (nowPosLength < posNode[7])
		{
			auto huchang = nowPosLength - posNode[6];
			auto angle = huchang / originR2;
			_pos = (originR1 - tanf(angle) * originR2) / thisSize.width;

			return ProgressType::Circle3_1;
		}
		else if (nowPosLength < posNode[8])
		{
			auto huchang = pi*originR1 / 4 - (nowPosLength - posNode[7]);
			auto angle = huchang / originR1;
			_pos = (originR2 - tanf(angle) * originR2) / thisSize.height;

			return ProgressType::Circle3_2;
		}
		else if (nowPosLength < posNode[9])
		{
			auto huchang = nowPosLength - posNode[8] + originR2;
			_pos = huchang / thisSize.height;

			return ProgressType::Step4;
		}
		else if (nowPosLength < posNode[10])
		{
			auto huchang = (nowPosLength - posNode[9]);
			auto angle = huchang / originR1;
			_pos = (tanf(angle) * originR1 + thisSize.height - topR2) / thisSize.height;

			return ProgressType::Circle4_1;
		}
		else if (nowPosLength < posNode[11])
		{
			auto huchang = pi*topR2 / 4 - (nowPosLength - posNode[10]);
			auto angle = huchang / topR2;
			_pos = (originR1 - tanf(angle) * topR2) / thisSize.width;

			return ProgressType::Circle4_2;
		}
		else if (nowPosLength < posNode[12])
		{
			auto huchang = nowPosLength - posNode[11] + originR1;
			_pos = huchang / thisSize.width;

			return ProgressType::Step5;
		}
		return ProgressType::End;
	}

	return ProgressType::None;
}

MyProgressFromTo* MyProgressFromTo::create(float duration,float toPercentage)
{
	MyProgressFromTo *progressFromTo = new (std::nothrow) MyProgressFromTo();
	progressFromTo->initWithDuration(duration,fromPercentage,toPercentage);
	progressFromTo->autorelease();

	return progressFromTo;
}

MyProgressFromTo* MyProgressFromTo::clone() const
{
	auto a = new (std::nothrow) MyProgressFromTo();
	a->initWithDuration(_duration,_from,_to);
	a->autorelease();
	return a;
}

MyProgressFromTo* MyProgressFromTo::reverse() const
{
	return MyProgressFromTo::create(_duration,_to,_from);
}

void MyProgressFromTo::startWithTarget(Node *target)
{
	ActionInterval::startWithTarget(target);
}

void MyProgressFromTo::update(float time)
{
	((MyProgressTimer*)(_target))->setPercentage(_from + (_to - _from) * time);
}

bool MyProgressFromTo::initWithDuration(float duration,float toPercentage)
{
	if (ActionInterval::initWithDuration(duration))
	{
		_to = toPercentage;
		_from = fromPercentage;

		return true;
	}

	return false;
}
其中这个函数percentToStep(),这个算法我写吐了!不知道你们看的懂不!

原理: 就是我把整个图片分成9个部分,两个竖边,一个下边,一个左上边和右上边还有四个弧度。


分割则是靠两个红点(代码中的m_vOrigin,m_vTop)这样就显示黑色区域!!!

调用方法

	MyProgressTimer* progressTimer = MyProgressTimer::create(Sprite::create("thinking_border.png"));
	progressTimer->setPosition(Vec2(winSize.width / 2-100,winSize.height*0.5));
	this->addChild(progressTimer);
	progressTimer->setOrigin(Vec2(0.08,0.08));
	progressTimer->setTop(Vec2(0.92,0.92));

	progressTimer->stopAllActions();
	progressTimer->runAction(Sequence::create(
		MyProgressFromTo::create(15.0f,100),CallFunc::create([&](){
		CCLOG("CallFunc: end!");
	}),nullptr));
以上版本是cocos2dx3.2版本的,代码直接复制黏贴即可!之前我给一个朋友弄个2.2.1版本的,以下是2dx-2.2.1版本的下载链接

点击打开链接

写的有点复杂,大家可以自己去看看,可能你会发现更好的解决方式,到时候告诉我哦!
你的支持是我学习的动力!!!


等过一阵子,我会写老虎机的实现方式!!!预告一下!

猜你在找的Cocos2d-x相关文章