牛骨文教育服务平台(让学习变的简单)

由于项目需要实现翻牌的效果,所以自己在完成的过程中将这篇文章写下来,想想还是觉得有点艰辛。

开始在网上找解决的办法找了很久,基本上就是一种解决方案,就是用CCOrbitCamera这个Action类来模拟实现翻牌的效果。

但是我在使用的效果中始终不如人意。

用CCOrbitCamera类实现倒是能实现,但是如果将牌移动到左上、左下或者其他不在屏幕中心的位置那这个效果就不行了,翻牌的位置就错误了,类似3D的了。

找了半天终于知道是什么原因了,Cocos2dX里面有这样的一句话,

CCDirector::sharedDirector()->setProjection(kCCDirectorProjection3D);

就是这个3D,Cocos2DX支持透视投影和正交投影两种模式,于是乎我把kCCDirectorProjection3D改成kCCDirectorProjection2D,对了,有感觉了。

这样一设置翻牌的动作就不是3D感了,就是正常的这种翻牌的感觉了。

但是项目中其他的图片出现了锯齿,这就不能忍了。

在用了很多办法都不能消除锯齿的时候我尝试到去读Cocos2dx关于设置setProjection函数的内容,看是否能够将锯齿避免,让翻转变得自然。

最终我失败了,确实还是太菜了不行。

我于是找替代方案来实现翻牌的动作,就找到了CCScaleTo来实现,这过程确实还是比较艰辛。

下面我把两种方案的关键代码都贴出来,方便大家看看吧。

  1. 首先还是用CCOrbitCamera类实现翻牌的效果(我封装成了一个函数)。
void HelloWorld::showObtAniUseOrbitCamera( CCSize visibleSize )
{
	if (m_pCardFront != NULL){
		this->removeChild(m_pCardFront);
	}
	if (m_pCardBack != NULL){
		this->removeChild(m_pCardBack);
	}
	// 加载牌的正反两面
	m_pCardFront = CCSprite::create("CardFront.png");
	m_pCardBack  = CCSprite::create("CardBack.png");
	/*m_pCardFront->setPosition(ccp(visibleSize.width/2-100,visibleSize.height/2+100));
	m_pCardBack->setPosition(ccp(visibleSize.width/2-100,visibleSize.height/2+100));*/
	m_pCardFront->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));
	m_pCardBack->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));
	this->addChild(m_pCardFront,5);
	this->addChild(m_pCardBack,5);
	// 动画序列(延时,显示,延时,隐藏)
	CCSequence *pBackSeq = CCSequence::create(CCDelayTime::create(0.5f),CCShow::create(),CCDelayTime::create(0.5f),CCHide::create(),NULL);
	//持续时间、半径初始值、半径增量、仰角初始值、仰角增量、离x轴的偏移角、离x轴的偏移角的增量
	CCOrbitCamera *pBackCamera = CCOrbitCamera::create(1.0f, 1, 0, 0, -90, 0, 0);
	CCSpawn* pSpawnBack = CCSpawn::create(pBackSeq,pBackCamera,NULL);
	m_pCardBack->runAction(pSpawnBack);

	// 动画序列(延时,隐藏,延时,显示)
	CCSequence *pFrontSeq = CCSequence::create(CCDelayTime::create(0.5f),CCHide::create(),CCDelayTime::create(0.5f),CCShow::create(),NULL);
	CCOrbitCamera *pLandCamera = CCOrbitCamera::create(1.2f, 1, 0, 0, -360, 0, 0);
	CCSpawn* pSpawnFront = CCSpawn::create(pFrontSeq,pLandCamera,NULL);
	m_pCardFront->runAction(pSpawnFront);
}

上面的注释写得比较详尽了,其实不难,就是背面显示的时候把正面隐藏,正面显示了把背面隐藏,就是这么个事。
这里面有个-90,-360是旋转的角度,可以自己尝试改了看会有什么效果。

下面是运行的效果图:

就是这样由背面翻转到正面,但注意,在“3D模式”下,position是设置在屏幕中间才会有这个效果,如果设置在其他位置就不是这个效果了,可以自己试试。

如果设置成2D模式就不会有这个情况了,但是不知道你自己的项目图片会不会出现锯齿,出现锯齿的情况我没有找到解决的办法。

  1. 用CCScaleTo实现的翻转

就是因为有锯齿的情况出现我又没解决到,所以我在需找替代方案,于是乎找到了CCScaleTo来实现。

下面是关键的代码:

void HelloWorld::showObtAniUseScaleTo(CCSize visibleSize)
{
	if (m_pCardFront != NULL){
		this->removeChild(m_pCardFront);
	}
	if (m_pCardBack != NULL){
		this->removeChild(m_pCardBack);
	}
	// 加载牌的正反两面
	m_pCardFront = CCSprite::create("CardFront.png");
	m_pCardBack  = CCSprite::create("CardBack.png");
	// 把牌反转了
	m_pCardFront->setFlipX(true);
	m_pCardFront->setPosition(ccp(visibleSize.width/2-100,visibleSize.height/2+100));
	m_pCardBack->setPosition(ccp(visibleSize.width/2-100,visibleSize.height/2+100));
	this->addChild(m_pCardFront,5);
	this->addChild(m_pCardBack,5);
	// 动画序列(延时,隐藏,延时,隐藏)
	CCSequence *pBackSeq = CCSequence::create(CCDelayTime::create(0.5f),CCHide::create(),CCDelayTime::create(0.5f),CCHide::create(),NULL);
	CCScaleTo* pScaleBack = CCScaleTo::create(1.2f,-1,1);
	CCSpawn* pSpawnBack = CCSpawn::create(pBackSeq,pScaleBack,NULL);
	m_pCardBack->runAction(pSpawnBack);

	// 动画序列(延时,显示,延时,显示)
	CCSequence *pFrontSeq = CCSequence::create(CCDelayTime::create(0.5f),CCShow::create(),CCDelayTime::create(0.5f),CCShow::create(),NULL);
	CCScaleTo* pScaleFront = CCScaleTo::create(1.2f,-1,1);
	CCSpawn* pSpawnFront = CCSpawn::create(pFrontSeq,pScaleFront,NULL);
	m_pCardFront->runAction(pSpawnFront);
}

这里主要就是要先把牌的正面setFlipX(true)这个函数来翻转一下,然后再绕Y轴模拟个旋转出来,如果还是不怎么清楚还请看官自己写代码试试效果。
CCScaleTo参数的设置主要就是为了绕Y来旋转,具体的各种情况也可以自己试试效果,实践是检验真理的唯一标准嘛,可以设置成(1,1),(1,-1)等等试试效果。

好了,差不多就是这样一个情况。

可以自己试试写个HelloWord调效果,加深印象。