[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]

红孩儿Cocos2d-X学习园地QQ2群:44208467 加群写:Cocos2d-x 
红孩儿Cocos2d-X学习园地QQ群:249941957 [暂满]加群写:Cocos2d-x 

本章为我的Cocos2d-x教程一书初稿。望各位看官多提建议!

Cocos2d-x 2.0 网格动画深入分析

另:本章所用Cocos2d-x版本为:

cocos2d-2.0-x-2.0.2 @ Aug 30 2012

http://cn.cocos2d-x.org/download

        写在前面:请各位大大在转载博文时注明来源,红孩儿每天熬夜写博实属不易,但屡有一些同学拿来主义,把本博的文章去头掐尾,抹掉作者,然后赤裸裸的改成自已的 " 原创  ",实在令人气愤。在此特声明:本博博文,欢迎您收藏,转载,如果有需要,也可以借用段落或插图,请您经我同意,我不是一个刻板吝啬的人。但如果直接剽窃,我将奋起反击!

       

        在TestCpp中的EffectsTest示例中展示了一些屏幕特效,它是将屏幕划分为多个格子,并对这些格子进行了动画处理从而产生出相应的屏幕特效。今天我们来学习一下这些动画。

主要是涉及到以下几个文件:

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,zvertArray[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及其派生CCGrid3DCCTiledGrid3DCCGridBase的关键是处理了将屏幕渲染到纹理这个功能。

它有两个重要的函数:

//在渲染之前要做的处理。

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出一个CCGridActionCCGridAction *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 implementationCCAssert(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 CCGrid3DActionpublic://取得和设置振幅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 classpCopy = (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 classpCopy = (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 90float 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 Grida = ccg(0,0);b = ccg(0,1);c = ccg(1,0);d = ccg(1,1);x = x0;}else{// Reversed Gridc = 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 classpCopy = (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 Grida = ccg(0,0);b = ccg(0,1);c = ccg(1,0);d = ccg(1,1);y = y0;}else{// Reversed Gridb = 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-leftv = originalVertex(a);v.y = diff.y;v.z += diff.z;setVertex(a, v);// upper-leftv = originalVertex(b);v.y -= diff.y;v.z -= diff.z;setVertex(b, v);// bottom-rightv = originalVertex(c);v.y = diff.y;v.z += diff.z;setVertex(c, v);// upper-rightv = 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 classpCopy = (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 classpCopy = (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 classpCopy = (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 classpCopy = (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 classpCopy = (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 classpCopy = (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 classpCopy = (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 memberCCTiledGrid3DAction::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_pTilesOrderm_nTilesCount = m_sGridSize.x * m_sGridSize.y;m_pTilesOrder = new int[m_nTilesCount];int i, j;unsigned int k;//将顺序索引填充到m_pTilesOrderfor (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 indexactionIdx++;actionIdx = actionIdx % MAX_LAYER;newScene();
}
//回退到上一个动画演示。
void TextLayer::backCallback(CCObject* pSender)
{// update the action indexactionIdx--;int total = MAX_LAYER;if( actionIdx < 0 )actionIdx += total;    newScene();
} 

 最后做个总结:

 

     Cocos2d-x提供了屏幕画面上的一些基于网格的动画,首先将要渲染的画面输出到一张纹理上,然后跟据屏幕大小创建相应数量的网格,通过对于网格上的顶点进行改变,形成顶点的运动动画,然后将纹理贴在网格上再绘制出来,就能够出现很多屏幕特效了。

 

     觉得怎么样?是不是恍然大悟呢?如果有这样的感觉,则我的辛苦就没有白费。

     最后,祝大家元旦快乐!2013年新的一年有更大的飞跃!
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 通过sql注入窃取用户数据库信息

    一、SQL注入的定义SQL Injection ,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。SQL注入漏洞的危害是巨大的,常常会导致整个数据库被“脱裤”,尽管如此,SQL注入仍然是现在最常见的Web漏洞之一。二、实现SQL注入“脱…...

    2024/5/3 15:25:58
  2. 网文作者的三道坎

    分享17k创始人血酬2007年旧文,时隔已久,文中所言仍具有现实意义。▼(一)这是年前,我和一个作者讨论的时候,想写的东西。因为时间少,所以分段开始写。从一个最新最新的入站作者,到一个近乎于神的名家天王,能保证写一本红一本,这里面至少有三道坎。第一个,是签约并完成…...

    2024/4/18 11:06:38
  3. 服务器--Tomcat配置400/404/500自定义错误页面

    一、说明1、web系统开发过程中经常遇见400/404/500类型的错误页面,对于开发人员而言见到这种页面多了可能觉得问题不大,但是实际运用当中是面向客户的,需要配置一个合理的自定义错误页面。 2、本文只提Tomcat设置400/404/500自定义错误页面(推荐),Springmvc controller配…...

    2024/4/17 18:41:11
  4. 安全漏洞扫描之Sql注入解析

    对于Web系统,要防范Sql注入|XSS(跨站脚本攻击)等其他攻击,一般处理方法是针对攻击的关键子进行过滤。这里针对Sql注入和XSS攻击防范方法提供使用的说明。 一、Sql注入防范 1、过滤Sql关键字 大家都知道Web服务器核心实现就是Servlet技术,servlet的过滤器可以对请求Header,请…...

    2024/4/17 18:43:28
  5. Java源码解析视频

    spring源码解析:链接:https://pan.baidu.com/s/1SudihLhZAv5c2NMljbjCUA 提取码:or4n springmvc源码解析:链接:https://pan.baidu.com/s/1g3AElydxL5eloww1pwcm_w 提取码:igpc mybatis源码解析链接:https://pan.baidu.com/s/18436lc6QD4KuqaCZN7IYyw 提取码:m052...

    2024/4/20 7:38:35
  6. web前端项目开发流程

    开发流程 图解需求 评审 召集需求涉及到的UI、开发、产品、测试人员整理业务流程,同步信息,明确分工 明确需求目的,考虑当前需求设计是否可满足目的 整理流程中如果涉及的其他人员,则召集商讨 如需求设计上影响现有业务功能,应要求产品重新设计实现方案,然后重新评审 注意…...

    2024/5/10 9:44:27
  7. Tomcat配置文件修改无效自动恢复还原的解决办法总结

    今天产品中集成一个报表,遇到诸多问题,其他一个很奇葩的问题就是,修改Tomcat几个配置文件,一直不起作用,启动调试了好几次才发现的,修改了一启动服务就恢复最初的配置信息了,真是奇葩。查了查知道原因了,因为我用的是eclipse,MyEclipse是不会遇到这个问题的,因为ecli…...

    2024/4/18 2:56:45
  8. DedeCMS反馈页面SQL注入漏洞

    DedeCMS反馈页面SQL注入漏洞描述: 目标网站存在SQL注入漏洞。 1.SQL注入攻击就是攻击者通过欺骗数据库服务器执行非授权的任意查询过程。 - 收起 2.漏洞形成原因:DedeCMS的plus\feedback.php中对变量 $typeid未做过滤,导致SQL注入漏洞。 危害: 被SQL注入后可能导致以下后果…...

    2024/4/25 6:00:32
  9. XNA Shader

    XNA Shader编程教程1-环境光照 Shader简史在DirectX8之前,GPU使用固定方式变换像素和顶点,即所谓的“固定管道”。这使得开发者不可能改变像素和顶点转化和处理的进程,使大多数游戏的图像表现看起来非常相。DirectX8提出了顶点和像素着色器,这让开发者可以在管道中决定如何…...

    2024/4/19 20:29:26
  10. Java架构师视频+授课资料

    近期整理了Java架构师相关视频和资料,供大家学习,获取链接在文末。若链接失效请留言. 一、视频部分截图二、资料部分截图链接:https://pan.baidu.com/s/1RHh5XsxJlMMRj3fejTKEdA 密码:79d6 欢迎加入公众号:三才猫,分享架构知识和阿里内推。...

    2024/4/17 18:43:10
  11. javascript前端开发环境sublime 配置

    当前eclipse 是 jsp的主要开发环境。但eclipse对javascript、html、css等格式的文件类型支持不够好。sublime 是非常流行的前端开发工具。在前端开发方面,它的语法高亮、代码折叠、插件支持做的非常优秀,有效地提高了开发效率。下面介绍下它的安装方法。详细步骤指南1.下载安…...

    2024/4/20 12:31:25
  12. 解决tomcat配置环境变量失败

    不能没有JAVA_HOME环境变量,不然即使java变量配置成功 start.bat也不能找到jdk...

    2024/4/18 16:15:11
  13. SQL注入攻击的原理及其防范措施

    ASP编程门槛很低,新手很容易上路。在一段不长的时间里,新手往往就已经能够编出看来比较完美的动态网站,在功能上,老手能做到的,新手也能够做到。那么新手与老手就没区别了吗?这里面区别可就大了,只不过外行人很难一眼就看出来罢了。在界面的友好性、运行性能以及网站的安…...

    2024/4/23 21:50:43
  14. SpringBoot内置tomcat配置SSL证书

    1.将阿里云域名 cyclothe.com 解析成www.cyclothe.com 到你的服务器下2.将域名对应的443 80 端口开发安全组, 浏览器默认对80端口隐藏3.去阿里云的域名中申请免费的ssl证书, 下载tomcat版4.将下载好的文件放到resource下5.配置你的yml文件:server:port: 443 #服务端口…...

    2024/4/20 4:38:19
  15. h5前端开发老师

    【兄弟连h5前端24小咨询热线:400-700-1307 QQ:3256649897 ◆学H5就找“兄弟连h5”◆】兄弟连web前端怎么样?兄弟连培训机构主要是针对无经验零基础的学员,h5前端开发老师,培训老师好坏看老师的培训实力,兄弟连H5前端老师都是刚从一线工作三年左右下来,并讲课一年是最合适…...

    2024/4/20 16:19:06
  16. Web常见安全漏洞-SQL注入

    SQL注入攻击(SQL Injection),简称注入攻击,是Web开发中最常见的一种安全漏洞。 可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作, 甚至有可能获取数据库乃至系统用户最高权限。而造成SQL注入的原因是因为程序没有有效过滤用…...

    2024/4/20 10:51:10
  17. python表白女神

    文章目录女神照片最终效果代码实现完整代码 明天就是情人节了,程序猿们肯定生活中被吐槽的不少,小编也经常被吐槽是直男,不会聊天,不浪漫等等。是不是觉得很憋屈呢,想当年我也是做过8x8x8的led表白神器的人。不过现在因为病毒的影响,大家身边应该没有这些硬件设施,那么今…...

    2024/4/20 13:37:44
  18. 64位系统,Tomcat配置成服务后,内存的修改

    前几天在搭建一个预发布环境,原先的系统用的32位,为了后面硬件扩展方便,系统选择了64位的,结果,结果将tomcat配置成服务后,想要修改内存,死活找不到:HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Procrun 2.0//Parameters/Java 问题卡了我好几天,终于通过…...

    2024/4/17 18:42:04
  19. 历史上留下浓重一笔的黑客们

    在互联网发展早期,黑客往往是一些因为兴趣而惹祸上身的天才少年,但随着互联网经济成为世界经济的重要一部分,让很多人对黑客产生了兴趣,因此今天很多黑客入侵电脑通常就是为了钱,而据一些专家表示,世界上一些顶级网络骗子每年收入可达一亿美元。为此国外网站businessinsi…...

    2024/4/17 18:43:05
  20. 【黑马程序员】登录时防止SQL注入漏洞攻击

    ----------------------Windows Phone 7手机开发、.Net培训、期待与您交流! ----------------------防止SQL注入漏洞攻击的方法:不使用SQL语句拼接,通过参数赋值。 使用SQL语句拼接时,用密码1 or 1=1,可以登录成功。所以为了网站的安全,还是通过参数赋值的方式来登陆。cl…...

    2024/4/18 10:05:58

最新文章

  1. 技术速递|Python in Visual Studio Code 2024年4月发布

    排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展 2024 年 4 月发布&#xff01; 此版本包括以下公告&#xff1a; 改进了 Flask 和 Django 的调试配置流程Jupyter Run Dependent Cells with Pylance 的模块和导入分析Hatch 环境发…...

    2024/5/10 11:09:08
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/9 21:23:04
  3. C++ //练习 11.14 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子的名和生日。

    C Primer&#xff08;第5版&#xff09; 练习 11.14 练习 11.14 扩展你在11.2.1节练习&#xff08;第378页&#xff09;中编写的孩子姓到名的map&#xff0c;添加一个pair的vector&#xff0c;保存孩子的名和生日。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#x…...

    2024/5/10 0:24:44
  4. 论文阅读AI工具链

    文献检索 可以利用智谱清言来生成合适的文献检索式&#xff0c;并根据需要不断调整。 谷歌学术 在Google Scholar中进行检索时&#xff0c;您可以使用类似的逻辑来构建您的搜索式&#xff0c;但是语法会有所不同。Google Scholar的搜索框接受普通的文本搜索&#xff0c;但是…...

    2024/5/10 0:16:27
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/9 15:10:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/10 10:22:18
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/9 17:11:10
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57