今天我們來學習一下這些動畫。
主要是涉及到以下幾個文件:
CCGrid.h /cpp :網格數據及渲染,包括基本網格數據和3D網格數據,這是數據的基礎。
CCActionGrid.h /cpp :網格基本動畫,這是動畫的基礎。
CCActionGrid3D.h/cpp: 3D網格基本動畫,這是3D網格動畫的基礎。
CCActionTiledGrid.h / cpp :網格衍生動畫,這是最終的特效實現。
咱們首先來看 關於網格數據及渲染的文件:CCGrid.h
#ifndef __EFFECTS_CCGRID_H__ #define __EFFECTS_CCGRID_H__ #include "cocoa/CCObject.h" #include "base_nodes/CCNode.h" #include "CCCamera.h" #include "ccTypes.h" #include "textures/CCTexture2D.h" #include "CCDirector.h" #include "kazmath/mat4.h" //使用Cocos2d命名空間 NS_CC_BEGIN //當前.h文件要用到以下三個類的指針。 class CCTexture2D; class CCGrabber; class CCGLProgram; //網格基類。由CCObject派生。 class CC_DLL CCGridBase : public CCObject { public: //析構 virtual ~CCGridBase(void); //是否激活狀態。 inline bool isActive(void) { return m_bActive; } //設置為激活狀態。 void setActive(bool bActive); //取得 inline int getReuseGrid(void) { return m_nReuseGrid; } inline void setReuseGrid(int nReuseGrid) { m_nReuseGrid = nReuseGrid; } //取得網格的大小。 inline const ccGridSize& getGridSize(void) { return m_sGridSize; } //設置網格的大小。 inline void setGridSize(const ccGridSize& gridSize) { m_sGridSize = gridSize; } //取得每個格子佔用的圖像點數。即圖像大於與格子大小的比值。 inline const CCPoint& getStep(void) { return m_obStep; } inline void setStep(const CCPoint& step) { m_obStep = step; } //取得紋理是否上下反轉 inline bool isTextureFlipped(void) { return m_bIsTextureFlipped; } //設置紋理是否上下反轉。 void setTextureFlipped(bool bFlipped); //初始化網格,參一為網格大小,參二為對應的紋理,參三為設置紋理是否反轉。 bool initWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped); ////初始化網格,參數為網格大小。 bool initWithSize(const ccGridSize& gridSize); //在渲染之前要做的處理。 void beforeDraw(void); //在渲染之後要做的處理。 void afterDraw(CCNode *pTarget); //渲染處理 virtual void blit(void); //還原到原頂點位置 virtual void reuse(void); //計算頂點緩衝 virtual void calculateVertexPoints(void); public: //詳細創建函數,參一為網格大小,參二為對應的紋理,參三為設置紋理是否反轉。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCGridBase* gridWithSize(const ccGridSize& gridSize, CCTexture2D *texture, bool flipped); //簡單創建函數,參數為網格大小。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCGridBase* gridWithSize(const ccGridSize& gridSize); //對應詳細創建函數的create實現。 static CCGridBase* create(const ccGridSize& gridSize, CCTexture2D *texture, bool flipped); //對應簡單創建函數的create實現。 static CCGridBase* create(const ccGridSize& gridSize); //設置2D投影矩陣。 void set2DProjection(void); protected: //是否被激活。 bool m_bActive; int m_nReuseGrid; //格子大小 ccGridSize m_sGridSize; //所用紋理 CCTexture2D *m_pTexture; //每格的圖像點數 CCPoint m_obStep; //將屏幕畫面渲染到紋理的處理器。 CCGrabber *m_pGrabber; //紋理是否上下反轉。 bool m_bIsTextureFlipped; //Shader代碼片段指針。 CCGLProgram* m_pShaderProgram; //投影方式 ccDirectorProjection m_directorProjection; }; 對應CPP: //簡單創建函數,參一為網格大小,參二為對應的紋理,參三為設置紋理是否反轉。內部調用create實現。CCGridBase* CCGridBase::gridWithSize(const ccGridSize& gridSize) { return CCGridBase::create(gridSize); } //對應簡單創建函數的create實現。 CCGridBase* CCGridBase::create(const ccGridSize& gridSize) { //先new出一個當前類實例。 CCGridBase *pGridBase = new CCGridBase(); //如果成功 if (pGridBase) { //進行初始化。 if (pGridBase->initWithSize(gridSize)) { //如果初始化成功交由內存管理器進行管理。 pGridBase->autorelease(); } else { //如果失敗釋放並置空。 CC_SAFE_RELEASE_NULL(pGridBase); } } //如果成功返回創建的類實例,否則反回NULL。 return pGridBase; } //詳細創建函數,參數為網格大小。內部調用create實現。 CCGridBase* CCGridBase::gridWithSize(const ccGridSize& gridSize, CCTexture2D *texture, bool flipped) { return CCGridBase::create(gridSize, texture, flipped); } //對應詳細創建函數的create實現。 CCGridBase* CCGridBase::create(const ccGridSize& gridSize, CCTexture2D *texture, bool flipped) { //先new出一個當前類實例。 CCGridBase *pGridBase = new CCGridBase(); //如果成功 if (pGridBase) { //進行初始化。 if (pGridBase->initWithSize(gridSize, texture, flipped)) { //如果初始化成功交由內存管理器進行管理。 pGridBase->autorelease(); } else { //如果失敗釋放並置空。 CC_SAFE_RELEASE_NULL(pGridBase); } } //如果成功返回創建的類實例,否則反回NULL。 return pGridBase; } //初始化函數。 bool CCGridBase::initWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped) { bool bRet = true; //未激活。 m_bActive = false; m_nReuseGrid = 0; //保存格子大小。 m_sGridSize = gridSize; //保存紋理。 m_pTexture = pTexture; //佔用紋理,對其引用計數器加一操作。 CC_SAFE_RETAIN(m_pTexture); //保存是否進行紋理反轉的變數。 m_bIsTextureFlipped = bFlipped; //取得紋理中的圖像大小。 const CCSize& texSize = m_pTexture->getContentSize(); //計算出一個格子所佔的紋理定址長度。 m_obStep.x = texSize.width / m_sGridSize.x; m_obStep.y = texSize.height / m_sGridSize.y; //新建一個屏幕圖像獲取器,這傢伙是幹嘛的?其實就是一個獲取屏幕圖像的類,可以將屏幕上渲染出的圖像輸出到一張指定的紋理中,類似DX中的RTT。 m_pGrabber = new CCGrabber(); if (m_pGrabber) { //將紋理設置為輸出紋理。 m_pGrabber->grab(m_pTexture); } else { //如果圖像獲取器創建失敗,做下返回值處理。 bRet = false; } //取得對應的Shader代碼片段。 m_pShaderProgram = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTexture); //計算所要用到的頂點數據並創建頂點緩衝區。 calculateVertexPoints(); return bRet; } //初始化。 bool CCGridBase::initWithSize(const ccGridSize& gridSize) { //取得設備指針,並通過它取得屏幕大小。 CCDirector *pDirector = CCDirector::sharedDirector(); CCSize s = pDirector->getWinSizeInPixels(); //計算相應大小對應的2次冪大小。 unsigned long POTWide = ccNextPOT((unsigned int)s.width); unsigned long POTHigh = ccNextPOT((unsigned int)s.height); // 使用ARGB8888格式。 CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888; //創建相應的像素繪沖區。 void *data = calloc((int)(POTWide * POTHigh * 4), 1); if (! data) { CCLOG("cocos2d: CCGrid: not enough memory."); this->release(); return false; } //創建一個紋理。 CCTexture2D *pTexture = new CCTexture2D(); //使用像素數據初始化紋理。 pTexture->initWithData(data, format, POTWide, POTHigh, s); //釋放像素數據。 free(data); //如果失敗,返回false。 if (! pTexture) { CCLOG("cocos2d: CCGrid: error creating texture"); delete this; return false; } //使用創建的紋理初始化 initWithSize(gridSize, pTexture, false); //釋放紋理。 pTexture->release(); return true; } //析構。 CCGridBase::~CCGridBase(void) { CCLOGINFO("cocos2d: deallocing %p", this); //釋放紋理。 CC_SAFE_RELEASE(m_pTexture); //釋放屏幕 CC_SAFE_RELEASE(m_pGrabber); } //設置激活。 void CCGridBase::setActive(bool bActive) { //保存激活設置 m_bActive = bActive; if (! bActive) { //如果未激活,復原投影矩陣。 CCDirector *pDirector = CCDirector::sharedDirector(); ccDirectorProjection proj = pDirector->getProjection(); pDirector->setProjection(proj); } } //設置紋理反轉。 void CCGridBase::setTextureFlipped(bool bFlipped) { //如果參數與原設置不同,更新設置並計算頂點緩衝。 if (m_bIsTextureFlipped != bFlipped) { m_bIsTextureFlipped = bFlipped; calculateVertexPoints(); } } //設置2D投影。 void CCGridBase::set2DProjection() { //取得窗口大小 CCDirector *director = CCDirector::sharedDirector(); CCSize size = director->getWinSizeInPixels(); //重新設置視口大小 glViewport(0, 0, (GLsizei)(size.width * CC_CONTENT_SCALE_FACTOR()), (GLsizei)(size.height * CC_CONTENT_SCALE_FACTOR()) ); //開始設置投影矩陣。 kmGLMatrixMode(KM_GL_PROJECTION); //先將投影矩陣單位化。 kmGLLoadIdentity(); //創建一個矩陣變數。 kmMat4 orthoMatrix; //通過參數生成出投影矩陣變數的值,此處使用的是正交投影矩陣。 kmMat4OrthographicProjection(&orthoMatrix, 0, size.width * CC_CONTENT_SCALE_FACTOR(), 0, size.height * CC_CONTENT_SCALE_FACTOR(), -1, 1); //將原單位化矩陣與正交投影矩陣相乘,當然還是正交投影矩陣了,做為投影矩陣的結果。 kmGLMultMatrix( &orthoMatrix ); //下面開始設置模型觀察矩陣。 kmGLMatrixMode(KM_GL_MODELVIEW); //將矩陣單位化。 kmGLLoadIdentity(); //設置投影矩陣。 ccSetProjectionMatrixDirty(); } //在開始渲染前的處理。 void CCGridBase::beforeDraw(void) { // 先取得當前的投影矩陣保存到變數中 CCDirector *director = CCDirector::sharedDirector(); m_directorProjection = director->getProjection(); // 設置新的投影矩陣。 set2DProjection(); // 設置開啟屏幕渲染到紋理。 m_pGrabber->beforeRender(m_pTexture); } //在渲染結束后的處理。 void CCGridBase::afterDraw(cocos2d::CCNode *pTarget) { //設置完成屏幕渲染到紋理。 m_pGrabber->afterRender(m_pTexture); //恢復原投影矩陣。 CCDirector *director = CCDirector::sharedDirector(); director->setProjection(m_directorProjection); // if (pTarget->getCamera()->isDirty()) { //取得演示的錨點做為攝像機的矩陣轉換中心點。 const CCPoint& offset = pTarget->getAnchorPointInPoints(); //注意:下面三句的意義是對攝像機進行矩陣變換,這個矩陣變換是相對於自身中心點位置,俗稱自身矩陣變換。 //先將當前模型矩陣偏移到這個中心點。 kmGLTranslatef(offset.x, offset.y, 0); //進行本地矩陣的轉換 pTarget->getCamera()->locate(); //恢復原位置。 kmGLTranslatef(-offset.x, -offset.y, 0); } //設置使用紋理。 ccGLBindTexture2D(m_pTexture->getName()); // restore projection for default FBO .fixed bug #543 #544 //TODO: CCDirector::sharedDirector()->setProjection(CCDirector::sharedDirector()->getProjection()); //TODO: CCDirector::sharedDirector()->applyOrientation(); //進行渲染 blit(); } //進行渲染 void CCGridBase::blit(void) { CCAssert(0, ""); } //還原到原來頂點位置。 void CCGridBase::reuse(void) { CCAssert(0, ""); } //計算頂點緩衝區。 void CCGridBase::calculateVertexPoints(void) { CCAssert(0, ""); } //3D網格類,派生於格子基類, class CC_DLL CCGrid3D : public CCGridBase { public: //構造 CCGrid3D(); //析構 ~CCGrid3D(void); //返回對應位置的頂點。 ccVertex3F vertex(const ccGridSize& pos); //返回對應位置的原始頂點。 ccVertex3F originalVertex(const ccGridSize& pos); //設置對應位置的頂點。 void setVertex(const ccGridSize& pos, const ccVertex3F& vertex); //重載基類的函數。 //渲染。 virtual void blit(void); //還原到原來頂點位置 virtual void reuse(void); //計算頂點緩衝。 virtual void calculateVertexPoints(void); public: //靜態函數:詳細參數的創建3D網格,參一為格子大小,參二為紋理指針,參三為是否進行紋理反轉,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCGrid3D* gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped); //靜態函數:簡單參數的創建3D網格,參數為格子大小,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCGrid3D* gridWithSize(const ccGridSize& gridSize); //詳細參數的創建3D網格 static CCGrid3D* create(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped); //簡單參數的創建3D網格 static CCGrid3D* create(const ccGridSize& gridSize); protected: //頂點緩衝指針_紋理UV GLvoid *m_pTexCoordinates; //頂點緩衝指針_位置 GLvoid *m_pVertices; //原始頂點緩衝指針_位置 GLvoid *m_pOriginalVertices; //索引緩衝指針 GLushort *m_pIndices; }; 對應CPP: //靜態函數:詳細參數的創建3D網格,參一為格子大小,參二為紋理指針,參三為是否進行紋理反轉,內部調用create實現。 CCGrid3D* CCGrid3D::gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped) { return CCGrid3D::create(gridSize, pTexture, bFlipped); } //上面的create實現 CCGrid3D* CCGrid3D::create(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped) { //先new出一個當前類實例 CCGrid3D *pRet= new CCGrid3D(); //如果成功 if (pRet) { //初始化並交由內存管理器進行引用計數器的管理 if (pRet->initWithSize(gridSize, pTexture, bFlipped)) { pRet->autorelease(); } else { //如果失敗,則釋放並置空。 delete pRet; pRet = NULL; } } //返回結果。 return pRet; } //簡單參數的創建3D網格,內部調用create實現。 CCGrid3D* CCGrid3D::gridWithSize(const ccGridSize& gridSize) { return CCGrid3D::create(gridSize); } //上面函數的create實現。 CCGrid3D* CCGrid3D::create(const ccGridSize& gridSize) { //先new出一個當前類實例 CCGrid3D *pRet= new CCGrid3D(); //如果成功 if (pRet) { //初始化並交由內存管理器進行引用計數器的管理 if (pRet->initWithSize(gridSize)) { pRet->autorelease(); } else { //如果失敗,則釋放並置空。 delete pRet; pRet = NULL; } } //返回結果。 return pRet; } //構造 CCGrid3D::CCGrid3D() : m_pTexCoordinates(NULL) , m_pVertices(NULL) , m_pOriginalVertices(NULL) , m_pIndices(NULL) { } //析構 CCGrid3D::~CCGrid3D(void) { //釋放各緩衝區 CC_SAFE_FREE(m_pTexCoordinates); CC_SAFE_FREE(m_pVertices); CC_SAFE_FREE(m_pIndices); CC_SAFE_FREE(m_pOriginalVertices); } //進行渲染處理 void CCGrid3D::blit(void) { //計算格子的數量 int n = m_sGridSize.x * m_sGridSize.y; //設置渲染頂點的格式 ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); //開啟使用Shader m_pShaderProgram->use(); //設置Shader中的 頂點矩陣,其值 = 投影矩陣X模型矩陣X觀察矩陣的結果,用於在Shader中進行頂點的最終位置計算。 m_pShaderProgram->setUniformForModelViewProjectionMatrix();; //頂點緩衝中位置屬性的指定。 glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, m_pVertices); //頂點緩衝中紋理貼圖UV屬性的指定。 glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, m_pTexCoordinates); //繪製三角形,每個格子兩個三角形,使用GL_TRIANGLES方式進行繪製,則每個格子需要6個頂點。所以頂點數為n*6,渲染時按照索引繪沖m_pIndices所指定的三角形頂點索引來進行繪製。 glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, m_pIndices); //增加一次DP統計值。 CC_INCREMENT_GL_DRAWS(1); } //計算頂點緩衝數據 void CCGrid3D::calculateVertexPoints(void) { //取得紋理的寬高。 float width = (float)m_pTexture->getPixelsWide(); float height = (float)m_pTexture->getPixelsHigh(); //取得紋理中圖像區域的高度。 float imageH = m_pTexture->getContentSizeInPixels().height; //定義臨時變數。 int x, y, i; //如果相應的頂點緩衝數據有值,先釋放乾淨並置空。 CC_SAFE_FREE(m_pVertices); CC_SAFE_FREE(m_pOriginalVertices); CC_SAFE_FREE(m_pTexCoordinates); CC_SAFE_FREE(m_pIndices); //計算總頂點數,每一行的頂點數為格子列數+1,每一列的頂點數為格子行數+1。 unsigned int numOfPoints = (m_sGridSize.x+1) * (m_sGridSize.y+1); //為相應的頂點緩衝區申請相應大小的內存。 //m_pVertices中存入的是頂點位置,使用ccVertex3F來存儲。所申請的內存大小即為頂點數乘以ccVertex3F的位元組數大小。 m_pVertices = malloc(numOfPoints * sizeof(ccVertex3F)); //同上。 m_pOriginalVertices = malloc(numOfPoints * sizeof(ccVertex3F)); //紋理UV使用ccVertex2F來存儲。 m_pTexCoordinates = malloc(numOfPoints * sizeof(ccVertex2F)); //索引緩衝m_pIndices使用GLushort來存儲繪製三角形所用的頂點的索引值,因為每個面3個索引,一個格子就需要6個索引。 m_pIndices = (GLushort*)malloc(m_sGridSize.x * m_sGridSize.y * sizeof(GLushort) * 6); //為了方便填充數據,將緩衝區地址轉換成相應的指針變數。 GLfloat *vertArray = (GLfloat*)m_pVertices; GLfloat *texArray = (GLfloat*)m_pTexCoordinates; GLushort *idxArray = m_pIndices; //雙循環遍歷每個格子。 for (x = 0; x < m_sGridSize.x; ++x) { for (y = 0; y < m_sGridSize.y; ++y) { //取得格子索引。 int idx = (y * m_sGridSize.x) + x; //取得格子的左上角和右下角在圖像中的相應位置。m_obStep是每個格子佔用的圖像點數。 GLfloat x1 = x * m_obStep.x; GLfloat x2 = x1 + m_obStep.x; GLfloat y1 = y * m_obStep.y; GLfloat y2= y1 + m_obStep.y; //取得格子的四個頂點的索引。 GLushort a = (GLushort)(x * (m_sGridSize.y + 1) + y); GLushort b = (GLushort)((x + 1) * (m_sGridSize.y + 1) + y); GLushort c = (GLushort)((x + 1) * (m_sGridSize.y + 1) + (y + 1)); GLushort d = (GLushort)(x * (m_sGridSize.y + 1) + (y + 1)); //按照三角形的繪製方式將格子頂點的索引組成兩個三角形的頂點索引。 GLushort tempidx[6] = {a, b, d, b, c, d}; //填充到相應的索引緩衝中。 memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort)); //格子四個頂點的位置。 int l1[4] = {a*3, b*3, c*3, d*3}; ccVertex3F e = {x1, y1, 0}; ccVertex3F f = {x2, y1, 0}; ccVertex3F g = {x2, y2, 0}; ccVertex3F h = {x1, y2, 0}; ccVertex3F l2[4] = {e, f, g, h}; int tex1[4] = {a*2, b*2, c*2, d*2}; CCPoint tex2[4] = {ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2)}; //遍歷放入相應的頂點位置和紋理UV中。 for (i = 0; i < 4; ++i) { //頂點的x,y,z vertArray[l1[i]] = l2[i].x; vertArray[l1[i] + 1] = l2[i].y; vertArray[l1[i] + 2] = l2[i].z; //紋理U值 texArray[tex1[i]] = tex2[i].x / width; //紋理V值 if (m_bIsTextureFlipped) { //上下反轉 texArray[tex1[i] + 1] = (imageH - tex2[i].y) / height; } else { //正常 texArray[tex1[i] + 1] = tex2[i].y / height; } } } } //將頂點位置數據填充到保存原始頂點位置的內存中。 memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F)); } //返回對應網格位置的頂點。 ccVertex3F CCGrid3D::vertex(const ccGridSize& pos) { //通過網格位置計算出起始頂點的索引。 int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3; //為方便獲取頂點數據,將頂點緩衝地址轉換為相應的指針變數。 float *vertArray = (float*)m_pVertices; //通過索引取得相應的頂點x,y,z。 ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]}; //返回頂點 return vert; } //返回網格對應位置的原始頂點。 ccVertex3F CCGrid3D::originalVertex(const ccGridSize& pos) { //通過格子位置計算出起始頂點的索引。 int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3; //為方便獲取頂點數據,將頂點緩衝地址轉換為相應的指針變數。 float *vertArray = (float*)m_pOriginalVertices; //通過索引取得相應的頂點x,y,z。 ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]}; //返回頂點 return vert; } //設置對應網格位置的頂點。 void CCGrid3D::setVertex(const ccGridSize& pos, const ccVertex3F& vertex) { //通過格子位置計算出起始頂點的索引。 int index = (pos.x * (m_sGridSize.y + 1) + pos.y) * 3; //為方便獲取頂點數據,將頂點緩衝地址轉換為相應的指針變數。 float *vertArray = (float*)m_pVertices; 設置對應索引位置的頂點的x,y,z。 vertArray[index] = vertex.x; vertArray[index+1] = vertex.y; vertArray[index+2] = vertex.z; } //還原原來位置。 void CCGrid3D::reuse(void) { //如果還原格子的變數大於0。 if (m_nReuseGrid > 0) { //將原始頂點位置拷貝到頂點緩衝中。 memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F)); //還原格子的變數做減1操作。 --m_nReuseGrid; } } //這也是一個網格類,但它在網格的每個位置點存的不是一個頂點,而是一個四邊形格子。 class CC_DLL CCTiledGrid3D : public CCGridBase { public: //構造 CCTiledGrid3D(); //析構 ~CCTiledGrid3D(void); //返回相應位置的格子數據 ccQuad3 tile(const ccGridSize& pos); //返回原始位置的格子數據。 ccQuad3 originalTile(const ccGridSize& pos); //設置相應位置的格子數據。 void setTile(const ccGridSize& pos, const ccQuad3& coords); //重載相應基類函數。 virtual void blit(void); virtual void reuse(void); virtual void calculateVertexPoints(void); public: //靜態函數:創建一個當前類的實例。參一為格子大小,參二為對應的紋理,參三為是否進行紋理反轉。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCTiledGrid3D* gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped); //上面函數的簡化版本。 CC_DEPRECATED_ATTRIBUTE static CCTiledGrid3D* gridWithSize(const ccGridSize& gridSize); //對應創建函數的實現。 static CCTiledGrid3D* create(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped); //對應創建函數的實現。 static CCTiledGrid3D* create(const ccGridSize& gridSize); protected: //所要用到的頂點數據緩衝區。 GLvoid *m_pTexCoordinates; GLvoid *m_pVertices; GLvoid *m_pOriginalVertices; GLushort *m_pIndices; }; 對應CPP: //構造函數。 CCTiledGrid3D::CCTiledGrid3D() : m_pTexCoordinates(NULL) , m_pVertices(NULL) , m_pOriginalVertices(NULL) , m_pIndices(NULL) { } //析構函數。 CCTiledGrid3D::~CCTiledGrid3D(void) { //釋放各頂點所用的數據緩衝區。 CC_SAFE_FREE(m_pTexCoordinates); CC_SAFE_FREE(m_pVertices); CC_SAFE_FREE(m_pOriginalVertices); CC_SAFE_FREE(m_pIndices); } //靜態函數:創建一個當前類的實例。參一為格子大小,參二為對應的紋理,參三為是否進行紋理反轉。內部調用create實現。 CCTiledGrid3D* CCTiledGrid3D::gridWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped) { return CCTiledGrid3D::create(gridSize, pTexture, bFlipped); } //上面函數的具體實現。 CCTiledGrid3D* CCTiledGrid3D::create(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped) { //先用new創建一個當前類的實例。 CCTiledGrid3D *pRet= new CCTiledGrid3D(); //如果成功。 if (pRet) { //進行初始化並交由內存管理器進行引用計數器的管理。 if (pRet->initWithSize(gridSize, pTexture, bFlipped)) { pRet->autorelease(); } else { //如果失敗,釋放new出來的實例指針並置空。 delete pRet; pRet = NULL; } } //返回實例指針。 return pRet; } //靜態函數:創建一個當前類的實例。簡化版本。 CCTiledGrid3D* CCTiledGrid3D::gridWithSize(const ccGridSize& gridSize) { return CCTiledGrid3D::create(gridSize); } //上面函數的具體實現。 CCTiledGrid3D* CCTiledGrid3D::create(const ccGridSize& gridSize) { //先用new創建一個當前類的實例。 CCTiledGrid3D *pRet= new CCTiledGrid3D(); if (pRet) { /進行初始化並交由內存管理器進行引用計數器的管理。 if (pRet->initWithSize(gridSize)) { pRet->autorelease(); } else { //如果失敗,釋放new出來的實例指針並置空。 delete pRet; pRet = NULL; } } //返回實例指針。 return pRet; } //實際渲染處理。 void CCTiledGrid3D::blit(void) { //取得格子的數量。 int n = m_sGridSize.x * m_sGridSize.y; //開啟使用shader片段 m_pShaderProgram->use(); //設置Shader中的 頂點矩陣,其值 = 投影矩陣X模型矩陣X觀察矩陣的結果,用於在Shader中進行頂點的最終位置計算。 m_pShaderProgram->setUniformForModelViewProjectionMatrix(); //設置頂點緩衝的結構,由位置和紋理坐構構成。 ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); //頂點緩衝中位置屬性的指定 glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, m_pVertices); //紋理坐標通道 glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, m_pTexCoordinates); //繪製圖形 glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, m_pIndices); //更新DP統計 CC_INCREMENT_GL_DRAWS(1); } //計算頂點緩衝的數據 void CCTiledGrid3D::calculateVertexPoints(void) { //取得紋理的寬高 float width = (float)m_pTexture->getPixelsWide(); float height = (float)m_pTexture->getPixelsHigh(); //取得紋理中圖像區域的高度。 float imageH = m_pTexture->getContentSizeInPixels().height; //定義臨時變數。 int numQuads = m_sGridSize.x * m_sGridSize.y; //如果相應的頂點緩衝數據有值,先釋放乾淨並置空。 CC_SAFE_FREE(m_pVertices); CC_SAFE_FREE(m_pOriginalVertices); CC_SAFE_FREE(m_pTexCoordinates); CC_SAFE_FREE(m_pIndices); //為相應的頂點緩衝區申請相應大小的內存。 m_pVertices = malloc(numQuads*4*sizeof(ccVertex3F)); m_pOriginalVertices = malloc(numQuads*4*sizeof(ccVertex3F)); m_pTexCoordinates = malloc(numQuads*4*sizeof(ccVertex2F)); m_pIndices = (GLushort*)malloc(numQuads*6*sizeof(GLushort)); //為了方便填充數據,將緩衝區地址轉換成相應的指針變數。 GLfloat *vertArray = (GLfloat*)m_pVertices; GLfloat *texArray = (GLfloat*)m_pTexCoordinates; GLushort *idxArray = m_pIndices; int x, y; //雙循環遍歷每個格子。 for (x = 0; x < m_sGridSize.x; ++x) { for (y = 0; y < m_sGridSize.y; ++y) { //取得格子的左上角和右下角在圖像中的位置。 float x1 = x * m_obStep.x; float x2 = x1 + m_obStep.x; float y1 = y * m_obStep.y; float y2 = y1 + m_obStep.y; //填充數據 *vertArray++ = x1; *vertArray++ = y1; *vertArray++ = 0; *vertArray++ = x2; *vertArray++ = y1; *vertArray++ = 0; *vertArray++ = x1; *vertArray++ = y2; *vertArray++ = 0; *vertArray++ = x2; *vertArray++ = y2; *vertArray++ = 0; float newY1 = y1; float newY2 = y2; //如果紋理V值上下反轉,則做下處理。 if (m_bIsTextureFlipped) { newY1 = imageH - y1; newY2 = imageH - y2; } //填充數據。 *texArray++ = x1 / width; *texArray++ = newY1 / height; *texArray++ = x2 / width; *texArray++ = newY1 / height; *texArray++ = x1 / width; *texArray++ = newY2 / height; *texArray++ = x2 / width; *texArray++ = newY2 / height; } } //索引緩衝數據填充。 for (x = 0; x < numQuads; x++) { idxArray[x*6+0] = (GLushort)(x * 4 + 0); idxArray[x*6+1] = (GLushort)(x * 4 + 1); idxArray[x*6+2] = (GLushort)(x * 4 + 2); idxArray[x*6+3] = (GLushort)(x * 4 + 1); idxArray[x*6+4] = (GLushort)(x * 4 + 2); idxArray[x*6+5] = (GLushort)(x * 4 + 3); } //填充原始位置頂點緩衝 memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat)); } //設置相應位置的格子數據。 void CCTiledGrid3D::setTile(const ccGridSize& pos, const ccQuad3& coords) { //先計算出對應格子的頂點索引 int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3; //為了方便填充數據,將緩衝區地址轉換成相應的指針變數。 float *vertArray = (float*)m_pVertices; //填充對應的數據 memcpy(&vertArray[idx], &coords, sizeof(ccQuad3)); } //返回原始位置的格子數據。 ccQuad3 CCTiledGrid3D::originalTile(const ccGridSize& pos) { //先計算出對應格子的頂點索引 int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3; //為了方便取得數據,將緩衝區地址轉換成相應的指針變數。 float *vertArray = (float*)m_pOriginalVertices; //定義變數值做為返回結果。 ccQuad3 ret; //由索引取得數據填充到返回值中。 memcpy(&ret, &vertArray[idx], sizeof(ccQuad3)); return ret; } //返回相應位置的格子數據 ccQuad3 CCTiledGrid3D::tile(const ccGridSize& pos) { //先計算出對應格子的頂點索引 int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3; //為了方便取得數據,將緩衝區地址轉換成相應的指針變數。 float *vertArray = (float*)m_pVertices; //定義變數值做為返回結果。 ccQuad3 ret; //由索引取得數據填充到返回值中。 memcpy(&ret, &vertArray[idx], sizeof(ccQuad3)); return ret; } //恢復為原始頂點 void CCTiledGrid3D::reuse(void) { //如果還原格子的變數大於0。 if (m_nReuseGrid > 0) { int numQuads = m_sGridSize.x * m_sGridSize.y; //將原始頂點位置拷貝到頂點緩衝中。 memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat)); //還原格子的變數做減1操作。 --m_nReuseGrid; } }
上面講的是網格的的數據和渲染基類CCGridBase及其派生CCGrid3D和CCTiledGrid3D,CCGridBase的關鍵是處理了將屏幕渲染到紋理這個功能。
它有兩個重要的函數:
//在渲染之前要做的處理。
voidbeforeDraw(void);
//在渲染之後要做的處理。
voidafterDraw(CCNode *pTarget);
我們來看一下這兩個函數是在哪裡調用的。
經過搜索,我們可以在CCNode.h中發現這一句:
/** A CCGrid object that is used when applying effects */
CC_PROPERTY(CCGridBase *, m_pGrid, Grid)
即每個CCNode有一個CCGridBase類型的成員指針變數。在其cpp的visit中發現了要找的東西。
void CCNode::visit() { if (!m_bIsVisible) { return; } kmGLPushMatrix(); //如果m_pGrid有值並且被激活則開啟渲染到紋理。 if (m_pGrid && m_pGrid->isActive()) { m_pGrid->beforeDraw(); } //相應結點的渲染處理。 … //如果m_pGrid有值並且被激活則關閉渲染到紋理,這樣當前結點上所有繪製的圖像都被輸出到m_pGrid中對應的紋理中了。 if (m_pGrid && m_pGrid->isActive()) { m_pGrid->afterDraw(this); } kmGLPopMatrix(); }
而CCGrid3D是一個基本的網格渲染類,他內部有所需要的頂點緩衝區。可以實現帶紋理貼圖的網格渲染功能。
CCTiledGrid3D比較有趣,它與CCGrid3D的不同之處是它的網格不是由一個個頂點構成,而是由一個個四邊形構成,CCGrid3D所表現的是網格各頂點的動畫,而CCTiledGrid3D是表現每個格子中的四邊形的動畫。
OK,下面我們來看一下操控網格數據表現一些基本動畫的類。
打開CCActionGrid.h: #ifndef __ACTION_CCGRID_ACTION_H__ #define __ACTION_CCGRID_ACTION_H__ #include "CCActionInterval.h" #include "CCActionInstant.h" //使用Cocos2d命名空間 NS_CC_BEGIN //用到CCGridBase類的指針。 class CCGridBase; //網格動畫基類 class CC_DLL CCGridAction : public CCActionInterval { public: //產生一個當前類的實例拷貝 virtual CCObject* copyWithZone(CCZone* pZone); //設定演示當前動畫的演員。 virtual void startWithTarget(CCNode *pTarget); //創建一個反向播放的動畫。 virtual CCActionInterval* reverse(void); //初始化網格的大小和動畫的時長。 virtual bool initWithSize(const ccGridSize& gridSize, float duration); //返回網格 virtual CCGridBase* getGrid(void); public: //靜態創建函數。參數一為格子大小,參數二為動畫時長,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCGridAction* actionWithSize(const ccGridSize& gridSize, float duration); //同上 static CCGridAction* create(const ccGridSize& gridSize, float duration); protected: //格子大小。 ccGridSize m_sGridSize; }; 對應CPP: //靜態創建函數。參數一為格子大小,參數二為動畫時長,內部調用create實現。 CCGridAction* CCGridAction::actionWithSize(const ccGridSize& gridSize, float duration) { return CCGridAction::create(gridSize, duration); } //同上 CCGridAction* CCGridAction::create(const ccGridSize& gridSize, float duration) { //先new出一個CCGridAction CCGridAction *pAction = new CCGridAction(); if (pAction) { //初始化並放入內存管理器中。 if (pAction->initWithSize(gridSize, duration)) { pAction->autorelease(); } else { //如果初始化失敗,釋放並置空。 CC_SAFE_DELETE(pAction); } } //返回創建的實例指針,當然,也可能返回NULL。 return pAction; } //初始化函數。 bool CCGridAction::initWithSize(const ccGridSize& gridSize, float duration) { //調用時間動畫基類的初始化函數保存動畫時長。 if (CCActionInterval::initWithDuration(duration)) { //保存格子大小。 m_sGridSize = gridSize; return true; } return false; } //設置演示當前動畫的演員,注意這個演員是什麼?不是精靈,而是 void CCGridAction::startWithTarget(CCNode *pTarget) { //調用時間動畫基類的相應函數。 CCActionInterval::startWithTarget(pTarget); //取得網格數據類。 CCGridBase *newgrid = this->getGrid(); CCNode *t = m_pTarget; //取得演員的對應網格數據。 CCGridBase *targetGrid = t->getGrid(); //有效性判斷,如果演員有網格數據並且已經填充了數據。 if (targetGrid && targetGrid->getReuseGrid() > 0) { //如果網格數據被激活並且其格子大小與本類實例的網格大小相同。 if (targetGrid->isActive() && targetGrid->getGridSize().x == m_sGridSize.x && targetGrid->getGridSize().y == m_sGridSize.y /*&& dynamic_cast<CCGridBase*>(targetGrid) != NULL*/) { //演員的網格數據恢復為原始數據。 targetGrid->reuse(); } else { CCAssert(0, ""); } } else { //如果演員沒有創建網格數據或者網格數據已經恢復為原始頂點。 //如果演員的網格數據有效並且是激活狀態。 if (targetGrid && targetGrid->isActive()) { //將其設為未激活。 targetGrid->setActive(false); } //將當前類實例的網格數據設置給演員之後激活。 t->setGrid(newgrid); t->getGrid()->setActive(true); } } //純虛函數:取得網格。做為基類沒做任何處理。 CCGridBase* CCGridAction::getGrid(void) { // Abstract class needs implementation CCAssert(0, ""); return NULL; } //創建一個反向播放的動畫。 CCActionInterval* CCGridAction::reverse(void) { return CCReverseTime::create(this); } //創建一個當前類實例的拷貝。 CCObject* CCGridAction::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCGridAction* pCopy = NULL; //如果pZone有效且已有拷貝數據。 if(pZone && pZone->m_pCopyObject) { //直接取用 pCopy = (CCGridAction*)(pZone->m_pCopyObject); } else { //否則新建一個當前類實例並設為pNewZone的拷貝數據。 pCopy = new CCGridAction(); pZone = pNewZone = new CCZone(pCopy); } //調用基類的相應函數。 CCActionInterval::copyWithZone(pZone); //初始化拷貝 pCopy->initWithSize(m_sGridSize, m_fDuration); //釋放臨時變數 CC_SAFE_DELETE(pNewZone); return pCopy; } //3D網格動畫基類 class CC_DLL CCGrid3DAction : public CCGridAction { public: //取得網格數據。 virtual CCGridBase* getGrid(void); //返回對應網格位置的頂點。 ccVertex3F vertex(const ccGridSize& pos); //返回對應網格位置的原始頂點。 ccVertex3F originalVertex(const ccGridSize& pos); //設置對應網格位置的頂點。 void setVertex(const ccGridSize& pos, const ccVertex3F& vertex); public: //靜態創建函數:參一為格子大小,參二為動畫時長,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCGrid3DAction* actionWithSize(const ccGridSize& gridSize, float duration); //上面的create實現。 static CCGrid3DAction* create(const ccGridSize& gridSize, float duration); }; 對應CPP: //取得網格數據。 CCGridBase* CCGrid3DAction::getGrid(void) { //創建一個對應大小的3D網格數據。 return CCGrid3D::create(m_sGridSize); } //返回對應網格位置的頂點。 ccVertex3F CCGrid3DAction::vertex(const ccGridSize& pos) { //取得演員的網格數據,調用網格數據的相應函數。 CCGrid3D *g = (CCGrid3D*)m_pTarget->getGrid(); return g->vertex(pos); } //返回對應網格位置的原始頂點。 ccVertex3F CCGrid3DAction::originalVertex(const ccGridSize& pos) { //取得演員的網格數據,調用網格數據的相應函數。 CCGrid3D *g = (CCGrid3D*)m_pTarget->getGrid(); return g->originalVertex(pos); } //設置對應網格位置的頂點。 void CCGrid3DAction::setVertex(const ccGridSize& pos, const ccVertex3F& vertex) { //取得演員的網格數據,調用網格數據的相應函數。 CCGrid3D *g = (CCGrid3D*)m_pTarget->getGrid(); g->setVertex(pos, vertex); } //派生於CCGridAction的3D格子動畫類。 class CC_DLL CCTiledGrid3DAction : public CCGridAction { public: //返回對應位置的格子頂點數據。 ccQuad3 tile(const ccGridSize& pos); //返回對應位置的原始格子頂點數據。 ccQuad3 originalTile(const ccGridSize& pos); //設置對應位置的格子數據。 void setTile(const ccGridSize& pos, const ccQuad3& coords); //返回網格數據。 virtual CCGridBase* getGrid(void); public: //靜態創建函數:參一為格子大小,參二為動畫時長,內部調用creat來實現。 CC_DEPRECATED_ATTRIBUTE static CCTiledGrid3DAction* actionWithSize(const ccGridSize& gridSize, float duration); //上面的create實現。 static CCTiledGrid3DAction* create(const ccGridSize& gridSize, float duration); }; //取得網格數據。 CCGridBase* CCTiledGrid3DAction::getGrid(void) { return CCTiledGrid3D::create(m_sGridSize); } //返回對應位置的格子頂點數據。 ccQuad3 CCTiledGrid3DAction::tile(const ccGridSize& pos) { //取得演員的網格數據,調用網格數據的相應函數。 CCTiledGrid3D *g = (CCTiledGrid3D*)m_pTarget->getGrid(); return g->tile(pos); } //返回對應位置的原始格子頂點數據。 ccQuad3 CCTiledGrid3DAction::originalTile(const ccGridSize& pos) { //取得演員的網格數據,調用網格數據的相應函數。 CCTiledGrid3D *g = (CCTiledGrid3D*)m_pTarget->getGrid(); return g->originalTile(pos); } //設置對應位置的格子數據。 void CCTiledGrid3DAction::setTile(const ccGridSize& pos, const ccQuad3& coords) { //取得演員的網格數據,調用網格數據的相應函數。 CCTiledGrid3D *g = (CCTiledGrid3D*)m_pTarget->getGrid(); return g->setTile(pos, coords); } //網格所用的變速動畫基類:先加速再減速。 class CC_DLL CCAccelDeccelAmplitude : public CCActionInterval { public: //析構 virtual ~CCAccelDeccelAmplitude(void); //初始化 bool initWithAction(CCAction *pAction, float duration); //設置演示動畫的演員。 virtual void startWithTarget(CCNode *pTarget); //更新動畫。 virtual void update(float time); //創建一個當前類的反向動畫實例。 virtual CCActionInterval* reverse(void); //取得速率 inline float getRate(void) { return m_fRate; } //設置速率 inline void setRate(float fRate) { m_fRate = fRate; } public: //靜態創建函數:參一為動畫實例指針,參二為動畫時長,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCAccelDeccelAmplitude* actionWithAction(CCAction *pAction, float duration); //上面函數的create實現。 static CCAccelDeccelAmplitude* create(CCAction *pAction, float duration); protected: //速率 float m_fRate; //所控制的時間動畫。 CCActionInterval *m_pOther; }; 對應CPP: //靜態創建函數:參一為動畫實例指針,參二為動畫時長,內部調用create實現。 CCAccelDeccelAmplitude* CCAccelDeccelAmplitude::actionWithAction(CCAction *pAction, float duration) { return CCAccelDeccelAmplitude::create(pAction, duration); } //上面函數的create實現。 CCAccelDeccelAmplitude* CCAccelDeccelAmplitude::create(CCAction *pAction, float duration) { //先new出一個當前類的實例。 CCAccelDeccelAmplitude *pRet = new CCAccelDeccelAmplitude(); if (pRet) { //初始化並交由內存管理器去進行引用計數器的管理。 if (pRet->initWithAction(pAction, duration)) { pRet->autorelease(); } else { //如果失敗,釋放並置空。 CC_SAFE_DELETE(pRet); } } //返回創建的當前類實例,當然可能為NULL。 return pRet; } //初始化處理。 bool CCAccelDeccelAmplitude::initWithAction(CCAction *pAction, float duration) { //調用基類的初始化函數。 if (CCActionInterval::initWithDuration(duration)) { //保存相應的變數值,佔用控制的動畫故對其引用計數加一。 m_fRate = 1.0f; m_pOther = (CCActionInterval*)(pAction); pAction->retain(); return true; } return false; } //析構 CCAccelDeccelAmplitude::~CCAccelDeccelAmplitude(void) { //不再佔用控制的時間動畫,對其引用計數器減一。 CC_SAFE_RELEASE(m_pOther); } //設置演示當前動畫的演員。 void CCAccelDeccelAmplitude::startWithTarget(CCNode *pTarget) { //先調用基類的相應函數。 CCActionInterval::startWithTarget(pTarget); //設置控制動畫使用此演員。 m_pOther->startWithTarget(pTarget); } //更新動畫。 void CCAccelDeccelAmplitude::update(float time) { //創建一個f值變為進度的2倍。 float f = time * 2; //如果動畫時間大於一半,讓進度由1再變為0。 if (f > 1) { f -= 1; f = 1 - f; } //使用powf處理來形成一個變速曲線公式來達到變速目的。 ((CCAccelDeccelAmplitude*)(m_pOther))->setAmplitudeRate(powf(f, m_fRate)); } //創建當前類的反向動畫實例。 CCActionInterval* CCAccelDeccelAmplitude::reverse(void) { return CCAccelDeccelAmplitude::create(m_pOther->reverse(), m_fDuration); } //網格所用的變速動畫基類:加速動畫。 class CC_DLL CCAccelAmplitude : public CCActionInterval { public: //析構 ~CCAccelAmplitude(void); //初始化處理。 bool initWithAction(CCAction *pAction, float duration); //取得速率 inline float getRate(void) { return m_fRate; } //設置速率 inline void setRate(float fRate) { m_fRate = fRate; } //設置演示當前動畫的演員。 virtual void startWithTarget(CCNode *pTarget); //更新動畫 virtual void update(float time); //創建一個當前動畫的反向動畫實例。 virtual CCActionInterval* reverse(void); public: //靜態創建函數:參一為一個時間動畫,參二為時長。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCAccelAmplitude* actionWithAction(CCAction *pAction, float duration); //上面函數的create實現。 static CCAccelAmplitude* create(CCAction *pAction, float duration); protected: //速率 float m_fRate; //控制動畫。 CCActionInterval *m_pOther; }; 對應CPP: //靜態創建函數:參一為一個時間動畫,參二為時長。內部調用create實現。 CCAccelAmplitude* CCAccelAmplitude::actionWithAction(CCAction *pAction, float duration) { return CCAccelAmplitude::create(pAction, duration); } //上面函數的create實現。 CCAccelAmplitude* CCAccelAmplitude::create(CCAction *pAction, float duration) { //創建三部曲,new,初始化,autorelease,一個不少。 CCAccelAmplitude *pRet = new CCAccelAmplitude(); if (pRet) { if (pRet->initWithAction(pAction, duration)) { pRet->autorelease(); } else { //當然,要有失敗處理。 CC_SAFE_DELETE(pRet); } } return pRet; } //初始化 bool CCAccelAmplitude::initWithAction(CCAction *pAction, float duration) { //先調用基類的初始化函數。 if (CCActionInterval::initWithDuration(duration)) { //速率設為1.0。 m_fRate = 1.0f; //保存動畫。佔用對其引用計數加一。 m_pOther = (CCActionInterval*)(pAction); pAction->retain(); return true; } return false; } //析構函數。 CCAccelAmplitude::~CCAccelAmplitude(void) { //不佔用,對其引用計數減一。 CC_SAFE_DELETE(m_pOther); } //設置演示當前動畫的演員。 void CCAccelAmplitude::startWithTarget(CCNode *pTarget) { //調用基類的相應函數。 CCActionInterval::startWithTarget(pTarget); //設置控制動畫使用此演員。 m_pOther->startWithTarget(pTarget); } //動畫更新處理。 void CCAccelAmplitude::update(float time) { //創建變速曲線來設置控制動畫的速率。 ((CCAccelAmplitude*)(m_pOther))->setAmplitudeRate(powf(time, m_fRate)); //更新控制動畫。 m_pOther->update(time); } //創建一個當前類的反向動畫實例。 CCActionInterval* CCAccelAmplitude::reverse(void) { return CCAccelAmplitude::create(m_pOther->reverse(), m_fDuration); } //網格所用的變速動畫基類:減速動畫。 class CC_DLL CCDeccelAmplitude : public CCActionInterval { public: //析構函數。 ~CCDeccelAmplitude(void); //初始化 bool initWithAction(CCAction *pAction, float duration); //取得速率 inline float getRate(void) { return m_fRate; } //設置速率 inline void setRate(float fRate) { m_fRate = fRate; } //設置演示當前動畫的演員。 virtual void startWithTarget(CCNode *pTarget); //更新處理。 virtual void update(float time); //創建一個當前類的反向播放的實例。 virtual CCActionInterval* reverse(void); public: //靜態創建函數,參一為一個動畫,參二為動畫時長。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCDeccelAmplitude* actionWithAction(CCAction *pAction, float duration); //上面的create實現。 static CCDeccelAmplitude* create(CCAction *pAction, float duration); protected: //速率 float m_fRate; //控制動畫。 CCActionInterval *m_pOther; }; 對應CPP: //靜態創建函數,參一為一個動畫,參二為動畫時長。內部調用create實現。 CCDeccelAmplitude* CCDeccelAmplitude::actionWithAction(CCAction *pAction, float duration) { return CCDeccelAmplitude::create(pAction, duration); } //上面的create實現。 CCDeccelAmplitude* CCDeccelAmplitude::create(CCAction *pAction, float duration) { //new, initWithAction, autorelease三部曲,當然別忘了失敗處理。 CCDeccelAmplitude *pRet = new CCDeccelAmplitude(); if (pRet) { if (pRet->initWithAction(pAction, duration)) { pRet->autorelease(); } else { CC_SAFE_DELETE(pRet); } } return pRet; } //初始化處理。 bool CCDeccelAmplitude::initWithAction(CCAction *pAction, float duration) { //先調用基類的初始化處理。 if (CCActionInterval::initWithDuration(duration)) { //速率置1。 m_fRate = 1.0f; //佔用控制動畫,對其引用計數器加一。 m_pOther = (CCActionInterval*)(pAction); pAction->retain(); return true; } return false; } //析構 CCDeccelAmplitude::~CCDeccelAmplitude(void) { //不再佔用控制動畫,對其引用計數器減一。 CC_SAFE_RELEASE(m_pOther); } //設置演示當前動畫的演員。 void CCDeccelAmplitude::startWithTarget(CCNode *pTarget) { //調用基類的相應函數。 CCActionInterval::startWithTarget(pTarget); //調用控制動畫的相應函數。 m_pOther->startWithTarget(pTarget); } //更新動畫。 void CCDeccelAmplitude::update(float time) { //與加速動畫有什麼不同?很容易明白。 ((CCDeccelAmplitude*)(m_pOther))->setAmplitudeRate(powf((1 - time), m_fRate)); m_pOther->update(time); } //創建一個當前類的反向動畫實例。 CCActionInterval* CCDeccelAmplitude::reverse(void) { return CCDeccelAmplitude::create(m_pOther->reverse(), m_fDuration); } //停止網格動畫。 class CC_DLL CCStopGrid : public CCActionInstant { public: //設置演示該動畫的演員。 virtual void startWithTarget(CCNode *pTarget); public: //靜態函數:創建一個當前類的實例動畫,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCStopGrid* action(void); //上面的create實現。 static CCStopGrid* create(void); }; 對應CPP: //設置演示當前動畫的演員。 void CCStopGrid::startWithTarget(CCNode *pTarget) { //調用基類的相應函數。 CCActionInstant::startWithTarget(pTarget); //取得演員所用的網格數據。 CCGridBase *pGrid = m_pTarget->getGrid(); if (pGrid && pGrid->isActive()) { //如果是激活狀態,取消激活。 pGrid->setActive(false); } } //靜態函數:創建一個當前類的實例動畫,內部調用create實現。 CCStopGrid* CCStopGrid::action(void) { return CCStopGrid::create(); } //上面的create實現。 CCStopGrid* CCStopGrid::create(void) { CCStopGrid* pAction = new CCStopGrid(); pAction->autorelease(); return pAction; } //恢復網格動畫。 class CC_DLL CCReuseGrid : public CCActionInstant { public: //初始化 bool initWithTimes(int times); //設置演示當前動畫的演員。 virtual void startWithTarget(CCNode *pTarget); public: //靜態函數:創建一個當前類的實例。參數為,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCReuseGrid* actionWithTimes(int times); //上面函數的create實現。 static CCReuseGrid* create(int times); protected: // int m_nTimes; }; 對應CPP: // CCReuseGrid* CCReuseGrid::actionWithTimes(int times) { return CCReuseGrid::create(times); } //上面函數的create實現。 CCReuseGrid* CCReuseGrid::create(int times) { //先new出一個當前類的實例。 CCReuseGrid *pAction = new CCReuseGrid(); if (pAction) { //進行初始化,成功后交由內存管理器進行引用計數器的管理。 if (pAction->initWithTimes(times)) { pAction->autorelease(); } else { //初始化失敗則釋放並置空。 CC_SAFE_DELETE(pAction); } } //返回創建的動畫實例,當然,也可能為NULL。 return pAction; } //初始化。 bool CCReuseGrid::initWithTimes(int times) { m_nTimes = times; return true; } //設置演示當前動畫的演員。 void CCReuseGrid::startWithTarget(CCNode *pTarget) { //調用基類的相應函數。 CCActionInstant::startWithTarget(pTarget); //如果演員有正在使用的網格動畫。 if (m_pTarget->getGrid() && m_pTarget->getGrid()->isActive()) { //取得這個網格動畫並激活。 m_pTarget->getGrid()->setReuseGrid(m_pTarget->getGrid()->getReuseGrid() + m_nTimes); } }
有了網格基本動畫,我們再來看一下3D網格基本動畫
CCActionGrid3D.h/cpp:
#include "CCActionGrid.h" NS_CC_BEGIN //波浪動畫 class CC_DLL CCWaves3D : public CCGrid3DAction public: //取得和設置振幅 inline float getAmplitude(void) { return m_fAmplitude; } inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //取得和設置頻率 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化 bool initWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration); //產生一個實例的拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //動畫更新。 virtual void update(float time); public: //創建一個波浪動畫,參一為波浪動畫搖動的次數,參二為波浪的振幅,參三為格子的大小,參四為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCWaves3D* actionWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCWaves3D* create(int wav, float amp, const ccGridSize& gridSize, float duration); protected: //波浪搖動的次數。 int m_nWaves; //搖動的振幅。 float m_fAmplitude; //搖動的頻率。 float m_fAmplitudeRate; }; CPP實現: //創建一個波浪動畫,參一為波浪動畫搖動的次數,參二為波浪的振幅,參三為格子的大小,參四為動畫時長。 CCWaves3D* CCWaves3D::actionWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration) { return CCWaves3D::create(wav, amp, gridSize, duration); } //上面的create實現。 CCWaves3D* CCWaves3D::create(int wav, float amp, const ccGridSize& gridSize, float duration) { //new,初始化,autorelease,失敗處理。 CCWaves3D *pAction = new CCWaves3D(); if (pAction) { if (pAction->initWithWaves(wav, amp, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCWaves3D::initWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration) { //先調用基類的初始化函數。 if (CCGrid3DAction::initWithSize(gridSize, duration)) { //保存相應的參數。 m_nWaves = wav; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; return true; } return false; } //產生一個當前類的實例。 CCObject* CCWaves3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCWaves3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCWaves3D*)(pZone->m_pCopyObject); } else { pCopy = new CCWaves3D(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithWaves(m_nWaves, m_fAmplitude, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫。 void CCWaves3D::update(float time) { //雙循環遍歷格子。 int i, j; for (i = 0; i < m_sGridSize.x + 1; ++i) { for (j = 0; j < m_sGridSize.y + 1; ++j) { //取出當前格子原始頂點,對z值進行sin曲線的變化加值。形成來回搖動的效果。 ccVertex3F v = originalVertex(ccg(i ,j)); v.z += (sinf((float)M_PI * time * m_nWaves * 2 + (v.y+v.x) * .01f) * m_fAmplitude * m_fAmplitudeRate); CCLog("v.z offset is %f\n", (sinf((float)M_PI * time * m_nWaves * 2 + (v.y+v.x) * .01f) * m_fAmplitude * m_fAmplitudeRate)); //將頂點設置到格子中。 setVertex(ccg(i, j), v); } } } 對應圖:
//繞X軸翻轉。 class CC_DLL CCFlipX3D : public CCGrid3DAction { public: //初始化動畫。 bool initWithDuration(float duration); //初始化格子大小。 virtual bool initWithSize(const ccGridSize& gridSize, float duration); //產生一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //動畫更新。 virtual void update(float time); public: //創建一個繞X軸翻轉的3D網格動畫。參數為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCFlipX3D* actionWithDuration(float duration); //上面的create實現。 static CCFlipX3D* create(float duration); }; 對應的CPP實現: //創建一個繞X軸翻轉的3D網格動畫。參數為動畫時長。CCFlipX3D::actionWithDuration(float duration) { return CCFlipX3D::create(duration); } //上面的create實現。 CCFlipX3D* CCFlipX3D::create(float duration) { //new ,初始化, autorelease,失敗處理。 CCFlipX3D *pAction = new CCFlipX3D(); if (pAction) { if (pAction->initWithSize(ccg(1, 1), duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化動畫。 bool CCFlipX3D::initWithDuration(float duration) { return CCGrid3DAction::initWithSize(ccg(1, 1), duration); } //初始化格子大小。 bool CCFlipX3D::initWithSize(const ccGridSize& gridSize, float duration) { if (gridSize.x != 1 || gridSize.y != 1) { // Grid size must be (1,1) CCAssert(0, "Grid size must be (1,1)"); return false; } return CCGrid3DAction::initWithSize(gridSize, duration); } //產生一個當前類的實例拷貝。 CCObject* CCFlipX3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCFlipX3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCFlipX3D*)(pZone->m_pCopyObject); } else { pCopy = new CCFlipX3D(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithSize(m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //動畫更新。 void CCFlipX3D::update(float time) { //角度,從0~180變化。 float angle = (float)M_PI * time; // 180 degrees //計算其sin值 float mz = sinf(angle); //對基除2後計算cos值。 angle = angle / 2.0f; // x calculates degrees from 0 to 90 float mx = cosf(angle); //定義臨時變數。 ccVertex3F v0, v1, v, diff; // v0 = originalVertex(ccg(1, 1)); v1 = originalVertex(ccg(0, 0)); // float x0 = v0.x; float x1 = v1.x; float x; ccGridSize a, b, c, d; // if ( x0 > x1 ) { // Normal Grid a = ccg(0,0); b = ccg(0,1); c = ccg(1,0); d = ccg(1,1); x = x0; } else { // Reversed Grid c = ccg(0,0); d = ccg(0,1); a = ccg(1,0); b = ccg(1,1); x = x1; } // diff.x = ( x - x * mx ); diff.z = fabsf( floorf( (x * mz) / 4.0f ) ); //取得左下角頂點,設置X和Z值。 v = originalVertex(a); v.x = diff.x; v.z += diff.z; setVertex(a, v); //取得左上角頂點。計算X和Z值。 v = originalVertex(b); v.x = diff.x; v.z += diff.z; setVertex(b, v); //取得右下角頂點。計算X和Z值。 v = originalVertex(c); v.x -= diff.x; v.z -= diff.z; setVertex(c, v); //取得右上角頂點。計算X和Z值。 v = originalVertex(d); v.x -= diff.x; v.z -= diff.z; setVertex(d, v); } 對應圖:
//繞Y軸反轉的3D網格動畫。 class CC_DLL CCFlipY3D : public CCFlipX3D { public: //動畫更新。 virtual void update(float time); //產生一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); public: //創建一個繞Y軸反轉的3D網格動畫,內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCFlipY3D* actionWithDuration(float duration); //上面的create實現。 static CCFlipY3D* create(float duration); }; 對應CPP實現: //創建一個繞Y軸反轉的3D網格動畫,內部調用create實現。 CCFlipY3D* CCFlipY3D::actionWithDuration(float duration) { return CCFlipY3D::create(duration); } //上面的create實現。 CCFlipY3D* CCFlipY3D::create(float duration) { //new ,初始化, autorelease,失敗處理。 CCFlipY3D *pAction = new CCFlipY3D(); if (pAction) { if (pAction->initWithSize(ccg(1, 1), duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //產生一個當前類的實例拷貝。 CCObject* CCFlipY3D::copyWithZone(CCZone* pZone) { CCZone* pNewZone = NULL; CCFlipY3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCFlipY3D*)(pZone->m_pCopyObject); } else { pCopy = new CCFlipY3D(); pZone = pNewZone = new CCZone(pCopy); } CCFlipX3D::copyWithZone(pZone); pCopy->initWithSize(m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //動畫更新。 void CCFlipY3D::update(float time) { //角度從0~180 float angle = (float)M_PI * time; // 180 degrees //對其進行sin計算。 float mz = sinf( angle ); //對其做除2計算。 angle = angle / 2.0f; // x calculates degrees from 0 to 90 //對其進行cos計算。 float my = cosf(angle); ccVertex3F v0, v1, v, diff; v0 = originalVertex(ccg(1, 1)); v1 = originalVertex(ccg(0, 0)); float y0 = v0.y; float y1 = v1.y; float y; ccGridSize a, b, c, d; if (y0 > y1) { // Normal Grid a = ccg(0,0); b = ccg(0,1); c = ccg(1,0); d = ccg(1,1); y = y0; } else { // Reversed Grid b = ccg(0,0); a = ccg(0,1); d = ccg(1,0); c = ccg(1,1); y = y1; } diff.y = y - y * my; diff.z = fabsf(floorf((y * mz) / 4.0f)); // bottom-left v = originalVertex(a); v.y = diff.y; v.z += diff.z; setVertex(a, v); // upper-left v = originalVertex(b); v.y -= diff.y; v.z -= diff.z; setVertex(b, v); // bottom-right v = originalVertex(c); v.y = diff.y; v.z += diff.z; setVertex(c, v); // upper-right v = originalVertex(d); v.y -= diff.y; v.z -= diff.z; setVertex(d, v); } 對應圖:
//球體3D網格動畫。 class CC_DLL CCLens3D : public CCGrid3DAction { public: // inline float getLensEffect(void) { return m_fLensEffect; } // inline void setLensEffect(float fLensEffect) { m_fLensEffect = fLensEffect; } //設置中心位置。 inline const CCPoint& getPosition(void) { return m_position; } void setPosition(const CCPoint& position); //初始化。 bool initWithPosition(const CCPoint& pos, float r, const ccGridSize& gridSize, float duration); //創建一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //動畫更新。 virtual void update(float time); public: //創建一個球體的3D網格動畫。參一為中心點位置,參二為半徑,參三為格子大小,參四為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCLens3D* actionWithPosition(const CCPoint& pos, float r, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCLens3D* create(const CCPoint& pos, float r, const ccGridSize& gridSize, float duration); protected: //球體的中心位置。 CCPoint m_position; //球體的半徑。 float m_fRadius; //效果公式的參數。 float m_fLensEffect; //這個命名本意是使用臟矩形,即相同的矩形沒有改變就不要重新更新。但可惜它在使用時的true與false應該反過來。這裡可以理解成是否更新中心點位置,需要重新計算。 bool m_bDirty; }; 對應的CPP: //創建一個球體的3D網格動畫。參一為中心點位置,參二為半徑,參三為格子大小,參四為動畫時長。 CCLens3D* CCLens3D::actionWithPosition(const CCPoint& pos, float r, const ccGridSize& gridSize, float duration) { return CCLens3D::create(pos, r, gridSize, duration); } //上面的create實現。 CCLens3D* CCLens3D::create(const CCPoint& pos, float r, const ccGridSize& gridSize, float duration) { //new,初始化,autorelease,失敗處理。 CCLens3D *pAction = new CCLens3D(); if (pAction) { if (pAction->initWithPosition(pos, r, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCLens3D::initWithPosition(const CCPoint& pos, float r, const ccGridSize& gridSize, float duration) { //先調用基類的相應函數。 if (CCGrid3DAction::initWithSize(gridSize, duration)) { //保存參數到成員變數。 m_position = ccp(-1, -1); setPosition(pos); m_fRadius = r; m_fLensEffect = 0.7f; //設置需要重新計算。 m_bDirty = true; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCLens3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCLens3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCLens3D*)(pZone->m_pCopyObject); } else { pCopy = new CCLens3D(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithPosition(m_position, m_fRadius, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //設置球體的中心位置。 void CCLens3D::setPosition(const CCPoint& pos) { if( !pos.equals(m_position)) {//位置有更新,則設置需要重新計算。 m_position = pos; m_bDirty = true; } } //動畫更新。 void CCLens3D::update(float time) { CC_UNUSED_PARAM(time); //如果需要重新計算。 if (m_bDirty) { int i, j; //雙循環遍歷格子。 for (i = 0; i < m_sGridSize.x + 1; ++i) { for (j = 0; j < m_sGridSize.y + 1; ++j) { //取出格子對應的頂點。 ccVertex3F v = originalVertex(ccg(i, j)); //計算格子頂點與中心點的差。 CCPoint vect = ccpSub(m_position, ccp(v.x, v.y)); //計算格子頂點與中心點的距離。 float r = ccpLength(vect); //如果距離在半徑內。 if (r < m_fRadius) { r = m_fRadius - r; float pre_log = r / m_fRadius; if ( pre_log == 0 ) { pre_log = 0.001f; } //通過一些函數來取得相應的頂點影響值。 float l = logf(pre_log) * m_fLensEffect; float new_r = expf( l ) * m_fRadius; //如果不是中心點,就進行位置的更新。 if (ccpLength(vect) > 0) { vect = ccpNormalize(vect); CCPoint new_vect = ccpMult(vect, new_r); v.z += ccpLength(new_vect) * m_fLensEffect; } } //設置格子的新頂點。 setVertex(ccg(i, j), v); } } m_bDirty = false; } } 對應圖:
//漣漪3D網格特效。 class CC_DLL CCRipple3D : public CCGrid3DAction { public: //取得和設置中心位置。 inline const CCPoint& getPosition(void) { return m_position; } void setPosition(const CCPoint& position); //取得和設置振幅。 inline float getAmplitude(void) { return m_fAmplitude; } inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //取得和設置頻率。 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化位置。 bool initWithPosition(const CCPoint& pos, float r, int wav, float amp, const ccGridSize& gridSize, float duration); virtual CCObject* copyWithZone(CCZone* pZone); virtual void update(float time); public: //創建一個漣漪3D網格特效。參一為中心位置,參二為半徑,參三為振幅,參四為格子大小,參五為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCRipple3D* actionWithPosition(const CCPoint& pos, float r, int wav, float amp, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCRipple3D* create(const CCPoint& pos, float r, int wav, float amp, const ccGridSize& gridSize, float duration); protected: //中心位置。 CCPoint m_position; //半徑。 float m_fRadius; //振動次數。 int m_nWaves; //振幅。 float m_fAmplitude; //振動頻率。 float m_fAmplitudeRate; }; CPP實現: //創建一個漣漪3D網格特效。 CCRipple3D* CCRipple3D::actionWithPosition(const CCPoint& pos, float r, int wav, float amp, const ccGridSize& gridSize, float duration) { return CCRipple3D::create(pos, r, wav, amp, gridSize, duration); } //上面的create實現。 CCRipple3D* CCRipple3D::create(const CCPoint& pos, float r, int wav, float amp, const ccGridSize& gridSize, float duration) { //先new出一個當前類的實例。 CCRipple3D *pAction = new CCRipple3D(); //如果成功。 if (pAction) { //進行初始化。 if (pAction->initWithPosition(pos, r, wav, amp, gridSize, duration)) { //如果初始化成功,交由內存管理器進行引用計數管理。 pAction->autorelease(); } else { //如果失敗,釋放並置空。 CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCRipple3D::initWithPosition(const CCPoint& pos, float r, int wav, float amp, const ccGridSize& gridSize, float duration) { //先調用基類的初始化處理。 if (CCGrid3DAction::initWithSize(gridSize, duration)) { //設置中心點位置。 setPosition(pos); //將參數保存到成員變數中。 m_fRadius = r; m_nWaves = wav; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; return true; } return false; } //設置中心點位置。 void CCRipple3D::setPosition(const CCPoint& position) { m_position = position; } //產生一個當前類的實例拷貝。 CCObject* CCRipple3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCRipple3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCRipple3D*)(pZone->m_pCopyObject); } else { pCopy = new CCRipple3D(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithPosition(m_position, m_fRadius, m_nWaves, m_fAmplitude, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫處理。 void CCRipple3D::update(float time) { int i, j; //雙循環遍歷每個格子。 for (i = 0; i < (m_sGridSize.x+1); ++i) { for (j = 0; j < (m_sGridSize.y+1); ++j) { //取得格子的原始頂點。 ccVertex3F v = originalVertex(ccg(i, j)); //計算頂點與中心點的位置之差。 CCPoint vect = ccpSub(m_position, ccp(v.x,v.y)); //計算出頂點與中心點的距離。 float r = ccpLength(vect); //如果在半徑範圍內。通過距離做為參數按照sin曲線公式計算出相應的Z值偏移。 if (r < m_fRadius) { r = m_fRadius - r; float rate = powf(r / m_fRadius, 2); v.z += (sinf( time*(float)M_PI * m_nWaves * 2 + r * 0.1f) * m_fAmplitude * m_fAmplitudeRate * rate); } //將偏移后的頂點設置給格子。 setVertex(ccg(i, j), v); } } } 效果圖:
//3D搖動的網格動畫。 class CC_DLL CCShaky3D : public CCGrid3DAction { public: //初始化。 bool initWithRange(int range, bool shakeZ, const ccGridSize& gridSize, float duration); //產生一個實例的拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //創建一個3D搖動的網格動畫。參一是隨機範圍,參二指定是否在Z值上搖動,參三為格子大小,參四為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCShaky3D* actionWithRange(int range, bool shakeZ, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCShaky3D* create(int range, bool shakeZ, const ccGridSize& gridSize, float duration); protected: //隨機範圍。 int m_nRandrange; //是否在Z值上搖動。 bool m_bShakeZ; }; //創建一個3D搖動的網格動畫。參一是隨機範圍,參二指定是否在Z值上搖動,參三為格子大小,參四為動畫時長。 CCShaky3D* CCShaky3D::actionWithRange(int range, bool shakeZ, const ccGridSize& gridSize, float duration) { return CCShaky3D::create(range, shakeZ, gridSize, duration); } //上面的create實現。 CCShaky3D* CCShaky3D::create(int range, bool shakeZ, const ccGridSize& gridSize, float duration) { //先new出一個當前類的實例, CCShaky3D *pAction = new CCShaky3D(); if (pAction) { //如果成功,對其進行初始化。 if (pAction->initWithRange(range, shakeZ, gridSize, duration)) { //如果初始化成功,交由內存管理器進行引用計數的管理。 pAction->autorelease(); } else { //如果失敗,釋放並置空。 CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCShaky3D::initWithRange(int range, bool shakeZ, const ccGridSize& gridSize, float duration) { //先調用基類的初始化函數。 if (CCGrid3DAction::initWithSize(gridSize, duration)) { //如果成功,保存參數到成員變數中。 m_nRandrange = range; m_bShakeZ = shakeZ; return true; } return false; } //產生一個當前類的實例。 CCObject* CCShaky3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCShaky3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCShaky3D*)(pZone->m_pCopyObject); } else { pCopy = new CCShaky3D(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithRange(m_nRandrange, m_bShakeZ, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //動畫更新。 void CCShaky3D::update(float time) { CC_UNUSED_PARAM(time); int i, j; //雙循環遍歷所有格子。 for (i = 0; i < (m_sGridSize.x+1); ++i) { for (j = 0; j < (m_sGridSize.y+1); ++j) { //取得格子的原始頂點。 ccVertex3F v = originalVertex(ccg(i ,j)); //對頂點的x,y進行隨機的的加成。 v.x += (rand() % (m_nRandrange*2)) - m_nRandrange; v.y += (rand() % (m_nRandrange*2)) - m_nRandrange; //如果需要Z值的搖動,對頂點的z進行隨機的的加成。 if (m_bShakeZ) { v.z += (rand() % (m_nRandrange*2)) - m_nRandrange; } //將頂點設置到相應格子中。 setVertex(ccg(i, j), v); } } } 對應圖:
//流體效果的3D網格動畫。 class CC_DLL CCLiquid : public CCGrid3DAction { public: //取得和設置振幅。 inline float getAmplitude(void) { return m_fAmplitude; } inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //取得和設置頻率。 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化 bool initWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration); //產生一個當前類的實例。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //創建一個流體效果的3D網格動畫。參一為動畫的次數,參二為振幅,參三為格子大小,參四為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCLiquid* actionWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCLiquid* create(int wav, float amp, const ccGridSize& gridSize, float duration); protected: //動畫的次數。 int m_nWaves; //振幅。 float m_fAmplitude; //頻率。 float m_fAmplitudeRate; }; 對應的CPP: //創建一個流體效果的3D網格動畫。參一為動畫的次數,參二為振幅,參三為格子大小,參四為動畫時長。 CCLiquid* CCLiquid::actionWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration) { return CCLiquid::create(wav, amp, gridSize, duration); } //上面的create實現。 CCLiquid* CCLiquid::create(int wav, float amp, const ccGridSize& gridSize, float duration) { //先new出一個當前類的實例動畫。 CCLiquid *pAction = new CCLiquid(); if (pAction) { //如果成功,進行初始化。 if (pAction->initWithWaves(wav, amp, gridSize, duration)) { //初始化成功交由內存管理器進行引用計數器的管理。 pAction->autorelease(); } else { //如果失敗,釋放並置空。 CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化 bool CCLiquid::initWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration) { //先調用基類的初始化函數。 if (CCGrid3DAction::initWithSize(gridSize, duration)) { //將相應的參數保存到成員變數中。 m_nWaves = wav; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCLiquid::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCLiquid* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCLiquid*)(pZone->m_pCopyObject); } else { pCopy = new CCLiquid(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithWaves(m_nWaves, m_fAmplitude, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //動畫更新。 void CCLiquid::update(float time) { int i, j; //雙循環遍歷所有的格子。 for (i = 1; i < m_sGridSize.x; ++i) { for (j = 1; j < m_sGridSize.y; ++j) { //取出格子的原始頂點位置。 ccVertex3F v = originalVertex(ccg(i, j)); //設置頂點的x,y值。 v.x = (v.x + (sinf(time * (float)M_PI * m_nWaves * 2 + v.x * .01f) * m_fAmplitude * m_fAmplitudeRate)); v.y = (v.y + (sinf(time * (float)M_PI * m_nWaves * 2 + v.y * .01f) * m_fAmplitude * m_fAmplitudeRate)); //將頂點數據設置給相應格子。 setVertex(ccg(i, j), v); } } } 對應圖:
//波浪效果的網格動畫,與CCWaves3D的區別是少了Z值的變化。 class CC_DLL CCWaves : public CCGrid3DAction { public: //設置振幅。 inline float getAmplitude(void) { return m_fAmplitude; } inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //設置頻率。 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化。 bool initWithWaves(int wav, float amp, bool h, bool v, const ccGridSize& gridSize, float duration); //產生一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //創建一個波浪效果的網格動畫,參一為波浪的次數,參二為振幅,參三為是否進行橫向運動,參四為是否進行豎向運動,參五為格子大小,參六為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCWaves* actionWithWaves(int wav, float amp, bool h, bool v, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCWaves* create(int wav, float amp, bool h, bool v, const ccGridSize& gridSize, float duration); protected: //波浪次數。 int m_nWaves; //振幅。 float m_fAmplitude; //頻率。 float m_fAmplitudeRate; //豎向 bool m_bVertical; //橫向。 bool m_bHorizontal; }; //創建一個波浪效果的網格動畫,參一為波浪的次數,參二為振幅,參三為是否進行橫向運動,參四為是否進行豎向運動,參五為格子大小,參六為動畫時長。 CCWaves* CCWaves::actionWithWaves(int wav, float amp, bool h, bool v, const ccGridSize& gridSize, float duration) { return CCWaves::create(wav, amp, h, v, gridSize, duration); } //上面的create實現。 CCWaves* CCWaves::create(int wav, float amp, bool h, bool v, const ccGridSize& gridSize, float duration) { //先new出一個當前類的實例。 CCWaves *pAction = new CCWaves(); //如果成功。 if (pAction) { //進行初始化。 if (pAction->initWithWaves(wav, amp, h, v, gridSize, duration)) { //初始化成功,則交給內存管理器進行引用計數器的管理。 pAction->autorelease(); } else { //否則釋放並置空。 CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCWaves::initWithWaves(int wav, float amp, bool h, bool v, const ccGridSize& gridSize, float duration) { if (CCGrid3DAction::initWithSize(gridSize, duration)) { m_nWaves = wav; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; m_bHorizontal = h; m_bVertical = v; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCWaves::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCWaves* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCWaves*)(pZone->m_pCopyObject); } else { pCopy = new CCWaves(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithWaves(m_nWaves, m_fAmplitude, m_bHorizontal, m_bVertical, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //動畫更新。 void CCWaves::update(float time) { int i, j; //雙循環遍歷所有格子。 for (i = 0; i < m_sGridSize.x + 1; ++i) { for (j = 0; j < m_sGridSize.y + 1; ++j) { //取得對應格子的頂點。 ccVertex3F v = originalVertex(ccg(i, j)); //如果進行橫向運動。 if (m_bVertical) { //計算X值。 v.x = (v.x + (sinf(time * (float)M_PI * m_nWaves * 2 + v.y * .01f) * m_fAmplitude * m_fAmplitudeRate)); } //如果進行豎向運動。 if (m_bHorizontal) { //計算Y值。 v.y = (v.y + (sinf(time * (float)M_PI * m_nWaves * 2 + v.x * .01f) * m_fAmplitude * m_fAmplitudeRate)); } //將頂點數據設置到相應格子中。 setVertex(ccg(i, j), v); } } } 對應圖:
//盤旋扭曲效果的3D網格動畫。 class CC_DLL CCTwirl : public CCGrid3DAction { public: //取得中心位置。 inline const CCPoint& getPosition(void) { return m_position; } //設置中心位置。 void setPosition(const CCPoint& position); //取得振幅。 inline float getAmplitude(void) { return m_fAmplitude; } //設置振幅。 inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //取得和設置頻率。 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化。 bool initWithPosition(const CCPoint& pos, int t, float amp, const ccGridSize& gridSize, float duration); //產生一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //創建一個盤旋扭曲效果的3D網格動畫。參一為中心位置,參二為盤旋扭曲的次數,參三為振幅,參四為格子大小,參五為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCTwirl* actionWithPosition(CCPoint pos, int t, float amp, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCTwirl* create(CCPoint pos, int t, float amp, const ccGridSize& gridSize, float duration); protected: //中心點位置。 CCPoint m_position; //盤旋扭曲的次數。 int m_nTwirls; //振幅。 float m_fAmplitude; //頻率。 float m_fAmplitudeRate; }; //創建一個盤旋扭曲效果的3D網格動畫。參一為中心位置,參二為盤旋扭曲的次數,參三為振幅,參四為格子大小,參五為動畫時長。 CCTwirl* CCTwirl::actionWithPosition(CCPoint pos, int t, float amp, const ccGridSize& gridSize, float duration) { return CCTwirl::create(pos, t, amp, gridSize, duration); } //上面的create實現。 CCTwirl* CCTwirl::create(CCPoint pos, int t, float amp, const ccGridSize& gridSize, float duration) { //先new出一個當前類的實例。 CCTwirl *pAction = new CCTwirl(); if (pAction) { //進行初始化。 if (pAction->initWithPosition(pos, t, amp, gridSize, duration)) { //成功則交由內存管理器進行引用計數器管理。 pAction->autorelease(); } else { //失敗則釋放並置空。 CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCTwirl::initWithPosition(const CCPoint& pos, int t, float amp, const ccGridSize& gridSize, float duration) { if (CCGrid3DAction::initWithSize(gridSize, duration)) { setPosition(pos); m_nTwirls = t; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; return true; } return false; } //設置中心點位置。 void CCTwirl::setPosition(const CCPoint& position) { m_position = position; } //產生一個當前類的實例拷貝。 CCObject* CCTwirl::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCTwirl* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCTwirl*)(pZone->m_pCopyObject); } else { pCopy = new CCTwirl(); pZone = pNewZone = new CCZone(pCopy); } CCGrid3DAction::copyWithZone(pZone); pCopy->initWithPosition(m_position, m_nTwirls, m_fAmplitude, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫。 void CCTwirl::update(float time) { int i, j; //將動畫的中心點位置保存到點c中。 CCPoint c = m_position; //雙循環遍歷每個格子。 for (i = 0; i < (m_sGridSize.x+1); ++i) { for (j = 0; j < (m_sGridSize.y+1); ++j) { //取得對應格子的頂點。 ccVertex3F v = originalVertex(ccg(i ,j)); //取得當前格子與格子中心位置的差。 CCPoint avg = ccp(i-(m_sGridSize.x/2.0f), j-(m_sGridSize.y/2.0f)); //計算當前格子與中心點位置的距離。 float r = ccpLength(avg); //計算振幅。 float amp = 0.1f * m_fAmplitude * m_fAmplitudeRate; //使用cos公式來計算出曲線變化值。 float a = r * cosf( (float)M_PI/2.0f + time * (float)M_PI * m_nTwirls * 2 ) * amp; //計算出一個偏移。 CCPoint d = ccp( sinf(a) * (v.y-c.y) + cosf(a) * (v.x-c.x), cosf(a) * (v.y-c.y) - sinf(a) * (v.x-c.x)); //當前頂點位置為動畫中心點位置加上偏移。 v.x = c.x + d.x; v.y = c.y + d.y; //將頂點設置給相應的格子。 setVertex(ccg(i ,j), v); } } } 對應圖:
上面講的是操控網格數據表現一些基本動畫的類。下面我們來看一下由這些基本動畫的類衍生出來的複雜動畫。
打開CCActionTiledGrid.h:
#ifndef __ACTION_CCTILEDGRID_ACTION_H__ #define __ACTION_CCTILEDGRID_ACTION_H__ #include "CCActionGrid.h" //使用Cocos2d命名空間 NS_CC_BEGIN //搖動的3D格子動畫。 class CC_DLL CCShakyTiles3D : public CCTiledGrid3DAction { public: //初始化,參數一為範圍大小,參數2為是否在Z值上搖動,參數3為格子的大小,參數4為動畫的持續時間。 bool initWithRange(int nRange, bool bShakeZ, const ccGridSize& gridSize, float duration); //創建一個當前類的實例拷貝 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //靜態函數:創建一個搖動的3D格子動畫。參一為範圍大小,參數2為是否在Z值上搖動,參數3為格子的大小,參數4為動畫的持續時間。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCShakyTiles3D* actionWithRange(int nRange, bool bShakeZ, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCShakyTiles3D* create(int nRange, bool bShakeZ, const ccGridSize& gridSize, float duration); protected: //隨機範圍。 int m_nRandrange; //是否在Z值上搖動 bool m_bShakeZ; }; struct Tile { CCPoint position; CCPoint startPosition; ccGridSize delta; }; //靜態函數:創建一個搖動的3D格子動畫。參一為範圍大小,參數2為是否在Z值上搖動,參數3為格子的大小,參數4為動畫的持續時間。內部調用create實現。 CCShakyTiles3D* CCShakyTiles3D::actionWithRange(int nRange, bool bShakeZ,const ccGridSize& gridSize, float duration) { return CCShakyTiles3D::create(nRange, bShakeZ, gridSize, duration); } //上面的create實現。 CCShakyTiles3D* CCShakyTiles3D::create(int nRange, bool bShakeZ,const ccGridSize& gridSize, float duration) { //先new出一個當前類的實例。 CCShakyTiles3D *pAction = new CCShakyTiles3D(); //如果成功。初始化並交由內存管理器進行引用計數管理。 if (pAction) { if (pAction->initWithRange(nRange, bShakeZ, gridSize, duration)) { pAction->autorelease(); } else { //失敗處理。 CC_SAFE_RELEASE_NULL(pAction); } } //返回結果。 return pAction; } //初始化。 bool CCShakyTiles3D::initWithRange(int nRange, bool bShakeZ, const ccGridSize& gridSize, float duration) { //先調用基類的相應函數。 if (CCTiledGrid3DAction::initWithSize(gridSize, duration)) { //保存相應的值到成員變數。 m_nRandrange = nRange; m_bShakeZ = bShakeZ; return true; } return false; } //產生一個當前類的實例拷貝。講的太多,略過。 CCObject* CCShakyTiles3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCShakyTiles3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { //in case of being called at sub class pCopy = (CCShakyTiles3D*)(pZone->m_pCopyObject); } else { pCopy = new CCShakyTiles3D(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithRange(m_nRandrange, m_bShakeZ, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫。 void CCShakyTiles3D::update(float time) { CC_UNUSED_PARAM(time); int i, j; //雙循環遍歷每個格子。 for (i = 0; i < m_sGridSize.x; ++i) { for (j = 0; j < m_sGridSize.y; ++j) { //取得格子的位置。 ccQuad3 coords = originalTile(ccg(i, j)); // 計算格子四個頂點的X坐標。 coords.bl.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.br.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tl.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tr.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; // 計算格子四個頂點的Y坐標。 coords.bl.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.br.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tl.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tr.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; // 是否在Z軸上搖動。 if (m_bShakeZ) { //如果搖動在四個頂點的Z值上有隨機的加成。 coords.bl.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.br.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tl.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tr.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; } //重新設置格子的頂點。 setTile(ccg(i, j), coords); } } } 對應圖:
//隨機抖動效果的3D網格動畫。 class CC_DLL CCShatteredTiles3D : public CCTiledGrid3DAction { public: //初始化函數。 bool initWithRange(int nRange, bool bShatterZ, const ccGridSize& gridSize, float duration); //創建一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //靜態函數:創建一個當前類的實例 。參一為範圍,參數為是否在Z抽上震動,參三為格子大小,參四為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCShatteredTiles3D* actionWithRange(int nRange, bool bShatterZ, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCShatteredTiles3D* create(int nRange, bool bShatterZ, const ccGridSize& gridSize, float duration); protected: //隨機範圍 int m_nRandrange; //區分第一次渲染所用。 bool m_bOnce; //是否在Z抽上震動。 bool m_bShatterZ; }; //靜態函數:創建一個當前類的實例 。參一為範圍,參數為是否在Z抽上震動,參三為格子大小,參四為動畫時長。 CCShatteredTiles3D* CCShatteredTiles3D::actionWithRange(int nRange, bool bShatterZ, const ccGridSize& gridSize, float duration) { return CCShatteredTiles3D::create(nRange, bShatterZ, gridSize, duration); } //上面的create實現。 CCShatteredTiles3D* CCShatteredTiles3D::create(int nRange, bool bShatterZ, const ccGridSize& gridSize, float duration) { //new,初始化,autorelease,失敗處理一條龍! CCShatteredTiles3D *pAction = new CCShatteredTiles3D(); if (pAction) { if (pAction->initWithRange(nRange, bShatterZ, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } //返在回結果。 return pAction; } //初始化。 bool CCShatteredTiles3D::initWithRange(int nRange, bool bShatterZ, const ccGridSize& gridSize, float duration) { //先調用基類的初始化處理。 if (CCTiledGrid3DAction::initWithSize(gridSize, duration)) { //設置標記提示在更新動理時指明是第一次進行更新。 m_bOnce = false; //將相應的參數值保存到成員變數中。 m_nRandrange = nRange; m_bShatterZ = bShatterZ; return true; } return false; } //產生一個當前類的實例。 CCObject* CCShatteredTiles3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCShatteredTiles3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCShatteredTiles3D*)(pZone->m_pCopyObject); } else { pCopy = new CCShatteredTiles3D(); pZone = pNewZone = new CCZone(pCopy); } //copy super class's member CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithRange(m_nRandrange, m_bShatterZ, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫。 void CCShatteredTiles3D::update(float time) { CC_UNUSED_PARAM(time); int i, j; //如果是第一次渲染。 if (m_bOnce == false) { //雙循環遍歷格子。 for (i = 0; i < m_sGridSize.x; ++i) { for (j = 0; j < m_sGridSize.y; ++j) { //取得格子的坐標。 ccQuad3 coords = originalTile(ccg(i ,j)); // 計算格子四個頂點的X坐標。 coords.bl.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.br.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tl.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tr.x += ( rand() % (m_nRandrange*2) ) - m_nRandrange; // 計算格子四個頂點的Y坐標。 coords.bl.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.br.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tl.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tr.y += ( rand() % (m_nRandrange*2) ) - m_nRandrange; if (m_bShatterZ) { coords.bl.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.br.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tl.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; coords.tr.z += ( rand() % (m_nRandrange*2) ) - m_nRandrange; } //重新設置格子的頂點。 setTile(ccg(i, j), coords); } } //設置不是第一次更新。 m_bOnce = true; } } struct Tile; 對應圖:
//重新排列格子效果的3D網格動畫。 class CC_DLL CCShuffleTiles : public CCTiledGrid3DAction { public: //析構 ~CCShuffleTiles(void); //初始化函數。 bool initWithSeed(int s, const ccGridSize& gridSize, float duration); //重新排列處理 void shuffle(int *pArray, unsigned int nLen); //取得 ccGridSize getDelta(const ccGridSize& pos); // void placeTile(const ccGridSize& pos, Tile *t); //重載基類的相應函數。 virtual void startWithTarget(CCNode *pTarget); virtual void update(float time); virtual CCObject* copyWithZone(CCZone* pZone); public: //創建一個重新排列格子的動畫:參一為,參二為格子大小,參三為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCShuffleTiles* actionWithSeed(int s, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCShuffleTiles* create(int s, const ccGridSize& gridSize, float duration); protected: // int m_nSeed; unsigned int m_nTilesCount; int *m_pTilesOrder; Tile *m_pTiles; }; //創建一個重新排列格子的動畫:參一為,參二為格子大小,參三為動畫時長。 CCShuffleTiles* CCShuffleTiles::actionWithSeed(int s, const ccGridSize& gridSize, float duration) { return CCShuffleTiles::create(s, gridSize, duration); } //上面的create實現。 CCShuffleTiles* CCShuffleTiles::create(int s, const ccGridSize& gridSize, float duration) { //new ,初始化,autorelease,失敗處理一條龍! CCShuffleTiles *pAction = new CCShuffleTiles(); if (pAction) { if (pAction->initWithSeed(s, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化處理。 bool CCShuffleTiles::initWithSeed(int s, const ccGridSize& gridSize, float duration) { //先調用基類的相應函數。 if (CCTiledGrid3DAction::initWithSize(gridSize, duration)) { //將參數值保存到成員變數中。 m_nSeed = s; m_pTilesOrder = NULL; m_pTiles = NULL; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCShuffleTiles::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCShuffleTiles* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCShuffleTiles*)(pZone->m_pCopyObject); } else { pCopy = new CCShuffleTiles(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithSeed(m_nSeed, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //析構。 CCShuffleTiles::~CCShuffleTiles(void) { //釋放申請的內存。 CC_SAFE_DELETE_ARRAY(m_pTilesOrder); CC_SAFE_DELETE_ARRAY(m_pTiles); } //重新隨機排列處理。 void CCShuffleTiles::shuffle(int *pArray, unsigned int nLen) { //定義臨時變數,並循環進行隨機排列。 int i; for( i = nLen - 1; i >= 0; i-- ) { unsigned int j = rand() % (i+1); //隨機交換 int v = pArray[i]; pArray[i] = pArray[j]; pArray[j] = v; } } //取得 ccGridSize CCShuffleTiles::getDelta(const ccGridSize& pos) { CCPoint pos2; //計算格子的位置索引 unsigned int idx = pos.x * m_sGridSize.y + pos.y; //取出 pos2.x = (float)(m_pTilesOrder[idx] / (int)m_sGridSize.y); pos2.y = (float)(m_pTilesOrder[idx] % (int)m_sGridSize.y); // return ccg((int)(pos2.x - pos.x), (int)(pos2.y - pos.y)); } //替換指定格子中的數據 void CCShuffleTiles::placeTile(const ccGridSize& pos, Tile *t) { //取得對應格子大小的原始頂點數據 ccQuad3 coords = originalTile(pos); //取得演員所用格子數據中格子的間隔。 CCPoint step = m_pTarget->getGrid()->getStep(); //計算出對應位置。 coords.bl.x += (int)(t->position.x * step.x); coords.bl.y += (int)(t->position.y * step.y); coords.br.x += (int)(t->position.x * step.x); coords.br.y += (int)(t->position.y * step.y); coords.tl.x += (int)(t->position.x * step.x); coords.tl.y += (int)(t->position.y * step.y); coords.tr.x += (int)(t->position.x * step.x); coords.tr.y += (int)(t->position.y * step.y); //設置對應格子的數據。 setTile(pos, coords); } //設置演示當前動畫的演員。 void CCShuffleTiles::startWithTarget(CCNode *pTarget) { //調用基類的相應函數。 CCTiledGrid3DAction::startWithTarget(pTarget); //如果m_nSeed有效,則做為隨機種子。 if (m_nSeed != -1) { srand(m_nSeed); } //創建索引數組m_pTilesOrder m_nTilesCount = m_sGridSize.x * m_sGridSize.y; m_pTilesOrder = new int[m_nTilesCount]; int i, j; unsigned int k; //將順序索引填充到m_pTilesOrder for (k = 0; k < m_nTilesCount; ++k) { m_pTilesOrder[k] = k; } //對順序索引數組進行重新隨機排序。 shuffle(m_pTilesOrder, m_nTilesCount); //創建格子數據。 m_pTiles = (struct Tile *)new Tile[m_nTilesCount]; Tile *tileArray = (Tile*) m_pTiles; //雙循環遍歷,通過結構指針設置相應格子的數據。 for (i = 0; i < m_sGridSize.x; ++i) { for (j = 0; j < m_sGridSize.y; ++j) { tileArray->position = ccp((float)i, (float)j); tileArray->startPosition = ccp((float)i, (float)j); tileArray->delta = getDelta(ccg(i, j)); ++tileArray; } } } //更新動畫。 void CCShuffleTiles::update(float time) { int i, j; //取得格子的數據指針。 Tile *tileArray = (Tile*)m_pTiles; //雙循環遍歷。 for (i = 0; i < m_sGridSize.x; ++i) { for (j = 0; j < m_sGridSize.y; ++j) { //重新計算格子位置。 tileArray->position = ccpMult(ccp((float)tileArray->delta.x, (float)tileArray->delta.y), time); //將指針數據填充到對應格子。 placeTile(ccg(i, j), tileArray); ++tileArray; } } } 對應圖:
//從右上角開始漸隱格子的動畫。 class CC_DLL CCFadeOutTRTiles : public CCTiledGrid3DAction { public: //為了檢測是否滿足相應條件的函數。 virtual float testFunc(const ccGridSize& pos, float time); //開啟格子。 void turnOnTile(const ccGridSize& pos); //關閉格子。 void turnOffTile(const ccGridSize& pos); //跟據距離轉換格子。 virtual void transformTile(const ccGridSize& pos, float distance); //更新動畫。 virtual void update(float time); public: //靜態函數:創建一個從右上角漸隱格子的動畫。參一為格子大小,參二為。 CC_DEPRECATED_ATTRIBUTE static CCFadeOutTRTiles* actionWithSize(const ccGridSize& gridSize, float time); //上面的create實現。 static CCFadeOutTRTiles* create(const ccGridSize& gridSize, float time); }; //靜態函數:創建一個從右上角漸隱格子的動畫。參一為格子大小,參二為。 CCFadeOutTRTiles* CCFadeOutTRTiles::actionWithSize(const ccGridSize& gridSize, float time) { return CCFadeOutTRTiles::create( gridSize, time); } //上面的create實現。 CCFadeOutTRTiles* CCFadeOutTRTiles::create(const ccGridSize& gridSize, float time) { //new,初始化,autorelease,失敗處理一條龍! CCFadeOutTRTiles *pAction = new CCFadeOutTRTiles(); if (pAction) { if (pAction->initWithSize(gridSize, time)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //為了檢測是否滿足相應條件的函數。 float CCFadeOutTRTiles::testFunc(const ccGridSize& pos, float time) { //計算出格子的位置。 CCPoint n = ccpMult(ccp((float)m_sGridSize.x, (float)m_sGridSize.y), time); //為了後面powf中的除法避免除零而做的判斷。 if ((n.x + n.y) == 0.0f) { return 1.0f; } //計算出一個powf處理后的值。 return powf((pos.x + pos.y) / (n.x + n.y), 6); } //開啟格子。 void CCFadeOutTRTiles::turnOnTile(const ccGridSize& pos) { //設置格子位置為原始數據。 setTile(pos, originalTile(pos)); } //關閉格子。 void CCFadeOutTRTiles::turnOffTile(const ccGridSize& pos) { //定義一個新的頂點數據,都清零後設置為對應格子的頂點數據。 ccQuad3 coords; memset(&coords, 0, sizeof(ccQuad3)); setTile(pos, coords); } //跟據距離轉換格子。 void CCFadeOutTRTiles::transformTile(const ccGridSize& pos, float distance) { //取得對應格子的頂點數據。 ccQuad3 coords = originalTile(pos); //取得每個像素所佔的圖像大小。 CCPoint step = m_pTarget->getGrid()->getStep(); //通過距離進行位置的重新計算。 coords.bl.x += (step.x / 2) * (1.0f - distance); coords.bl.y += (step.y / 2) * (1.0f - distance); coords.br.x -= (step.x / 2) * (1.0f - distance); coords.br.y += (step.y / 2) * (1.0f - distance); coords.tl.x += (step.x / 2) * (1.0f - distance); coords.tl.y -= (step.y / 2) * (1.0f - distance); coords.tr.x -= (step.x / 2) * (1.0f - distance); coords.tr.y -= (step.y / 2) * (1.0f - distance); //用新數據設置對應格子的頂點數據。 setTile(pos, coords); } //更新動畫。 void CCFadeOutTRTiles::update(float time) { int i, j; //雙循環遍歷。 for (i = 0; i < m_sGridSize.x; ++i) { for (j = 0; j < m_sGridSize.y; ++j) { //為了檢測是否滿足相應條件的函數,返回距離值。 float distance = testFunc(ccg(i, j), time); if ( distance == 0 ) { //如果距離為0,關閉格子。 turnOffTile(ccg(i, j)); } else if (distance < 1) { //如果距離在0~1間,進行格子的轉換處理。 transformTile(ccg(i, j), distance); } else { //如果距離大於等於1,開啟格子。 turnOnTile(ccg(i, j)); } } } } 對應圖:
//從左下角漸隱格子的動畫。 class CC_DLL CCFadeOutBLTiles : public CCFadeOutTRTiles { public: //檢測是否滿足相應條件的函數 virtual float testFunc(const ccGridSize& pos, float time); public: //靜態函數:創建一個從左下角漸隱格子的動畫。參一為格子大小,參二為。 CC_DEPRECATED_ATTRIBUTE static CCFadeOutBLTiles* actionWithSize(const ccGridSize& gridSize, float time); //上面的create實現。 static CCFadeOutBLTiles* create(const ccGridSize& gridSize, float time); }; // //靜態函數:創建一個從左下角漸隱格子的動畫。參一為格子大小,參二為。 CCFadeOutBLTiles* CCFadeOutBLTiles::actionWithSize(const ccGridSize& gridSize, float time) { return CCFadeOutBLTiles::create(gridSize, time); } //上面的create實現。 CCFadeOutBLTiles* CCFadeOutBLTiles::create(const ccGridSize& gridSize, float time) { //new ,初始化,autorelease,失敗處理一條龍! CCFadeOutBLTiles *pAction = new CCFadeOutBLTiles(); if (pAction) { if (pAction->initWithSize(gridSize, time)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //檢測是否滿足相應條件的函數 float CCFadeOutBLTiles::testFunc(const ccGridSize& pos, float time) { //計算出格子的位置。 CCPoint n = ccpMult(ccp((float)m_sGridSize.x, (float)m_sGridSize.y), (1.0f - time)); //為了後面powf中的除法避免除零而做的判斷。 if ((pos.x + pos.y) == 0) { return 1.0f; } //計算出一個powf處理后的值。 return powf((n.x + n.y) / (pos.x + pos.y), 6); } //向上部漸隱格子的動畫。 class CC_DLL CCFadeOutUpTiles : public CCFadeOutTRTiles { public: //檢測是否滿足相應條件的函數 virtual float testFunc(const ccGridSize& pos, float time); //跟據距離轉換格子。 virtual void transformTile(const ccGridSize& pos, float distance); public: //靜態函數:創建一個從上部漸隱格子的動畫。參一為格子大小,參二為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCFadeOutUpTiles* actionWithSize(const ccGridSize& gridSize, float time); //上面的create實現。 static CCFadeOutUpTiles* create(const ccGridSize& gridSize, float time); }; //靜態函數:創建一個從上部漸隱格子的動畫。參一為格子大小,參二為動畫時長。 CCFadeOutUpTiles* CCFadeOutUpTiles::actionWithSize(const ccGridSize& gridSize, float time) { return CCFadeOutUpTiles::create(gridSize, time); } //上面的create實現。 CCFadeOutUpTiles* CCFadeOutUpTiles::create(const ccGridSize& gridSize, float time) { //new ,初始化,autorelease,失敗處理一條龍! CCFadeOutUpTiles *pAction = new CCFadeOutUpTiles(); if (pAction) { if (pAction->initWithSize(gridSize, time)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //檢測是否滿足相應條件的函數 float CCFadeOutUpTiles::testFunc(const ccGridSize& pos, float time) { //計算出格子的位置。 CCPoint n = ccpMult(ccp((float)m_sGridSize.x, (float)m_sGridSize.y), time); //為了後面powf中的除法避免除零而做的判斷。 if (n.y == 0.0f) { return 1.0f; } //計算出一個powf處理后的值。 return powf(pos.y / n.y, 6); } //跟據距離轉換格子。 void CCFadeOutUpTiles::transformTile(const ccGridSize& pos, float distance) { //取得對應格子的頂點數據。 ccQuad3 coords = originalTile(pos); //取得一個格子所佔用的圖像大小。 CCPoint step = m_pTarget->getGrid()->getStep(); //通過距離進行位置的重新計算。 //讓格子的下部的Y值上移,上部的Y值下移,這樣格子就像被壓扁了一樣的效果。 coords.bl.y += (step.y / 2) * (1.0f - distance); coords.br.y += (step.y / 2) * (1.0f - distance); coords.tl.y -= (step.y / 2) * (1.0f - distance); coords.tr.y -= (step.y / 2) * (1.0f - distance); //設置格子的新位置。 setTile(pos, coords); } 對應圖:
//從左下角漸隱格子的動畫。 class CC_DLL CCFadeOutBLTiles : public CCFadeOutTRTiles { public: //檢測是否滿足相應條件的函數 virtual float testFunc(const ccGridSize& pos, float time); public: //靜態函數:創建一個從左下角漸隱格子的動畫。參一為格子大小,參二為。 CC_DEPRECATED_ATTRIBUTE static CCFadeOutBLTiles* actionWithSize(const ccGridSize& gridSize, float time); //上面的create實現。 static CCFadeOutBLTiles* create(const ccGridSize& gridSize, float time); }; // //靜態函數:創建一個從左下角漸隱格子的動畫。參一為格子大小,參二為。 CCFadeOutBLTiles* CCFadeOutBLTiles::actionWithSize(const ccGridSize& gridSize, float time) { return CCFadeOutBLTiles::create(gridSize, time); } //上面的create實現。 CCFadeOutBLTiles* CCFadeOutBLTiles::create(const ccGridSize& gridSize, float time) { //new ,初始化,autorelease,失敗處理一條龍! CCFadeOutBLTiles *pAction = new CCFadeOutBLTiles(); if (pAction) { if (pAction->initWithSize(gridSize, time)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //檢測是否滿足相應條件的函數 float CCFadeOutBLTiles::testFunc(const ccGridSize& pos, float time) { //計算出格子的位置。 CCPoint n = ccpMult(ccp((float)m_sGridSize.x, (float)m_sGridSize.y), (1.0f - time)); //為了後面powf中的除法避免除零而做的判斷。 if ((pos.x + pos.y) == 0) { return 1.0f; } //計算出一個powf處理后的值。 return powf((n.x + n.y) / (pos.x + pos.y), 6); }
對應圖:
//向上部漸隱格子的動畫。 class CC_DLL CCFadeOutUpTiles : public CCFadeOutTRTiles { public: //檢測是否滿足相應條件的函數 virtual float testFunc(const ccGridSize& pos, float time); //跟據距離轉換格子。 virtual void transformTile(const ccGridSize& pos, float distance); public: //靜態函數:創建一個從上部漸隱格子的動畫。參一為格子大小,參二為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCFadeOutUpTiles* actionWithSize(const ccGridSize& gridSize, float time); //上面的create實現。 static CCFadeOutUpTiles* create(const ccGridSize& gridSize, float time); }; //靜態函數:創建一個從上部漸隱格子的動畫。參一為格子大小,參二為動畫時長。 CCFadeOutUpTiles* CCFadeOutUpTiles::actionWithSize(const ccGridSize& gridSize, float time) { return CCFadeOutUpTiles::create(gridSize, time); } //上面的create實現。 CCFadeOutUpTiles* CCFadeOutUpTiles::create(const ccGridSize& gridSize, float time) { //new ,初始化,autorelease,失敗處理一條龍! CCFadeOutUpTiles *pAction = new CCFadeOutUpTiles(); if (pAction) { if (pAction->initWithSize(gridSize, time)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //檢測是否滿足相應條件的函數 float CCFadeOutUpTiles::testFunc(const ccGridSize& pos, float time) { //計算出格子的位置。 CCPoint n = ccpMult(ccp((float)m_sGridSize.x, (float)m_sGridSize.y), time); //為了後面powf中的除法避免除零而做的判斷。 if (n.y == 0.0f) { return 1.0f; } //計算出一個powf處理后的值。 return powf(pos.y / n.y, 6); } //跟據距離轉換格子。 void CCFadeOutUpTiles::transformTile(const ccGridSize& pos, float distance) { //取得對應格子的頂點數據。 ccQuad3 coords = originalTile(pos); //取得一個格子所佔用的圖像大小。 CCPoint step = m_pTarget->getGrid()->getStep(); //通過距離進行位置的重新計算。 //讓格子的下部的Y值上移,上部的Y值下移,這樣格子就像被壓扁了一樣的效果。 coords.bl.y += (step.y / 2) * (1.0f - distance); coords.br.y += (step.y / 2) * (1.0f - distance); coords.tl.y -= (step.y / 2) * (1.0f - distance); coords.tr.y -= (step.y / 2) * (1.0f - distance); //設置格子的新位置。 setTile(pos, coords); } 對應圖:
//向下部漸隱格子的動畫。 class CC_DLL CCFadeOutDownTiles : public CCFadeOutUpTiles { public: //檢測是否滿足相應條件的函數 virtual float testFunc(const ccGridSize& pos, float time); public: //靜態函數:創建一個從下部漸隱格子的動畫。參一為格子大小,參二為動畫時長。 CC_DEPRECATED_ATTRIBUTE static CCFadeOutDownTiles* actionWithSize(const ccGridSize& gridSize, float time); //上面的create實現。 static CCFadeOutDownTiles* create(const ccGridSize& gridSize, float time); }; //靜態函數:創建一個從下部漸隱格子的動畫。參一為格子大小,參二為動畫時長。 CCFadeOutDownTiles* CCFadeOutDownTiles::actionWithSize(const ccGridSize& gridSize, float time) { return CCFadeOutDownTiles::create(gridSize, time); } //上面的create實現。 CCFadeOutDownTiles* CCFadeOutDownTiles::create(const ccGridSize& gridSize, float time) { //new ,初始化,autorelease,失敗處理一條龍! CCFadeOutDownTiles *pAction = new CCFadeOutDownTiles(); if (pAction) { if (pAction->initWithSize(gridSize, time)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //檢測是否滿足相應條件的函數 float CCFadeOutDownTiles::testFunc(const ccGridSize& pos, float time) { //計算出格子的位置。 CCPoint n = ccpMult(ccp((float)m_sGridSize.x, (float)m_sGridSize.y), (1.0f - time)); //為了後面powf中的除法避免除零而做的判斷。 if (pos.y == 0) { return 1.0f; } //計算出一個powf處理后的值。 return powf(n.y / pos.y, 6); } 對應圖:
//格子的消失動畫 class CC_DLL CCTurnOffTiles : public CCTiledGrid3DAction { public: //析構 ~CCTurnOffTiles(void); //初始化 bool initWithSeed(int s, const ccGridSize& gridSize, float duration); //重新排列格子。 void shuffle(int *pArray, unsigned int nLen); //開啟格子。 void turnOnTile(const ccGridSize& pos); //關閉格子。 void turnOffTile(const ccGridSize& pos); //重載基類的相應函數。 virtual CCObject* copyWithZone(CCZone* pZone); virtual void startWithTarget(CCNode *pTarget); virtual void update(float time); public: //創建一個 CC_DEPRECATED_ATTRIBUTE static CCTurnOffTiles* actionWithSize(const ccGridSize& size, float d); // CC_DEPRECATED_ATTRIBUTE static CCTurnOffTiles* actionWithSeed(int s, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCTurnOffTiles* create(const ccGridSize& size, float d); //上面的create實現。 static CCTurnOffTiles* create(int s, const ccGridSize& gridSize, float duration); protected: int m_nSeed; unsigned int m_nTilesCount; int *m_pTilesOrder; }; //創建一個 CCTurnOffTiles* CCTurnOffTiles::actionWithSize(const ccGridSize& size, float d) { return CCTurnOffTiles::create( size, d); } //上面的create實現。 CCTurnOffTiles* CCTurnOffTiles::create(const ccGridSize& size, float d) { //new ,初始化,autorelease,失敗處理一條龍! CCTurnOffTiles* pAction = new CCTurnOffTiles(); if (pAction->initWithSize(size, d)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } return pAction; } //創建一個 CCTurnOffTiles* CCTurnOffTiles::actionWithSeed(int s, const ccGridSize& gridSize, float duration) { return CCTurnOffTiles::create(s, gridSize, duration); } //上面的create實現。 CCTurnOffTiles* CCTurnOffTiles::create(int s, const ccGridSize& gridSize, float duration) { //new ,初始化,autorelease,失敗處理一條龍! CCTurnOffTiles *pAction = new CCTurnOffTiles(); if (pAction) { if (pAction->initWithSeed(s, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCTurnOffTiles::initWithSeed(int s, const ccGridSize& gridSize, float duration) { //調用基類的相應函數。 if (CCTiledGrid3DAction::initWithSize(gridSize, duration)) { //保存參數到成員變數。 m_nSeed = s; m_pTilesOrder = NULL; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCTurnOffTiles::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCTurnOffTiles* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCTurnOffTiles*)(pZone->m_pCopyObject); } else { pCopy = new CCTurnOffTiles(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithSeed(m_nSeed, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //析構。 CCTurnOffTiles::~CCTurnOffTiles(void) { CC_SAFE_DELETE_ARRAY(m_pTilesOrder); } //重新隨機排列。 void CCTurnOffTiles::shuffle(int *pArray, unsigned int nLen) { //定義臨時變數,並循環進行隨機排列。 int i; for (i = nLen - 1; i >= 0; i--) { //隨機交換。 unsigned int j = rand() % (i+1); int v = pArray[i]; pArray[i] = pArray[j]; pArray[j] = v; } } //開啟格子 void CCTurnOffTiles::turnOnTile(const ccGridSize& pos) { //設置格子的數據為原始數據。 setTile(pos, originalTile(pos)); } //關閉格子。 void CCTurnOffTiles::turnOffTile(const ccGridSize& pos) { //定義一個新的頂點數據,都清零後設置為對應格子的頂點數據。 ccQuad3 coords; memset(&coords, 0, sizeof(ccQuad3)); setTile(pos, coords); } //設置演示當前動畫的演員。 void CCTurnOffTiles::startWithTarget(CCNode *pTarget) { // unsigned int i; //調用基類的相應函數。 CCTiledGrid3DAction::startWithTarget(pTarget); //初始化隨機種子。 if (m_nSeed != -1) { srand(m_nSeed); } //取得格子數量 m_nTilesCount = m_sGridSize.x * m_sGridSize.y; //創建相應大小的排序索引數組。 m_pTilesOrder = new int[m_nTilesCount]; //填充數據。 for (i = 0; i < m_nTilesCount; ++i) { m_pTilesOrder[i] = i; } //隨機排列格子。 shuffle(m_pTilesOrder, m_nTilesCount); } //更新動畫。 void CCTurnOffTiles::update(float time) { unsigned int i, l, t; //通過進度值計算要消失的格子的數量。 l = (int)(time * (float)m_nTilesCount); //遍歷每個格子 for( i = 0; i < m_nTilesCount; i++ ) { //取出順序索引,並計算出相應的格子位置。 t = m_pTilesOrder[i]; ccGridSize tilePos = ccg( t / m_sGridSize.y, t % m_sGridSize.y ); //如果當前索引i小於要消失的可子的數量值,關閉格子。 if ( i < l ) { turnOffTile(tilePos); } else { //開啟格子。 turnOnTile(tilePos); } } } 對應圖:
//波浪狀的格子動畫。 class CC_DLL CCWavesTiles3D : public CCTiledGrid3DAction { public: //取得和設置振幅。 inline float getAmplitude(void) { return m_fAmplitude; } inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //取得和設置頻率。 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化波浪狀網格的動畫 bool initWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration); //創建一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //靜態函數:創建一個當前類的實例對象指針,參數一為 CC_DEPRECATED_ATTRIBUTE static CCWavesTiles3D* actionWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCWavesTiles3D* create(int wav, float amp, const ccGridSize& gridSize, float duration); protected: int m_nWaves; //振幅。 float m_fAmplitude; //頻率。 float m_fAmplitudeRate; }; //靜態函數:創建一個當前類的實例對象指針,參數一為 CCWavesTiles3D* CCWavesTiles3D::actionWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration) { return CCWavesTiles3D::create(wav, amp, gridSize, duration); } //上面的create實現。 CCWavesTiles3D* CCWavesTiles3D::create(int wav, float amp, const ccGridSize& gridSize, float duration) { //new ,初始化,autorelease,失敗處理一條龍! CCWavesTiles3D *pAction = new CCWavesTiles3D(); if (pAction) { if (pAction->initWithWaves(wav, amp, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCWavesTiles3D::initWithWaves(int wav, float amp, const ccGridSize& gridSize, float duration) { //調用基類的初始化函數。 if (CCTiledGrid3DAction::initWithSize(gridSize, duration)) { //將相應參數保存到成員變數中。 m_nWaves = wav; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCWavesTiles3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCWavesTiles3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCWavesTiles3D*)(pZone->m_pCopyObject); } else { pCopy = new CCWavesTiles3D(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithWaves(m_nWaves, m_fAmplitude, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫。 void CCWavesTiles3D::update(float time) { int i, j; //雙循環遍歷。 for( i = 0; i < m_sGridSize.x; i++ ) { for( j = 0; j < m_sGridSize.y; j++ ) { //取得對應格子的頂點數據。 ccQuad3 coords = originalTile(ccg(i, j)); //重新設置頂點數據位置。 coords.bl.z = (sinf(time * (float)M_PI *m_nWaves * 2 + (coords.bl.y+coords.bl.x) * .01f) * m_fAmplitude * m_fAmplitudeRate ); coords.br.z = coords.bl.z; coords.tl.z = coords.bl.z; coords.tr.z = coords.bl.z; //將新的位置數據設置給相應格子。 setTile(ccg(i, j), coords); } } } 對應圖:
//跳動的格子動畫。 class CC_DLL CCJumpTiles3D : public CCTiledGrid3DAction { public: //取得跳動的範圍。 inline float getAmplitude(void) { return m_fAmplitude; } inline void setAmplitude(float fAmplitude) { m_fAmplitude = fAmplitude; } //取和和設置頻率。 inline float getAmplitudeRate(void) { return m_fAmplitudeRate; } inline void setAmplitudeRate(float fAmplitudeRate) { m_fAmplitudeRate = fAmplitudeRate; } //初始化。 bool initWithJumps(int j, float amp, const ccGridSize& gridSize, float duration); //創建一個當前類的實例拷貝。 virtual CCObject* copyWithZone(CCZone* pZone); //更新動畫。 virtual void update(float time); public: //靜態函數:創建一個當前類的動畫實例。 CC_DEPRECATED_ATTRIBUTE static CCJumpTiles3D* actionWithJumps(int j, float amp, const ccGridSize& gridSize, float duration); //上面的create實現。 static CCJumpTiles3D* create(int j, float amp, const ccGridSize& gridSize, float duration); protected: //跳躍的次數。 int m_nJumps; //振幅。 float m_fAmplitude; //頻率。 float m_fAmplitudeRate; }; //靜態函數:創建一個當前類的動畫實例。 CCJumpTiles3D* CCJumpTiles3D::actionWithJumps(int j, float amp, const ccGridSize& gridSize, float duration) { return CCJumpTiles3D::create(j, amp, gridSize, duration); } //上面的create實現。 CCJumpTiles3D* CCJumpTiles3D::create(int j, float amp, const ccGridSize& gridSize, float duration) { //new ,初始化,autorelease,失敗處理一條龍! CCJumpTiles3D *pAction = new CCJumpTiles3D(); if (pAction) { if (pAction->initWithJumps(j, amp, gridSize, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCJumpTiles3D::initWithJumps(int j, float amp, const ccGridSize& gridSize, float duration) { //調用基類的相應函數。 if (CCTiledGrid3DAction::initWithSize(gridSize, duration)) { //保存參數到成員變數。 m_nJumps = j; m_fAmplitude = amp; m_fAmplitudeRate = 1.0f; return true; } return false; } //產生一個當前類的實例拷貝。 CCObject* CCJumpTiles3D::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCJumpTiles3D* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCJumpTiles3D*)(pZone->m_pCopyObject); } else { pCopy = new CCJumpTiles3D(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithJumps(m_nJumps, m_fAmplitude, m_sGridSize, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //更新動畫。 void CCJumpTiles3D::update(float time) { int i, j; //定義兩個臨時變數,分別設置為不同的sin曲線變化值。 float sinz = (sinf((float)M_PI * time * m_nJumps * 2) * m_fAmplitude * m_fAmplitudeRate ); float sinz2 = (sinf((float)M_PI * (time * m_nJumps * 2 + 1)) * m_fAmplitude * m_fAmplitudeRate ); //雙循環遍歷。 for( i = 0; i < m_sGridSize.x; i++ ) { for( j = 0; j < m_sGridSize.y; j++ ) { //取得對應格子的頂點數據。 ccQuad3 coords = originalTile(ccg(i, j)); //(i+j)的值對2取模,可以實現上,下,左,右相鄰的Z值加成不同。 if ( ((i+j) % 2) == 0 ) { coords.bl.z += sinz; coords.br.z += sinz; coords.tl.z += sinz; coords.tr.z += sinz; } else { coords.bl.z += sinz2; coords.br.z += sinz2; coords.tl.z += sinz2; coords.tr.z += sinz2; } //將新的頂點數據設置給相應格子。 setTile(ccg(i, j), coords); } } } 對應圖:
//橫向分割的格子動畫。 class CC_DLL CCSplitRows : public CCTiledGrid3DAction { public : //初始化。 bool initWithRows(int nRows, float duration); //重載基類的相應函數。 virtual CCObject* copyWithZone(CCZone* pZone); virtual void update(float time); virtual void startWithTarget(CCNode *pTarget); public: //靜態函數:創建一個橫向分割的格子動畫。參一為橫向分的份數,參二為動畫時長。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCSplitRows* actionWithRows(int nRows, float duration); //上面的create實現。 static CCSplitRows* create(int nRows, float duration); protected: //切分的行數。 int m_nRows; //屏幕大小。 CCSize m_winSize; }; //靜態函數:創建一個橫向分割的格子動畫。參一為橫向分的份數,參二為動畫時長。內部調用create實現。 CCSplitRows* CCSplitRows::actionWithRows(int nRows, float duration) { return CCSplitRows::create(nRows, duration); } //上面的create實現。 CCSplitRows* CCSplitRows::create(int nRows, float duration) { //new ,初始化,autorelease,失敗處理一條龍! CCSplitRows *pAction = new CCSplitRows(); if (pAction) { if (pAction->initWithRows(nRows, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCSplitRows::initWithRows(int nRows, float duration) { //保存切分的份數。 m_nRows = nRows; //將切分的份數做為參數放在格子大小的Y值中初始化3D格子動畫。 return CCTiledGrid3DAction::initWithSize(ccg(1, nRows), duration); } //產生一個當前類的實例拷貝。 CCObject* CCSplitRows::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCSplitRows* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCSplitRows*)(pZone->m_pCopyObject); } else { pCopy = new CCSplitRows(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithRows(m_nRows, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //以置演示當前動畫的演員。 void CCSplitRows::startWithTarget(CCNode *pTarget) { CCTiledGrid3DAction::startWithTarget(pTarget); m_winSize = CCDirector::sharedDirector()->getWinSizeInPixels(); } //更新動畫。 void CCSplitRows::update(float time) { int j; //遍歷切分的格子。在初始化時說過格子大小的Y值中保存了切分的份數。 for (j = 0; j < m_sGridSize.y; ++j) { //通過格子的的索引取得原始的頂點位置。 ccQuad3 coords = originalTile(ccg(0, j)); //創建臨時變數保存方向。 float direction = 1; //對i取2的模,可使相鄰的切分塊方向不同。 if ( (j % 2 ) == 0 ) { direction = -1; } //根據方向來對頂點X值進行偏移。 coords.bl.x += direction * m_winSize.width * time; coords.br.x += direction * m_winSize.width * time; coords.tl.x += direction * m_winSize.width * time; coords.tr.x += direction * m_winSize.width * time; //設置格子的頂點數據,這樣就可以實現每個切分格子的運動了。 setTile(ccg(0, j), coords); } } 對應圖:
//縱向切分的格子運動動畫。 class CC_DLL CCSplitCols : public CCTiledGrid3DAction { public: //初始化。 bool initWithCols(int nCols, float duration); //重載基類的相應函數。 virtual CCObject* copyWithZone(CCZone* pZone); virtual void update(float time); virtual void startWithTarget(CCNode *pTarget); public: //靜態函數:創建一個縱向分割的格子動畫。參一為縱向切分的份數,參二為動畫時長。內部調用create實現。 CC_DEPRECATED_ATTRIBUTE static CCSplitCols* actionWithCols(int nCols, float duration); //上面的create實現。 static CCSplitCols* create(int nCols, float duration); protected: //切分的列數。 int m_nCols; //屏幕大小。 CCSize m_winSize; }; //靜態函數:創建一個縱向分割的格子動畫。參一為縱向切分的份數,參二為動畫時長。內部調用create實現。 CCSplitCols* CCSplitCols::actionWithCols(int nCols, float duration) { return CCSplitCols::create(nCols, duration); } //上面的create實現。 CCSplitCols* CCSplitCols::create(int nCols, float duration) { //new ,初始化,autorelease,失敗處理一條龍! CCSplitCols *pAction = new CCSplitCols(); if (pAction) { if (pAction->initWithCols(nCols, duration)) { pAction->autorelease(); } else { CC_SAFE_RELEASE_NULL(pAction); } } return pAction; } //初始化。 bool CCSplitCols::initWithCols(int nCols, float duration) { //保存切分的份數。 m_nCols = nCols; //將切分的份數做為參數放在格子大小的X值中初始化3D格子動畫。 return CCTiledGrid3DAction::initWithSize(ccg(nCols, 1), duration); } //產生一個當前類的實例拷貝。 CCObject* CCSplitCols::copyWithZone(CCZone *pZone) { CCZone* pNewZone = NULL; CCSplitCols* pCopy = NULL; if(pZone && pZone->m_pCopyObject) { pCopy = (CCSplitCols*)(pZone->m_pCopyObject); } else { pCopy = new CCSplitCols(); pZone = pNewZone = new CCZone(pCopy); } CCTiledGrid3DAction::copyWithZone(pZone); pCopy->initWithCols(m_nCols, m_fDuration); CC_SAFE_DELETE(pNewZone); return pCopy; } //設置演示當前動畫的演員。 void CCSplitCols::startWithTarget(CCNode *pTarget) { //調用基類的相應函數。 CCTiledGrid3DAction::startWithTarget(pTarget); //取得屏幕大小 m_winSize = CCDirector::sharedDirector()->getWinSizeInPixels(); } //更新動畫。 void CCSplitCols::update(float time) { int i; //遍歷切分的格子。在初始化時說過格子大小的X值中保存了切分的份數。 for (i = 0; i < m_sGridSize.x; ++i) { //通過格子的的索引取得原始的頂點位置。 ccQuad3 coords = originalTile(ccg(i, 0)); //創建臨時變數保存方向。 float direction = 1; //對i取2的模,可使相鄰的切分塊方向不同。 if ( (i % 2 ) == 0 ) { direction = -1; } //根據方向來對頂點Y值進行偏移。 coords.bl.y += direction * m_winSize.height * time; coords.br.y += direction * m_winSize.height * time; coords.tl.y += direction * m_winSize.height * time; coords.tr.y += direction * m_winSize.height * time; //設置格子的頂點數據,這樣就可以實現每個切分格子的運動了。 setTile(ccg(i, 0), coords); } } 對應圖:
最後我們來看一下EffectsTest的場景演示方面的代碼:
EffectsTest.h: //由TestScene派生出一個場景。 class EffectTestScene : public TestScene { public: //運行這個場景。 virtual void runThisTest(); }; //由CCLayerColor派生出一個TextLayer,用於演示各動畫效果。 class TextLayer : public CCLayerColor { protected: //UxString m_strTitle; public: TextLayer(void); ~TextLayer(void); void checkAnim(float dt); virtual void onEnter(); void restartCallback(CCObject* pSender); void nextCallback(CCObject* pSender); void backCallback(CCObject* pSender); void newScene(); static TextLayer* create(); };
對應CPP:
// enum { kTagTextLayer = 1, kTagBackground = 1, kTagLabel = 2, }; //動畫的索引 static int actionIdx=0; //效果標題列表。 static std::string effectsList[] = { "Shaky3D", "Waves3D", "FlipX3D", "FlipY3D", "Lens3D", "Ripple3D", "Liquid", "Waves", "Twirl", "ShakyTiles3D", "ShatteredTiles3D", "ShuffleTiles", "FadeOutTRTiles", "FadeOutBLTiles", "FadeOutUpTiles", "FadeOutDownTiles", "TurnOffTiles", "WavesTiles3D", "JumpTiles3D", "SplitRows", "SplitCols", "PageTurn3D", }; //由CCShaky3D派生出一個動畫演示。 class Shaky3DDemo : public CCShaky3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { //調用基類相應函數創建一個具體的動畫演示。 return CCShaky3D::create(5, false, ccg(15,10), t); } }; //由CCWaves3D派生出一個動畫演示。 class Waves3DDemo : public CCWaves3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { //調用基類相應函數創建一個具體的動畫演示。 return CCWaves3D::create(5, 40, ccg(15,10), t); } }; //由CCFlipX3D派生出一個動畫演示。 class FlipX3DDemo : public CCFlipX3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCFlipX3D* flipx = CCFlipX3D::create(t); CCActionInterval* flipx_back = flipx->reverse(); CCDelayTime* delay = CCDelayTime::create(2); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(flipx, delay, flipx_back, NULL)); } }; //由CCFlipY3D派生出一個動畫演示。 class FlipY3DDemo : public CCFlipY3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCFlipY3D* flipy = CCFlipY3D::create(t); CCActionInterval* flipy_back = flipy->reverse(); CCDelayTime* delay = CCDelayTime::create(2); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(flipy, delay, flipy_back, NULL)); } }; //由CCLens3D派生出一個動畫演示。 class Lens3DDemo : public CCLens3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCSize size = CCDirector::sharedDirector()->getWinSize(); //調用基類相應函數創建一個具體的動畫演示。 return CCLens3D::create(CCPointMake(size.width/2,size.height/2), 240, ccg(15,10), t); } }; //由CCRipple3D派生出一個動畫演示。 class Ripple3DDemo : public CCRipple3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCSize size = CCDirector::sharedDirector()->getWinSize(); //調用基類相應函數創建一個具體的動畫演示。 return CCRipple3D::create(CCPointMake(size.width/2,size.height/2), 240, 4, 160, ccg(32,24), t); } }; //由CCLiquid派生出一個動畫演示。 class LiquidDemo : public CCLiquid { public: //重載其創建函數。 static CCActionInterval* create(float t) { //調用基類相應函數創建一個具體的動畫演示。 return CCLiquid::create(4, 20, ccg(16,12), t); } }; //由CCWaves派生出一個動畫演示。 class WavesDemo : public CCWaves { public: //重載其創建函數。 static CCActionInterval* create(float t) {//調用基類相應函數創建一個具體的動畫演示。 return CCWaves::create(4, 20, true, true, ccg(16,12), t); } }; //由CCTwirl派生出一個動畫演示。 class TwirlDemo : public CCTwirl { public: //重載其創建函數。 static CCActionInterval* create(float t) {//調用基類相應函數創建一個具體的動畫演示。 CCSize size = CCDirector::sharedDirector()->getWinSize(); return CCTwirl::create(CCPointMake(size.width/2, size.height/2), 1, 2.5f, ccg(12,8), t); } }; //由CCShakyTiles3D派生出一個動畫演示。 class ShakyTiles3DDemo : public CCShakyTiles3D { public: //重載其創建函數。 static CCActionInterval* create(float t) {//調用基類相應函數創建一個具體的動畫演示。 return CCShakyTiles3D::create(5, false, ccg(16,12), t) ; } }; //由CCShatteredTiles3D派生出一個動畫演示。 class ShatteredTiles3DDemo : public CCShatteredTiles3D { public: //重載其創建函數。 static CCActionInterval* create(float t) {//調用基類相應函數創建一個具體的動畫演示。 return CCShatteredTiles3D::create(5, false, ccg(16,12), t); } }; //由CCShuffleTiles派生出一個動畫演示。 class ShuffleTilesDemo : public CCShuffleTiles { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCShuffleTiles* shuffle = CCShuffleTiles::create(25, ccg(16,12), t); CCActionInterval* shuffle_back = shuffle->reverse(); CCDelayTime* delay = CCDelayTime::create(2); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(shuffle, delay, shuffle_back, NULL)); } }; //由CCFadeOutTRTiles派生出一個動畫演示。 class FadeOutTRTilesDemo : public CCFadeOutTRTiles { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCFadeOutTRTiles* fadeout = CCFadeOutTRTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); } }; //由CCFadeOutBLTiles派生出一個動畫演示。 class FadeOutBLTilesDemo : public CCFadeOutBLTiles { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCFadeOutBLTiles* fadeout = CCFadeOutBLTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); } }; //由CCFadeOutUpTiles派生出一個動畫演示。 class FadeOutUpTilesDemo : public CCFadeOutUpTiles { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCFadeOutUpTiles* fadeout = CCFadeOutUpTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); } }; //由CCFadeOutDownTiles派生出一個動畫演示。 class FadeOutDownTilesDemo : public CCFadeOutDownTiles { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCFadeOutDownTiles* fadeout = CCFadeOutDownTiles::create(ccg(16,12), t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); } }; //由CCTurnOffTiles派生出一個動畫演示。 class TurnOffTilesDemo : public CCTurnOffTiles { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCTurnOffTiles* fadeout = CCTurnOffTiles::create(25, ccg(48,32) , t); CCActionInterval* back = fadeout->reverse(); CCDelayTime* delay = CCDelayTime::create(0.5f); //調用基類相應函數創建一個具體的動畫演示。 return (CCActionInterval*)(CCSequence::create(fadeout, delay, back, NULL)); } }; //由CCWavesTiles3D派生出一個動畫演示。 class WavesTiles3DDemo : public CCWavesTiles3D { public: //重載其創建函數。 static CCActionInterval* create(float t) {//調用基類相應函數創建一個具體的動畫演示。 return CCWavesTiles3D::create(4, 120, ccg(15,10), t); } }; //由CCJumpTiles3D派生出一個動畫演示。 class JumpTiles3DDemo : public CCJumpTiles3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { CCSize size = CCDirector::sharedDirector()->getWinSize(); //調用基類相應函數創建一個具體的動畫演示。 return CCJumpTiles3D::create(2, 30, ccg(15,10), t); } }; //由CCSplitRows派生出一個動畫演示。 class SplitRowsDemo : public CCSplitRows { public: //重載其創建函數。 static CCActionInterval* create(float t) { //調用基類相應函數創建一個具體的動畫演示。 return CCSplitRows::create(9, t); } }; //由CCSplitCols派生出一個動畫演示。 class SplitColsDemo : public CCSplitCols { public: //重載其創建函數。 static CCActionInterval* create(float t) { //調用基類相應函數創建一個具體的動畫演示。 return CCSplitCols::create(9, t); } }; //由CCPageTurn3D派生出一個動畫演示。 class PageTurn3DDemo : public CCPageTurn3D { public: //重載其創建函數。 static CCActionInterval* create(float t) { //調用基類相應函數創建一個具體的動畫演示。 CCDirector::sharedDirector()->setDepthTest(true); return CCPageTurn3D::create(ccg(15,10), t); } }; #define MAX_LAYER 22 //創建相應的效果。 CCActionInterval* createEffect(int nIndex, float t) { //設置 CCDirector::sharedDirector()->setDepthTest(false); //根據索引來創建相應的動畫實例。 switch(nIndex) { case 0: return Shaky3DDemo::create(t); case 1: return Waves3DDemo::create(t); case 2: return FlipX3DDemo::create(t); case 3: return FlipY3DDemo::create(t); case 4: return Lens3DDemo::create(t); case 5: return Ripple3DDemo::create(t); case 6: return LiquidDemo::create(t); case 7: return WavesDemo::create(t); case 8: return TwirlDemo::create(t); case 9: return ShakyTiles3DDemo::create(t); case 10: return ShatteredTiles3DDemo::create(t); case 11: return ShuffleTilesDemo::create(t); case 12: return FadeOutTRTilesDemo::create(t); case 13: return FadeOutBLTilesDemo::create(t); case 14: return FadeOutUpTilesDemo::create(t); case 15: return FadeOutDownTilesDemo::create(t); case 16: return TurnOffTilesDemo::create(t); case 17: return WavesTiles3DDemo::create(t); case 18: return JumpTiles3DDemo::create(t); case 19: return SplitRowsDemo::create(t); case 20: return SplitColsDemo::create(t); case 21: return PageTurn3DDemo::create(t); } return NULL; } //取得相應的動畫。 CCActionInterval* getAction() { CCActionInterval* pEffect = createEffect(actionIdx, 3); return pEffect; } //運行當前的場景。 void EffectTestScene::runThisTest() { //創建一個當前的動畫演示層放入場景,並運行這個場景。 addChild(TextLayer::create()); CCDirector::sharedDirector()->replaceScene(this); } #define SID_RESTART 1 //構造函數。 TextLayer::TextLayer(void) { //調用基類LayerColor的初始化函數,設置當前層的背景色。 initWithColor( ccc4(32,128,32,255) ); // float x,y; //取得屏幕大小。 CCSize s = CCDirector::sharedDirector()->getWinSize(); x = s.width; y = s.height; //創建一個節點。 CCNode* node = CCNode::create(); //創建一個動畫。 CCActionInterval* effect = getAction(); //將動畫綁定到這個節點上。 node->runAction(effect); //將這個節點再放入到當前層中。 addChild(node, 0, kTagBackground); //創建第一個精靈做為背景。 CCSprite *bg = CCSprite::create(s_back3); node->addChild(bg, 0); // bg->setAnchorPoint( CCPointZero ); bg->setPosition(ccp(s.width/2, s.height/2)); //創建第二個精靈(女一號)。 CCSprite* grossini = CCSprite::create(s_pPathSister2); node->addChild(grossini, 1); grossini->setPosition( CCPointMake(x/3,y/2) ); //創建一個縮放動畫及對應的反向動畫。 CCActionInterval* sc = CCScaleBy::create(2, 5); CCActionInterval* sc_back = sc->reverse(); //讓第二個精靈運行相應的動畫序列。 grossini->runAction( CCRepeatForever::create((CCActionInterval*)(CCSequence::create(sc, sc_back, NULL)) ) ); //創建第三個精靈。(女二號) CCSprite* tamara = CCSprite::create(s_pPathSister1); node->addChild(tamara, 1); tamara->setPosition( CCPointMake(2*x/3,y/2) ); //創建一個縮放動畫及對應的反向動畫。 CCActionInterval* sc2 = CCScaleBy::create(2, 5); CCActionInterval* sc2_back = sc2->reverse(); //讓第三個精靈運行相應的動畫序列。tamara->runAction( CCRepeatForever::create((CCActionInterval*)(CCSequence::create(sc2, sc2_back, NULL))) ); //創建一個文字標籤。 CCLabelTTF* label = CCLabelTTF::create((effectsList[actionIdx]).c_str(), "Marker Felt", 32); //設置標籤的位置並放入當前層中。 label->setPosition( CCPointMake(x/2,y-80) ); addChild(label); label->setTag( kTagLabel ); //創建三個菜單按鈕分別代表運行上一個,重新運行當前動畫,運行下一個動畫。 CCMenuItemImage *item1 = CCMenuItemImage::create(s_pPathB1, s_pPathB2, this, menu_selector(TextLayer::backCallback) ); CCMenuItemImage *item2 = CCMenuItemImage::create(s_pPathR1, s_pPathR2, this, menu_selector(TextLayer::restartCallback) ); CCMenuItemImage *item3 = CCMenuItemImage::create(s_pPathF1, s_pPathF2, this, menu_selector(TextLayer::nextCallback) ); //由三個菜單按鈕創建菜單。 CCMenu *menu = CCMenu::create(item1, item2, item3, NULL); //設置相應菜單按鈕的位置。 menu->setPosition(CCPointZero); item1->setPosition(CCPointMake( s.width/2 - item2->getContentSize().width*2, item2->getContentSize().height/2)); item2->setPosition(CCPointMake( s.width/2, item2->getContentSize().height/2)); item3->setPosition(CCPointMake( s.width/2 + item2->getContentSize().width*2, item2->getContentSize().height/2)); //將菜單加入當前層中。 addChild(menu, 1); //對當前層調用一個函數。 schedule( schedule_selector(TextLayer::checkAnim) ); } //檢查動畫。 void TextLayer::checkAnim(float dt) { //取得對應結點。 CCNode* s2 = getChildByTag(kTagBackground); //判斷如果沒有正在運行中的動畫,並且其有格子數據,則將其格子數據釋放並置空。 if ( s2->numberOfRunningActions() == 0 && s2->getGrid() != NULL) s2->setGrid(NULL);; } //析構。 TextLayer::~TextLayer(void) { } //創建一個當前層的函數。 TextLayer* TextLayer::create() { TextLayer* pLayer = new TextLayer(); pLayer->autorelease(); return pLayer; } //當前層被載入時的處理。 void TextLayer::onEnter() { CCLayer::onEnter(); } //創建一個新場景。 void TextLayer::newScene() { CCScene* s = new EffectTestScene(); CCNode* child = TextLayer::create(); s->addChild(child); CCDirector::sharedDirector()->replaceScene(s); s->release(); } //重啟當前動畫演示。 void TextLayer::restartCallback(CCObject* pSender) { newScene(); } //前進到下一個動畫演示。 void TextLayer::nextCallback(CCObject* pSender) { // update the action index actionIdx++; actionIdx = actionIdx % MAX_LAYER; newScene(); } //回退到上一個動畫演示。 void TextLayer::backCallback(CCObject* pSender) { // update the action index actionIdx--; int total = MAX_LAYER; if( actionIdx < 0 ) actionIdx += total; newScene(); }
最後做個總結:
Cocos2d-x提供了屏幕畫面上的一些基於網格的動畫,首先將要渲染的畫面輸出到一張紋理上,然後跟據屏幕大小創建相應數量的網格,通過對於網格上的頂點進行改變,形成頂點的運動動畫,然後將紋理貼在網格上再繪製出來,就能夠出現很多屏幕特效了。
覺得怎麼樣?是不是恍然大悟呢?如果有這樣的感覺,則我的辛苦就沒有白費。
最後,祝大家快樂 !!