用遮罩实现扑克牌翻牌的效果

项目中要实现扑克牌随着手指翻牌的效果,当时想到的是利用类似帧动画来做,后面一个同事也提到可以用遮罩效果来实现,基本思路就是这两个了,一个是类似帧动画来实现,一个是遮罩实现;其实感觉还有更好的方式,就是OpenGL绘制实现,类似IOS和Android的翻书页效果,可惜能力有限;

类似帧动画的实现效果,算是比较简单的,但是有一个问题就是图片太多了,最后生成的包也太大了,所以中途也变成了用遮罩来实现,遮罩我也不太熟悉,有需要的可以看下网上其他资料,好了,不多说了,贴代码,里面有比较详细的注释,相信大家都看得懂的;

先是.h文件:

#ifndef POKEREFFECT_H

#define POKEREFFECT_H


#include "cocos2d.h"

USING_NS_CC;


class PokerEffect :public Layer

{

public:

   static PokerEffect * create();

   virtual bool init();

    

private:

   virtual void onEnter();

   bool onBegin(Touch * touch,Event * event);

   void onMoved(Touch * touch,Event * event);

   void onEnded(Touch * touch,Event * event);

    

public:

   Sprite * maskedSpriteWithSprite(Sprite * textureSprite,Sprite * maskSprite, float Ratio);

    

private:

   Sprite * mMaskedCal;//被遮罩出来的精灵

   Sprite * mEffectSprite;//特效精灵

   Size mVisibleSize;//屏幕可视的大小

   float mOffset;// 手指点击的偏移

    

   Point mTouchPoint;//手指点击的坐标

   Point mSpritePoint;//精灵的坐标

   Point mFirstTouchPoint;//触屏的第一个点坐标

   Point mFirstImagePoint;//第一张图片的大小

    

   std::vector<float>  mOffsetPoint;//横向手指偏移量数组

   std::vector<float>  mMaskRatio;//横向遮罩比例

   std::vector<float>  mVerticalPoint;//竖向手指偏移量数组

   std::vector<float>  mVerticalMaskRatio;//竖向遮罩比例

    

   ssize_t mIsRefresh;//是否刷新

   bool isHorizontal;//是否横、竖

   bool isRotation;//是否旋转

    

   void initVector();//容器数值初始化

   void setCardPokerEffect(int i,bool isHorizontal);//横向或竖向翻牌

   void setCardRotation(Touch * touch);//牌旋转

};



#endif //


再是.cpp文件:

#include "PokerEffect.h"


PokerEffect* PokerEffect::create()

{

PokerEffect* pRet =new PokerEffect();

if (pRet && pRet->init())

{

pRet->autorelease();

return pRet;

}

else

{

delete pRet;

pRet =NULL;

returnNULL;

}

}


bool PokerEffect::init()

{

if (!Layer::init())

{

returnfalse;

}


mVisibleSize =Director::getInstance()->getWinSize();

    isHorizontal =true;

    isRotation = true;

    

Sprite * oo =Sprite::create("background.jpg");

oo -> setPosition(mVisibleSize.width /2, mVisibleSize.height /2);

oo -> setScale(mVisibleSize.height / oo->getContentSize().height);

this ->addChild(oo);


    initVector();

    

    mIsRefresh = 0;

    

    mEffectSprite =Sprite::create("01.png");

mEffectSprite ->setAnchorPoint(Point(0,1));

mEffectSprite ->setPosition(mVisibleSize.width /2 - mEffectSprite -> getContentSize().width /2, mVisibleSize.height /2 + mEffectSprite -> getContentSize().height /2);

mFirstImagePoint =mEffectSprite -> getPosition();

this ->addChild(mEffectSprite);


EventListenerTouchOneByOne * listener =EventListenerTouchOneByOne::create();

listener -> setSwallowTouches(true);

listener ->onTouchBegan = CC_CALLBACK_2(PokerEffect::onBegin,this);

listener ->onTouchMoved = CC_CALLBACK_2(PokerEffect::onMoved,this);

listener ->onTouchEnded = CC_CALLBACK_2(PokerEffect::onEnded,this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);


returntrue;

}


boolPokerEffect::onBegin(Touch * touch,Event * event)

{

mTouchPoint = touch ->getLocation();

    setCardRotation(touch);

    

returntrue;

}

voidPokerEffect::onMoved(Touch * touch,Event * event)

{

mOffset = touch->getLocation().y -mTouchPoint.y ;

int i =0;


if (mOffset >0)

{

for (; i <mOffsetPoint.size(); i++)

{

if (mOffset <=mOffsetPoint.at(i))

break;

}

}


if (mIsRefresh == i)

return;


    if (mSpritePoint.y <=mFirstTouchPoint.y < (mSpritePoint.y +mEffectSprite -> getContentSize().height /10)) {

        setCardPokerEffect(i,isHorizontal);

    }

}


voidPokerEffect::onEnded(Touch * touch,Event * event)

{

}


voidPokerEffect::onEnter()

{

Layer::onEnter();


mMaskedCal =this -> maskedSpriteWithSprite(

Sprite::create("01.png"), 

Sprite::create("mask_bg.png")

,1);

mMaskedCal ->setPosition(mVisibleSize.width /2, mVisibleSize.height /2);

mMaskedCal ->setVisible(false);

this ->addChild(mMaskedCal);

// mMaskedCal -> setTag(101);


}


// 设置牌旋转

voidPokerEffect::setCardRotation(Touch * touch)

{

//    mTouchPoint = Point(0, touch -> getLocation().y - mOffsetPoint.at(mIsRefresh));

   mFirstTouchPoint = touch -> getLocation();

    mSpritePoint =Director :: getInstance() ->convertToGL(mEffectSprite ->getPosition());

    

    if (mFirstTouchPoint.y >= (mSpritePoint.y + mEffectSprite -> getContentSize().height /5)

        && mEffectSprite ->getBoundingBox().containsPoint(mFirstTouchPoint)) {

       if (isRotation) {

           if (isHorizontal) {

                mEffectSprite ->setPosition(Point(mVisibleSize.width /2 + mEffectSprite -> getContentSize().width /3, mVisibleSize.height /2 + mEffectSprite -> getContentSize().height /2));

               mEffectSprite -> setRotation(90);

               mEffectSprite -> setTag(1);

               isHorizontal = false;

                

            }else {

               this -> removeChildByTag(1);

               this -> removeChildByTag(2);

               mEffectSprite = Sprite::create("01.png");

               mEffectSprite -> setAnchorPoint(Point(0,1));

                mEffectSprite ->setPosition(mVisibleSize.width /2 - mEffectSprite -> getContentSize().width /2, mVisibleSize.height /2 + mEffectSprite -> getContentSize().height /2);

                mFirstImagePoint =mEffectSprite -> getPosition();

               this -> addChild(mEffectSprite);

               isHorizontal = true;

            }

        }

    }

    

}


// 设置翻牌的动画

voidPokerEffect::setCardPokerEffect(int i,bool isHorizontal)

{

   if (i < 10)

    {

       if (i < 1) {

           isRotation = true;

        }else {

           isRotation = false;

        }

        

       mIsRefresh = i;

       if (isHorizontal) {

           mEffectSprite -> removeFromParent();

           mEffectSprite = Sprite::create(String::createWithFormat("%02d.png", i + 1) -> getCString());

           mEffectSprite -> setAnchorPoint(Point(0,1));

            mEffectSprite ->setPosition(mFirstImagePoint);

           this -> addChild(mEffectSprite);

            

           mMaskedCal -> removeFromParent();

            mMaskedCal =this -> maskedSpriteWithSprite(

                                                       Sprite::create("J01.png"),

                                                       Sprite::create("mask_bg.png"),

                                                       mMaskRatio.at(i));

           mMaskedCal -> setAnchorPoint(Point(0,0));

            mMaskedCal ->setPosition(mFirstImagePoint.x, (mFirstImagePoint.y - mEffectSprite -> getContentSize().height) - (1 - mMaskRatio.at(i)) *mMaskedCal -> getContentSize().height /2);

           this->addChild(mMaskedCal);

            

        }else {

           mEffectSprite -> removeFromParent();

           mEffectSprite = Sprite::create(String::createWithFormat("p%02d.png", i + 1) -> getCString());

            mEffectSprite ->setPosition(Point(mVisibleSize.width /2 - mEffectSprite -> getContentSize().width /2, mFirstImagePoint.y));

           mEffectSprite -> setAnchorPoint(Point(0,1));

           mEffectSprite -> setTag(2);

           this -> addChild(mEffectSprite);

            

           mMaskedCal -> removeFromParent();

            mMaskedCal =this->maskedSpriteWithSprite(

                                                     Sprite::create("J02.png"),

                                                     Sprite::create("mask_bg_vert.png"),

                                                     mVerticalMaskRatio.at(i));

           mMaskedCal -> setAnchorPoint(Point(0,0.5));

            mMaskedCal ->setPosition(mVisibleSize.width /2 - mEffectSprite -> getContentSize().width /2 + 25,

                                     mEffectSprite -> getPosition().y -mEffectSprite -> getContentSize().height +mMaskedCal-> getContentSize().height *mVerticalMaskRatio.at(i) /2

                                      );

           this -> addChild(mMaskedCal);

            

        }

    }

}


// 初始化数值

voidPokerEffect::initVector()

{

    //横向手指移动的距离

    mOffsetPoint.push_back(0);

    mOffsetPoint.push_back(20);

    mOffsetPoint.push_back(90);

    mOffsetPoint.push_back(110);

    mOffsetPoint.push_back(150);

    mOffsetPoint.push_back(220);

    mOffsetPoint.push_back(270);

    mOffsetPoint.push_back(300);

    mOffsetPoint.push_back(310);

    

    // 横向偏移量

    mMaskRatio.push_back(0);

    mMaskRatio.push_back(0);

    mMaskRatio.push_back(0);

    mMaskRatio.push_back(0);

    mMaskRatio.push_back(0);

    mMaskRatio.push_back(0.075);

    mMaskRatio.push_back(0.175);

    mMaskRatio.push_back(0.3);

    mMaskRatio.push_back(0.475);

    mMaskRatio.push_back(1);

    

    //竖向手指移动的距离

    //   mVerticalPoint.push_back(0);

    //   mVerticalPoint.push_back(20);

    //   mVerticalPoint.push_back(70);

    //   mVerticalPoint.push_back(120);

    //   mVerticalPoint.push_back(200);

    //   mVerticalPoint.push_back(250);

    //   mVerticalPoint.push_back(300);

    //   mVerticalPoint.push_back(350);

    //   mVerticalPoint.push_back(400);

    

    // 竖向偏移量

    mVerticalMaskRatio.push_back(0);

    mVerticalMaskRatio.push_back(0);

    mVerticalMaskRatio.push_back(0);

    mVerticalMaskRatio.push_back(0.055);

    mVerticalMaskRatio.push_back(0.1);

    mVerticalMaskRatio.push_back(0.155);

    mVerticalMaskRatio.push_back(0.2);

    mVerticalMaskRatio.push_back(0.245);

    mVerticalMaskRatio.push_back(0.445);

    mVerticalMaskRatio.push_back(1);

}


// 创建遮罩

Sprite *PokerEffect::maskedSpriteWithSprite(Sprite *textureSprite,Sprite *maskSprite , float Ratio)

{


maskSprite->setPosition(textureSprite->getContentSize().width / 2, textureSprite->getContentSize().height /2);

maskSprite->setScaleY(Ratio);

Point textureSpritePoint =Point(textureSprite->getContentSize().width /2, textureSprite->getContentSize().height /2 * Ratio);

textureSprite->setPosition(textureSpritePoint);


    /*****************RenderTexture实现的四个步骤*****************/

    

    //1、创建RenderTexture类,以像素为单位,指定你想要绘制的纹理的宽度和高度

RenderTexture *rt =RenderTexture::create(textureSprite->getContentSize().width, maskSprite->getContentSize().height);


//2、调用RenderTexturebegin方法来初始化渲染操作

rt->begin();


    //{src color,destination color}   把将要画上去的颜色为源颜色,把原来的颜色称为目标颜色”,“目标颜色为屏幕:黑色,源颜色maskSprite(即白色的图片,但是四角Alpha值减小),{GL_ONE,GL_ZERO}可知目标颜色*GL_ZERO,源颜色*GL_ONE,得到的为源颜色

BlendFunc blenfuc1 = {GL_ONE, GL_ZERO };

maskSprite->setBlendFunc(blenfuc1);


    //“目标颜色为屏幕:上面计算后的颜色,源颜色textureSprite{GL_DST_ALPHA,GL_ZERO}可知目标颜色*GL_ZERO,源颜色*GL_DST_ALPHA(屏幕的Alpha值)

BlendFunc blenfuc2 = {GL_DST_ALPHA, GL_ZERO };

textureSprite->setBlendFunc(blenfuc2);


    //3、调用OpenGl函数来绘制实际的内容,这些OpenGl调用的最终都会绘制到屏幕之外去,而不会影响游戏中现在渲染的图像。

    //如果想要渲染一个节点的话,可以直接调用某个节点的visit方法,如sprite—>visit(),然后这个函数会自动发射一些OpenGl函数指针给图形硬件去显示

maskSprite->visit();

textureSprite->visit();

    

    //4、调用RenderTextureend方法来借宿绘制操作,一旦你完成之后,rendertexture有一个sprite属性,你可以把它当Sprite来用

    rt->end();

Sprite *retval =Sprite::createWithTexture(rt->getSprite()->getTexture());

retval->setFlippedY(true);//同时翻转y,因为纹理创建出来是倒的

    

return retval;

}


额,第一次写博客,不知道文件图片怎么弄,我把类文件和图片资源上传了,给个地址:http://download.csdn.net/detail/huluoboyou/7947075

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值