cocos2dx 新手引导 ClippingNode + DrawNode + Sprite

.h头文件

/*!

  • @brief GuideLayer

  • @author elvis cui

  • @date 2020-08-28

  • @ingroup Scenes/GuideLayer

  • 新手引导层

2.3、分析总结

通过ClippingNode进行裁剪遮罩,其实是这样的:

将模板(Stencil)上所有元素的形状集合作为“形状模板”,其元素本身不渲染。

使用“形状模板”对底板进行裁剪。

显示从底板上裁剪下来的图片区域。

总的来说:

模板(Stencil)相当于是一个样板,上面有很多不同形状的"洞洞"。

然后根据样板,对底板进行裁剪,“挖洞”。

然后将剪下来的那些碎片,按照原来的位置进行摆放。

其中:模板(Stencil)只是一个“形状模板”,本身的图片是不进行绘制的。

模板节点是Node的子类,一般常常使用DrawNode,因为它可以绘制不同形状的图形。当然也可以直接使用Node节点作为作为模板。

*/

#pragma once

#include “cocos2d.h”
#include “cocostudio.h”
#include “cocos-ext.h”
#include “MobileKit.h”

USING_NS_CC;
USING_NS_CC_EXT;

typedef enum GuideType
{
Type_None = -1,
Type_Circle = 1, //圆形遮罩
Type_Rect = 2, //矩形遮罩
Type_ImageOrBtn = 3, //图片或按钮遮罩
}GuideType;

class GuideLayer : public Layer, public MKNodeBinder, public MKObserver
{
public:
GuideLayer();
virtual ~GuideLayer();

public:
static GuideLayer* create();
static std::string LayerName;

//开始圆形引导  世界坐标下的圆中心和半径
void startCircleGuide(cocos2d::Vec2 circle_center_worldPos, float radius);

//开始矩形引导   世界坐标下的矩形
void startRectGuide(Rect worldSpaceRect);

//开始图片或者按钮形状的新手引导    图片路径和时间坐标的位置
void startImageOrBtnGuide(std::string filePath, cocos2d::Vec2 worldSpacePos);

private:
/*!
* @brief 初始化GuideLayer
* @param
*/
virtual bool init();

virtual bool onTouchBegan(Touch *touch, Event *unused_event) override;
virtual void onTouchMoved(Touch *touch, Event *unused_event) override;
virtual void onTouchEnded(Touch *touch, Event *unused_event) override;

protected:
/*!
* @brief 绑定变量
* @param node 节点
/
virtual void onBindVariable(Node
node) override;

/**
* @brief	绑定触摸事件的回调方法
* @param   node 节点
*/
virtual void onBindCallback(Node* node) override;

/**
* @brief	绑定变量完成
*/
virtual void onFinishBinding() override;

/**
* @brief	设备按键
*/
void onKeyReleased(EventKeyboard::KeyCode keyCode, cocos2d::Event *event);

/*!
* @brief	响应通知
* @param    通知数据
*/
virtual void onNotify(MKNotice* notify) override;

private:
/*!
* @brief 关闭界面
*/
void close();

private:
//创建灰色的bg
EventListenerTouchOneByOne* m_touchListener = nullptr; //触摸监听器
LayerColor* createGrayBg();

bool touchInRectArea(Touch* touch); //是否点中了扣洞的矩形区域
bool touchInCircleArea(Touch *touch); //是否点中了扣洞的圆形区域
bool touchInImageOrBtnArea(Touch* touch); //是否点中了扣洞的图片或按钮区域

GuideType m_guideType = GuideType::Type_None;

cocos2d::Vec2 m_circle_center_pos = cocos2d::Vec2::ZERO; //原点位置
float m_circle_radius = 1.0f; //圆的半径

// 触摸事件如果在这个矩形区域内,则可以穿透   继续传递下去
cocos2d::Rect m_rectArea = Rect::ZERO;

//图片或按钮的新手引导
cocos2d::Sprite* m_sprite_imageOrBtn_guide = nullptr;

};

.cpp文件
#include “GuideLayer.h”
#include “GameUtils.h”
#include “SoundManager.h”
#include “GameNotify.h”

std::string GuideLayer::LayerName = “GuideLayer”;

GuideLayer::GuideLayer()
{
auto listener = EventListenerKeyboard::create();
listener->onKeyReleased = CC_CALLBACK_2(GuideLayer::onKeyReleased, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

registerAllNotice();

}

GuideLayer::~GuideLayer()
{
}

GuideLayer* GuideLayer::create()
{
GuideLayer* layer = new GuideLayer();
if (layer && layer->init())
{
layer->autorelease();
return layer;
}
else
{
delete layer;
layer = nullptr;
}
return nullptr;
}

bool GuideLayer::init()
{
if (!Layer::init())
{
return false;
}

Node* node = MKUIHelper::readNode("Guide/GuideLayer.csb", this);
addChild(node);
MKUIHelper::bindNodes(node, this, true);

//auto action = CSLoader::createTimeline("Guide/GuideLayer.csb");
//node->runAction(action);
//action->gotoFrameAndPlay(0, false);

return true;

}

bool GuideLayer::onTouchBegan(Touch* touch, Event *event)
{
bool result = false; //isTouch

if (this->m_guideType == GuideType::Type_Rect)
{
	result = this->touchInRectArea(touch);
}
else if (this->m_guideType == GuideType::Type_Circle)
{
	result = this->touchInCircleArea(touch);
}
else if (this->m_guideType == GuideType::Type_ImageOrBtn)
{
	result = this->touchInImageOrBtnArea(touch);
}

//根据是否点中设置是否吞噬触摸
if (result)
{ //点击到了遮罩位置
	LogD("1111111111111111");
	this->m_touchListener->setSwallowTouches(false);
}
else
{ //点击的背景
	LogD("2222222222222222");
	this->m_touchListener->setSwallowTouches(true);
}

return true;

}

void GuideLayer::onTouchMoved(Touch* touch, Event *event)
{

}

void GuideLayer::onTouchEnded(Touch* touch, Event *event)
{
Point point = touch->getLocation();
Point startPoint = touch->getStartLocation();
//Point pannelPoint = m_imgBg->getParent()->convertToNodeSpace(point);//->getParent()
//if (!m_imgBg->getBoundingBox().containsPoint(pannelPoint))
//{
// close();
//}
}

void GuideLayer::onKeyReleased(EventKeyboard::KeyCode keyCode, cocos2d::Event *event)
{
if (keyCode == EventKeyboard::KeyCode::KEY_BACK)
{
//MKEventSystem::sendNotice(kOnClickKeyBackNtf);
}
else if (keyCode == EventKeyboard::KeyCode::KEY_ESCAPE)
{ //esc键
//MKEventSystem::sendNotice(kOnClickKeyBackNtf);
}
event->stopPropagation();
}

void GuideLayer::onBindVariable(Node * node)
{

}

void GuideLayer::onBindCallback(Node* node)
{

}

void GuideLayer::onFinishBinding()
{
//test code elviscui todo

//this->startCircleGuide(cocos2d::Vec2(200, 200), 100);

//this->startRectGuide(Rect(300, 300, 300, 300)); //x, y, width, height

this->startImageOrBtnGuide("textures/game/StartLayer/btn_signIn.png", Vec2(Director::getInstance()->getWinSize().width / 2, Director::getInstance()->getWinSize().height / 2));

}

void GuideLayer::onNotify(MKNotice* notify)
{
const std::string& type = notify->getType();

}

void GuideLayer::close()
{
this->removeFromParentAndCleanup(true);
}

bool GuideLayer::touchInCircleArea(Touch *touch)
{
bool result = false;

auto touchPos = touch->getLocation();
//Vec2 nodeSpace = this->convertToNodeSpace(touchPos);
if (touchPos.getDistance(this->m_circle_center_pos) <= this->m_circle_radius)
{
	return true;
}

return false;

}

bool GuideLayer::touchInRectArea(Touch* touch)
{
bool result = false;

auto touchPos = touch->getLocation();
//Vec2 nodeSpace = this->convertToNodeSpace(touchPos);
if (this->m_rectArea.containsPoint(touchPos))
{
	result = true;
}

return result;

}

bool GuideLayer::touchInImageOrBtnArea(Touch* touch)
{
bool result = false;

auto touchPos = touch->getLocation();
if (this->m_sprite_imageOrBtn_guide != nullptr)
{
	Vec2 nodeSpace = this->m_sprite_imageOrBtn_guide->getParent()->convertToNodeSpace(touchPos);
	Rect boundBox = this->m_sprite_imageOrBtn_guide->getBoundingBox();
	if (boundBox.containsPoint(nodeSpace))
	{
		result = true;
	}
}

return result;

}

LayerColor* GuideLayer::createGrayBg()
{
cocos2d::Size winSize = Director::getInstance()->getWinSize();
LayerColor* layerColor = LayerColor::create(Color4B(0, 0, 0, 255 * 0.7f), winSize.width, winSize.height); //黑色底板

if (m_touchListener == nullptr)
{
	m_touchListener = EventListenerTouchOneByOne::create();
	m_touchListener->onTouchBegan = CC_CALLBACK_2(GuideLayer::onTouchBegan, this);
	m_touchListener->onTouchMoved = CC_CALLBACK_2(GuideLayer::onTouchMoved, this);
	m_touchListener->onTouchEnded = CC_CALLBACK_2(GuideLayer::onTouchEnded, this);
	m_touchListener->setSwallowTouches(true);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(m_touchListener, layerColor);
}

return layerColor;

}

//------------------------------public method begin-------------------------------

void GuideLayer::startCircleGuide(cocos2d::Vec2 circle_center_worldPos, float radius)
{

this->m_guideType = GuideType::Type_Circle; //设置引导类型
this->m_circle_center_pos = circle_center_worldPos;
this->m_circle_radius = radius;

ClippingNode* clippingNode = ClippingNode::create(); //创建裁剪节点

//设置模板
DrawNode* drawNode = DrawNode::create();
drawNode->drawSolidCircle(circle_center_worldPos, radius, 360, 9999, Color4F(1, 0, 0, 1));
clippingNode->setStencil(drawNode);

//设置底板
LayerColor* diban = this->createGrayBg();
clippingNode->addChild(diban);

clippingNode->setInverted(true); //反向显示
clippingNode->setAlphaThreshold(0.05f);
this->addChild(clippingNode);

}

void GuideLayer::startRectGuide(cocos2d::Rect worldSpaceRect)
{
this->m_guideType = GuideType::Type_Rect; //设置引导类型
this->m_rectArea = worldSpaceRect;

ClippingNode* clippingNode = ClippingNode::create(); //创建裁剪节点

//设置模板
DrawNode* drawNode = DrawNode::create();
drawNode->drawSolidRect(cocos2d::Vec2(worldSpaceRect.getMinX(), worldSpaceRect.getMinY()), 
	cocos2d::Vec2(worldSpaceRect.getMaxX(), worldSpaceRect.getMaxY()), Color4F(1, 0, 0, 1)); //矩形的起点, 矩形的终点  左下角为 0,0 点
clippingNode->setStencil(drawNode);

//设置底板
LayerColor* diban = this->createGrayBg();
clippingNode->addChild(diban);

clippingNode->setInverted(true); //反向显示
clippingNode->setAlphaThreshold(0.05f);
this->addChild(clippingNode);

}

void GuideLayer::startImageOrBtnGuide(std::string filePath, cocos2d::Vec2 worldSpacePos)
{

this->m_guideType = GuideType::Type_ImageOrBtn; //设置引导类型

ClippingNode* clippingNode = ClippingNode::create(); //创建裁剪节点

//设置模板
Node* stencil_node = Node::create();

this->m_sprite_imageOrBtn_guide = cocos2d::Sprite::create(filePath);
m_sprite_imageOrBtn_guide->setPosition(worldSpacePos);
m_sprite_imageOrBtn_guide->getTexture()->setAntiAliasTexParameters(); //抗锯齿
//m_sprite_imageOrBtn_guide->getTexture()->setAliasTexParameters();  //不抗锯齿
stencil_node->addChild(m_sprite_imageOrBtn_guide);

clippingNode->setStencil(stencil_node);

//设置底板
LayerColor* diban = this->createGrayBg();
clippingNode->addChild(diban);

clippingNode->setInverted(true); //反向显示
clippingNode->setAlphaThreshold(0.05f);
this->addChild(clippingNode);

}

//------------------------------public method end-------------------------------

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值