cocos2d-3.x实现擦图效果

//
//  Eraser.h
//  Eraser
//
//  Created by students on 16/1/12.
//
//

#ifndef __Eraser__Eraser__
#define __Eraser__Eraser__

#include <stdio.h>
#include <cocos2d.h>
USING_NS_CC;
//pszFileName--精灵文件名, eraserImmediately---是否可以立即擦除 true---可以, false---不能
//drawType---擦除形状, 0---正方形,1---圆形, 2---自定义形状(可用一张图片代替)
class Eraser : public Sprite
{
public:
    Eraser();
    ~Eraser();

    static Eraser* create(std::string pszFileName,const bool& eraserImmediately = true,const unsigned int& drawType = 0);
    virtual bool init(std::string pszFileName,const bool& eraserImmediately = true,const unsigned int& drawType = 0);

    virtual void onEnter();
    virtual void onExit();

public:
    CC_PROPERTY(bool, isEraser, Eraser);//设置是否可以擦除
    CC_PROPERTY(float, drawWidth, DrawWidth);//擦除大小,默认10.F
    CC_PROPERTY(bool, isEraserOK, EraserOK);//是否擦除完毕

    void setDrawStencil(std::string pszFileName);

private:
    void eraserByBlend(Point& point);
    void eraserByBlend(const Point& point);
    void eraserByColorMask();

private:
    void initData(std::string pszFileName,const bool& eraserImmediately = true,const unsigned int& zdrawType = 0);
    Size spriteSize;//精灵大小
    unsigned int drawType;//擦除形状

    Point touchPoint;//触摸点
    Texture2D* drawTextture;//自定义图片时,设置的擦除图片

    RenderTexture* Rtex;//渲染纹理
    DrawNode* pEraser;//渲染节点
};

#endif /* defined(__Eraser__Eraser__) */
//
//  Eraser.cpp
//  Eraser
//
//  Created by students on 16/1/12.
//
//

#include "Eraser.h"
Eraser::Eraser()
{

}
Eraser::~Eraser()
{
    pEraser->release();
}

Eraser* Eraser::create(std::string pszFileName,const bool& eraserImmediately,const unsigned int& drawType)
{//创建对象
    Eraser* pRet = new Eraser();
    if (pRet && pRet->init(pszFileName,eraserImmediately,drawType)) {
        pRet->autorelease();
        return pRet;
    }else
    {
        delete pRet;
        pRet = NULL;
        return NULL;
    }
}
bool Eraser::init(std::string pszFileName,const bool& eraserImmediately,const unsigned int& drawType)
{
    if (!Sprite::init()) {
        return false;
    }
    initData(pszFileName,eraserImmediately,drawType);

    auto dis = Director::getInstance()->getEventDispatcher();
    auto lis = EventListenerTouchOneByOne::create();
    lis->onTouchBegan = [this](Touch* touch,Event* event)
    {
        if (isEraser)
        {
            Point point = touch->getLocation();
            eraserByBlend(-this->getPosition() + point + spriteSize/2.f);
            touchPoint = point;

            return true;
        }

        return false;
    };
    lis->onTouchMoved = [this](Touch* touch,Event* event)
    {
        if (isEraser)
        {
            Point point = touch->getLocation();
            Point normal = (point-touchPoint).getNormalized();

            while(1)
            {
                if (point.distance(touchPoint) < 1.f)
                {
                    eraserByBlend(-this->getPosition() + point + spriteSize/2.f);
                    break;
                }
                touchPoint = touchPoint + normal*1.f;
                eraserByBlend(-this->getPosition() + touchPoint + spriteSize/2.f);
            }

            touchPoint = point;
        }
    };
    dis->addEventListenerWithSceneGraphPriority(lis, this);

    return true;
}
void Eraser::initData(std::string pszFileName,const bool& eraserImmediately,const unsigned int& zdrawType)
{
    isEraser = eraserImmediately;
    drawType = zdrawType;
    drawWidth = 10.0f;

    auto size = Director::getInstance()->getWinSize();
    //设置图片
    auto sprite = Sprite::create(pszFileName);
    auto scalex = size.width/sprite->getContentSize().width;
    auto scaley = size.height/sprite->getContentSize().height;
    sprite->setScaleX(scalex);
    sprite->setScaleY(scaley);

    spriteSize = size;

    sprite->setAnchorPoint(Vec2::ZERO);

    //渲染纹理
    Rtex = RenderTexture::create(spriteSize.width, spriteSize.height);
    Rtex->setPosition(Point::ZERO);
    this->addChild(Rtex);

    //????
    Rtex->begin();
    sprite->visit();//??
    Rtex->end();

    //渲染节点
    pEraser = DrawNode::create();
    setDrawWidth(10.0f);
    pEraser->retain();///???
    //自定义擦除的图片
    drawTextture = new Texture2D;
    drawTextture->retain();
}
void Eraser::setDrawStencil(std::string pszFileName)
{
    drawTextture = Director::getInstance()->getTextureCache()->addImage(pszFileName);
}

void Eraser::eraserByBlend(Point& point)
{

}
void Eraser::eraserByBlend(const Point& point)
{
    switch (drawType) {
        case 2:
        {
            auto drawSprite = Sprite::createWithTexture(drawTextture);
            drawSprite->setPosition(point);
            BlendFunc blendFunc = {GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA};
            drawSprite->setBlendFunc(blendFunc);
            Rtex->begin();
            drawSprite->visit();
            Rtex->end();
        }
            break;

        default:
        {
            pEraser->setPosition(point);
            BlendFunc blendFunc = {GL_ONE,GL_ZERO};
            pEraser->setBlendFunc(blendFunc);
            Rtex->begin();
            pEraser->visit();
            Rtex->end();
        }
            break;
    }
}
void Eraser::eraserByColorMask()
{
    Rtex->begin();
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
    pEraser->visit();
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    Rtex->end();
}

void Eraser::setEraser(bool var)
{
    this->isEraser = var;
}
bool Eraser::getEraser()
{
    return isEraser;
}
bool Eraser::getEraserOK()
{
    isEraserOK = false;

    auto image = new Image();
    image = Rtex->newImage();

    int m = 3;
    if (image->hasAlpha()) {
        m = 4;
    }

    unsigned char* data_ = image->getData();
    int x = 0,y = 0;
    for (x = 0; x<spriteSize.width; ++x) {
        for (y = 0; y<spriteSize.height; ++y) {
            unsigned char* pixel = data_+(x+y*image->getWidth())*m;

            unsigned int r = (unsigned int)*pixel;
            unsigned int g = (unsigned int)*(pixel + 1);
            unsigned int b = (unsigned int)*(pixel + 2);
            unsigned int a = (unsigned int)*(pixel + 3);

            if (r != 0 && g!=0 && b!=0 && a!=0) {
                isEraserOK = false;
                break;
            }
        }
        if (spriteSize.height != y) {
            break;
        }
    }
    if (x == spriteSize.width && y == spriteSize.height) {
        isEraserOK = true;
    }
    delete image;

    return this->isEraserOK;
}
void Eraser::setEraserOK(bool var)
{
    this->isEraser = var;
}
float Eraser::getDrawWidth()
{
    return this->drawWidth;
}
void Eraser::setDrawWidth(float var)
{
    this->drawWidth = var;
    switch (drawType) {
        case 0:
        {
            pEraser->drawDot(Vec2::ZERO, drawWidth, Color4F(0, 0, 0, 0));
        }
            break;
        case 1:
        {
            float fRadius = drawWidth;
            const int nCount = 100;
            const float coef = 2.0f*(float)M_PI/nCount;
            static Vec2 circle[nCount];
            for (unsigned int i=0; i<nCount; i++) {
                float rads = i*coef;
                circle[i].x = fRadius*cosf(rads);
                circle[i].y = fRadius*sinf(rads);
            }
            pEraser->drawPolygon(circle, nCount, Color4F(0, 0, 0, 0), 0, Color4F(0, 0, 0, 0));
        }
            break;
        case 2:
        {

        }
            break;

        default:
            break;
    }
}
void Eraser::onEnter()
{
    Sprite::onEnter();//单点触摸

}
void Eraser::onExit()
{
    Sprite::onExit();
}
时间: 2024-10-09 06:51:21

cocos2d-3.x实现擦图效果的相关文章

js实现轮播图效果(附源码)--原生js的应用

1.js实现轮播图效果 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="Author" content="奇客艺术"> <meta name="keyword" content="关键字"> <meta name=

【学习ios之路:UI系列】实现轮播图效果(UIImageView,UIScrollView,UIPageControl,NSTimer相结合)

实现效果,在不点击的情况下,自定滚动,点击时,停止.如下图 部分代码如下: //调用NSTimer方法,自定计时 - (void)autoScroll { self.timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self  selector:@selector(scrollToRight) userInfo:nil repeats:YES]; } //实现触发方法 - (void)scrollToRight { [UIVie

AngularJS:实现轮播图效果

要实现这个功能,可以https://github.com/sroze/ngInfiniteScroll这个第三方控件实现的.实现步骤如下: 1. 下载ng-infinite-scroll.js程序http://sroze.github.io/ngInfiniteScroll/ 目前版本是1.0.0 2. 如果你是用的jQuery2.0以上版本,还需要修改ng-infinite-scroll.js程序,将所有的将所有的$window.xxx改为$(window).xxx, elem.xxx改为$(

Html5如何快速在页面中写出多个轮播图效果

我们在做项目的过程中,有时候客户需求要求你在同一个页面中,写几个不同样式的轮播图效果,那么如何快速实现呢?(要知道若果你每个轮播图都要用原生javascript写的话,会很麻烦,代码也不够简洁) 这里我们就可以借助插件来实现这一功能,swiper.js就是一个专门处理轮播图效果的js库,下面举例来说明: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"&g

花瓣网轮播图效果

没有加上定时器效果,仅仅能手动进行图片的切换 效果图: index.html <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN""> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>index</title> &

如何增强ArcGIS插值图出图效果

by 李远祥 在一些科研领域,经常会遇到使用插值的方式进行处理,并生成最终的插值图.插值图在ArcGIS里面非常容易生成,只要具备了采用点数据,通过ArcToolBox里面的插值的工具可以直接生成最终的插值数据.插值的方法有很多种,这里就不做介绍了.数据生成后,其地图制作也是相当的简单,只需要在符号系统的标签里面设置一下,并进行重分类,使用色带去渲染就可以完成.下图去掉一些地图的整饰元素,直接使用最原始的栅格渲染方式进行出图. 尽管这个图按照笔者的经验,将研究区域的边界加上去,并且标红,加入一些

开发路程(14):背景图片移动插件MyFloatingBg(浮动背景图效果,可让背景随着页面的滚动而滚动)

MyFloatingBg这插件可以帮助你在网页上加入可移动背景Background.你可以用于整个文件的背景,或是某几个banner的背景. 它可支持简单的animation效果,你不用去做一个flash文件或动态gif图片.单靠jquery和图片,你便可以做出不同的效果.由于我们把动画效果跟内容分开,我们也可以随时更改文字等内容,而不影响其运作.这个效果很是大气,我想可以使用在高级餐厅,珠宝展会等中做展示用. 1 <!doctype html> 2 <html lang="e

JavaScript学习——实现首页轮播图效果

1.相关技术 获取元素 document.getElementById("id 名称") 事件(onload) 定时操作:setInterval("changeImg()",3000); 2.步骤分析(此案例轮播图效果是基于HTML&CSS--使用DIV和CSS完成网站首页重构实现的) 事先准备三张一样大小的图片(img1.img2.img3)放在文件夹Img下. 第一步:确定事件(onload)并为其绑定一个函数 第二步:书写绑定的这个函数 第三步:书写定

图片热区比切图效果好

切片和图像热区是啥?图像切片是将很大的页面图像,切成相似拼图的那种方式,以后运用 HTML 代码,再完满的拼接起来的一种加快页面图像显现的方法,图像切片以后你还能够在不一样的切片上参加连接等等,然后到达点击不一样图像区域跳转到不一样页面的作用.图像热区是在一章图像上,制作任意多边形或许圆形的区域,并参加连接的一种方式,图像热区的优点在于,图像不必被切割,就算被点击的区域是不规则的形状,图像热区也能够很轻松的敷衍,而切片要敷衍多边形的区域,能够就需求屡次切片了,那么切片和图像热区到底有啥详细差异和