Cocos2d-x3.3RC0 tests-cpp分析之BillBoardTest

1、.h头文件

#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "VisibleRect.h"
USING_NS_CC;
using namespace ui;

class BillBoardDemo : public cocos2d::Layer
{
public:
    CREATE_FUNC(BillBoardDemo);
    virtual bool init();
    virtual void update(float dt) override;
    void addNewBillBoardWithCoords(Vec3 p);
    void addNewAniBillBoardWithCoords(Vec3 p);
    void rotateCameraCallback(Ref* sender,float value);
    void onTouchesMoved(const std::vector<Touch*>& touches,Event* event);
    
    void menuCallback_orientedPoint(Ref* sender);
    void menuCallback_orientedPlane(Ref* sender);
    
    BillBoardDemo();
    virtual ~BillBoardDemo();
    
protected:
    Camera*   _camera;
    Layer*    _layerBillBoard;
    std::vector<BillBoard*> _billboards;
};

2、.cpp文件

#include "BillBoardTest.h"

BillBoardDemo::BillBoardDemo()
:_camera(nullptr)
{

}

bool BillBoardDemo::init()
{
    bool bRet = false;
    do{
        CC_BREAK_IF(!Layer::init());
        
        //注册事件监听
        auto listener = EventListenerTouchAllAtOnce::create();
        listener->onTouchesMoved = CC_CALLBACK_2(BillBoardDemo::onTouchesMoved, this);//事件回调
        Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
        
        //添加层
        auto layer3D = Layer::create();
        addChild(layer3D,0);
        _layerBillBoard = layer3D;
        
        auto winSize = Director::getInstance()->getWinSize();
        //创建摄像机
        if(_camera == nullptr)
        {
            //参数1:透视相机的视野。参数2:相机的长宽比。参数3:近点平面距离。参数4:远点平面距离
            _camera = Camera::createPerspective(60, (GLfloat)winSize.width / winSize.height, 1, 500);
            _camera->setCameraFlag(CameraFlag::USER1);//设置相机Flag,便于相机识别节点
            _layerBillBoard->addChild(_camera);//相机加入层
        }
        
        std::string imgs[3] = {"Icon.png","r2.png"};
        for(unsigned int i = 0; i < 4; i++)
        {
            Layer* layer = Layer::create();
            //随机创建BillBoard对象
            auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1()*1+0.5)]);
            billboard->setScale(0.5);//设置缩放
            //CCRANDOM_MINUS1_1返回一个-1到1的float值
            billboard->setPosition3D(Vec3(0.0f,0.0f,CCRANDOM_MINUS1_1()*150.0f));//设置3D坐标
            //ALPHA_NON_PREMULTIPLIED混合方式 {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}
            //源因子使用源颜色的透明度,目标因子使用减去源颜色的透明度
            billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);//设置颜色混合
            billboard->setOpacity(CCRANDOM_0_1()*128+128);//设置可见性
            _billboards.push_back(billboard);
            layer->addChild(billboard);
            //1,层对象加入层
            _layerBillBoard->addChild(layer);//加入层
            layer->runAction(RepeatForever::create(RotateBy::create(CCRANDOM_0_1(),Vec3(0.0f,45.0f,0.0f))));//层执行翻转动作
        }
        {
            auto billboard = BillBoard::create("Icon.png");
            billboard->setScale(0.2f);
            billboard->setPosition3D(Vec3(0.0f,30.0f,0.0f));
            
            auto billboard2 = BillBoard::create("r2.png");
            billboard2->setPosition3D(Vec3(0.0f,0.0f,100.0f));
            billboard->addChild(billboard2);
            _billboards.push_back(billboard);
            _billboards.push_back(billboard2);
            
            auto sprite3D = Sprite3D::create("orc.c3t");
            sprite3D->setScale(2.0f);
            sprite3D->addChild(billboard);
            sprite3D->runAction(RepeatForever::create(RotateBy::create(10.0f, Vec3(0.0f,360.0f,0.0f))));
            //2,Sprite3D对象加入层
            _layerBillBoard->addChild(sprite3D);
        }
        
        //添加新的billboard
        addNewBillBoardWithCoords(Vec3(20,5,0));
        addNewBillBoardWithCoords(Vec3(60,5,0));
        addNewBillBoardWithCoords(Vec3(100,5,0));
        addNewBillBoardWithCoords(Vec3(140,5,0));
        addNewBillBoardWithCoords(Vec3(180,5,0));
        addNewAniBillBoardWithCoords(Vec3(-20,0,0));
        addNewAniBillBoardWithCoords(Vec3(-60,0,0));
        addNewAniBillBoardWithCoords(Vec3(-100,0,0));
        addNewAniBillBoardWithCoords(Vec3(-140,0,0));
        addNewAniBillBoardWithCoords(Vec3(-180,0,0));
        _camera->setPosition3D(Vec3(0,100,230));//设置相机的3D位置
        _camera->lookAt(Vec3(0,0,0), Vec3(0,1,0));//设置相机的,参数1:目标的中心位置,参数2:向上的向量
        
        
        //添加菜单
        TTFConfig ttfConfig("fonts/arial.ttf",30);
        auto label1 = Label::createWithTTF(ttfConfig, "rotate+");
        auto menuItem1 = MenuItemLabel::create(label1, CC_CALLBACK_1(BillBoardDemo::rotateCameraCallback, this,10));
        auto label2 = Label::createWithTTF(ttfConfig, "rotate-");
        auto menuItem2 = MenuItemLabel::create(label2, CC_CALLBACK_1(BillBoardDemo::rotateCameraCallback, this, -10));
        auto menu = Menu::create(menuItem1,menuItem2,nullptr);
        menu->setPosition(Vec2::ZERO);
        menuItem1->setPosition(Vec2(winSize.width - 80,VisibleRect::top().y - 160));
        menuItem2->setPosition(Vec2(winSize.width - 80,VisibleRect::top().y - 190));
        addChild(menu,0);
        _layerBillBoard->setCameraMask(2);//设置mask使得对相机可见
        
        //设置billboard观察模式
        label1 = Label::createWithTTF(ttfConfig, "Point Oriented");
        menuItem1 = MenuItemLabel::create(label1, CC_CALLBACK_1(BillBoardDemo::menuCallback_orientedPoint, this));
        label2 = Label::createWithTTF(ttfConfig, "Plane Oriented");
        menuItem2 = MenuItemLabel::create(label2, CC_CALLBACK_1(BillBoardDemo::menuCallback_orientedPlane, this));
        menuItem1->setPosition(Vec2(winSize.width -80,VisibleRect::top().y - 100));
        menuItem2->setPosition(Vec2(winSize.width -80,VisibleRect::top().y - 130));
        
        menu = Menu::create(menuItem1,menuItem2,nullptr);
        menu->setPosition(Vec2::ZERO);
        this->addChild(menu,10);
        menuCallback_orientedPoint(nullptr);
        
        
        bRet = true;
    }while(0);
    return bRet;
}

void BillBoardDemo::menuCallback_orientedPoint(cocos2d::Ref *sender)
{
    for(auto& billboard : _billboards)
    {
        billboard->setMode(BillBoard::Mode::VIEW_POINT_ORIENTED);
    }
}
void BillBoardDemo::menuCallback_orientedPlane(cocos2d::Ref *sender)
{
    for(auto& billboard : _billboards)
    {
        billboard->setMode(BillBoard::Mode::VIEW_PLANE_ORIENTED);
    }
}

BillBoardDemo::~BillBoardDemo()
{
    if(_camera)
    {
        _camera = nullptr;
    }
}
//创建新的BillBoard
void BillBoardDemo::addNewBillBoardWithCoords(Vec3 p)
{
    std::string imgs[3] = {"Icon.png","r2.png"};
    for(unsigned int i = 0; i < 10; i++)
    {
        //随机图片
        auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1()*1+0.5)]);
        billboard->setScale(0.5f);
        billboard->setPosition3D(Vec3(p.x,p.y,-150.0f+30*i));//Z轴值越来越大
        billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);//设置颜色混合方式
        billboard->setOpacity(CCRANDOM_0_1()*128+128);
        _layerBillBoard->addChild(billboard);//3,加入新的billboard对象
        _billboards.push_back(billboard);
    }
}
//创建新的BillBoard
void BillBoardDemo::addNewAniBillBoardWithCoords(cocos2d::Vec3 p)
{
    for(unsigned i = 0; i < 10; i++)
    {
        auto billboardAni = BillBoard::create("grossini.png");
        billboardAni->setScale(0.5);
        billboardAni->setPosition3D(Vec3(p.x,p.y,-150.0f+30*i));
        _layerBillBoard->addChild(billboardAni);//4,加入新的billboard对象
        //使用帧动画
        auto animation = Animation::create();
        for(int i = 1; i < 15; i++)
        {
            char szName1[100] = {0};
            sprintf(szName1, "grossini_dance_%02d.png",i);
            animation->addSpriteFrameWithFile(szName1);
        }
        animation->setDelayPerUnit(2.8f/14.0f);//设置一帧的时间
        animation->setRestoreOriginalFrame(true);//重复播放
        
        auto action = Animate::create(animation);
        billboardAni->runAction(RepeatForever::create(action));
        billboardAni->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);//设置颜色混合方式
        billboardAni->setOpacity(CCRANDOM_0_1()*128+128);
        _billboards.push_back(billboardAni);
    }
}

void BillBoardDemo::update(float dt)
{
    
}
//触摸事件,改变摄像机的坐标
void BillBoardDemo::onTouchesMoved(const std::vector<Touch *> &touches, cocos2d::Event *event)
{
    if(touches.size() == 1)
    {
        auto touch = touches[0];
        auto location = touch->getLocation();
        auto PreviousLocation = touch->getPreviousLocation();
        Vec2 newPos = PreviousLocation - location;
        
        Vec3 cameraDir;
        Vec3 cameraRightDir;
        _camera->getNodeToWorldTransform().getForwardVector(&cameraDir);
        cameraDir.normalize();
        cameraDir.y = 0;
        _camera->getNodeToWorldTransform().getRightVector(&cameraRightDir);
        cameraRightDir.normalize();
        cameraRightDir.y = 0;
        Vec3 cameraPos = _camera->getPosition3D();
        cameraPos+= cameraDir*newPos.y*0.5;
        cameraPos+= cameraRightDir*newPos.x*0.5;
        _camera->setPosition3D(cameraPos);
    }
}
//翻转摄像机
void BillBoardDemo::rotateCameraCallback(cocos2d::Ref *sender, float value)
{
    Vec3 rotation3D = _camera->getRotation3D();
    rotation3D.y += value;
    _camera->setRotation3D(rotation3D);
}

3、使用

HelloWorldScene中的createScene中创建BillBoardDemo层,加入scene。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值