//好久没写博客,本人比较懒,而且没啥技术,所以。。。
进度条,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版本的下载链接:
写的有点复杂,大家可以自己去看看,可能你会发现更好的解决方式,到时候告诉我哦!
你的支持是我学习的动力!!!
等过一阵子,我会写老虎机的实现方式!!!预告一下!