Cocos2d-JS Tutorial – Chalk Board 2 – Erasing

Objective

In Continuation of our last Chalk Board drawing post, let’s see how to erase the board in this post.

ENGINE VERSION : COCOS2D-JS 3.8.1

Preview

Contents

  1. Prerequisite
  2. Download
  3. Chalk back to Position
  4. Draw / Erase Mode
  5. Touch Eraser Detection
  6. Erasing Magic
  7. Complete Board.js Code

At any point of time, refer to the source files Board.jsmain.js and resource.js for clarity.

1. Prerequisite

  • Should have Cocos2d-x installed in system.
  • Should have basic working knowledge of Cocos2d-JS
  • Read Previous post on Chalk Board Drawing.

See this link to get started with Cocos2d-x.

2. Download Code

Download project @ https://github.com/GethuGames/cocos2dx-chalk-board-draw/archive/erase1.0.zip Complete Project can be found in GITHUB.

Note: This is not directly executable. This contains the source and resources excluding the cocos2dx bundle. So, create a new project, download this github and replace the files in ur new project with this github files to be able to run the project.

3. Chalk back to Position

When you are erasing, you dont want the chalk to be in the middle of the board and overlap with the Eraser. So let’s create a action that will move the chalk to the bottom of the move after drawing (on touches ended).

// inside `onTouchesEnded` of Board.js
slf.chalkSprite.runAction(cc.moveTo(0.2, cc.p(size.width * 0.7, slf.chalkSprite.getContentSize().height * 0.8)).easing(cc.easeIn(1.0)));

Add that code in `onTouchesEnded`, so as to drop the chalk to bottom after each draw.

4. Draw / Erase Mode

As you have seen in the video above, we should be able to drag the Eraser to clear the board. So to separate erasing and drawing in the common action of dragging, lets define a variable `mode`.

     mode : 0,
  1. When mode is 0, our Canvas will be in drawing mode and
  2. When it is 1, it will be in Erasing mode.
  3. When the touch begins on Eraser, we set the mode to 1 and drag the eraser instead of chalk.
  4. Touching anywhere else other than Eraser, will set the mode to 0 and start drawing.

5. Touch Eraser Detection

Now in `touchesBegan`, we need to identify If the touch is made on Eraser and set the mode accordingly.

// This code goes in `onTouchesBegan` function of Board.js
        slf.mode                =   0;

        dist                    =   Math.round(cc.pDistance(pos, slf.duster.getPosition()));
        if (dist < slf.duster.getContentSize().width) {
            slf.mode            =   1;
        }

Above is a very simple Hit Test Logic.

  • Set the mode to 0 (Draw) by default.
  • Then find the distance between touch point (pos) and eraser.
  • If the distance is less than the size of the eraser itself, then set the mode to `1`, since the touch is made on or very close to the Eraser.

Also introduce a `if` condition inside the `for` loop of `onTouchesMoved`:

        for (var i = 0; i < dist; i += 5) {
            var cPos            =   cc.pLerp(slf.prevPoint, pos, i/dist);
            if (slf.mode == 0) {
                slf.drawBrushAtPoint(cPos, cc.color(240, 240, 240, 230));
            } else if (slf.mode == 1) {
                // Erase Code to be updated
            }
        }

Now, drawing lines will be called only when the mode is `0`. Try running the code and see what happens when you touch on Eraser and drag across the board. You will see no lines.

All pieces are now set. Let’s see how to do the actual erasing Magic.

6. Erasing Magic

Now close the function `drawBrushAtPoint()` to `eraseAtPoint`. All code will be similar to drawing, except for just one line, which is,

    this.chalkBrush.setBlendFunc( cc.ZERO, cc.ONE_MINUS_SRC_ALPHA );

Setting the blend function of the sprite to ( cc.ZERO, cc.ONE_MINUS_SRC_ALPHA ) will erase rather than drawing. That’s it. Very very simple. Here is the full code of `eraseAtPoint`.

    eraseAtPoint                :   function(pt) {
        this.renderTex.begin();
        this.chalkBrush         =   cc.Sprite.create(res.chalkBrush_png);
        this.chalkBrush.setRotation(Math.random() * 180);
        this.chalkBrush.setPosition(pt);
        this.chalkBrush.setScale(10.0);
        this.chalkBrush.setOpacity(230);
        this.chalkBrush.setBlendFunc(  cc.ZERO, cc.ONE_MINUS_SRC_ALPHA );
        this.chalkBrush.visit();
        this.renderTex.end();

        this.duster.setPosition(pt);
    }

See this is much similar to Drawing code, except for setting the Blend function. With different blend functions, some super awesome visuals can be created.

Erase Line

Happy Coding (y)

Complete Board.js Code

var Board = cc.Scene.extend({

    boardSprite                 :   null,

    renderTex                   :   null,

    chalkSprite                 :   null,

    chalkBrush                  :   null,

    prevPoint                   :   cc.p(0, 0),

    mode                        :   0,

    ctor                        :   function () {

        this._super();

        var slf                 =   this;
        var size                =   cc.winSize;
        
        if( 'touches' in cc.sys.capabilities ) { 
            console.log('Can Touch');
            this._touchListener = cc.EventListener.create({
                event: cc.EventListener.TOUCH_ALL_AT_ONCE,
                onTouchesBegan: this.onTouchesBegan,
                onTouchesMoved: this.onTouchesMoved,
                onTouchesEnded: this.onTouchesEnded
            });

            cc.eventManager.addListener(this._touchListener, this);
        } else {
            console.log('No Touch Capabs');
        }

        this.boardSprite        =   cc.Sprite.create(res.Board_BG);
        this.boardSprite.setPosition(cc.p(size.width / 2, size.height / 2));
        this.boardSprite.setScale(640 / this.boardSprite.getContentSize().width,
                size.height / this.boardSprite.getContentSize().height);
        this.addChild(this.boardSprite);

        this.renderTex     =   cc.RenderTexture.create(size.width, size.height);
        this.renderTex.setPosition(cc.p(size.width / 2, size.height / 2));
        this.addChild(this.renderTex);

        this.chalkSprite        =   cc.Sprite.create(res.chalk_png);
        this.chalkSprite.setPosition(cc.p(size.width * 0.7, this.chalkSprite.getContentSize().height * 0.8));
        this.addChild(this.chalkSprite, 2);

        this.duster             =   cc.Sprite.create(res.duster_png);
        this.duster.setPosition(cc.p(this.duster.getContentSize().width * 0.5, this.duster.getContentSize().height * 0.8));
        this.duster.setScale(0.5);
        this.duster.setRotation(30);
        this.addChild(this.duster, 2);
    }, 

    onTouchesBegan:function(touches, event) {
        var slf                 =   event.getCurrentTarget();
        var pos                 =   touches[0].getLocation();
        console.log('Began : ' + JSON.stringify(pos));
        
        slf.prevPoint           =   pos;
        slf.mode                =   0;

        /*
        var dist                =   Math.round(cc.pDistance(pos, slf.chalkSprite.getPosition()));
        if (dist < slf.chalkSprite.getContentSize().width) {
            slf.mode            =   0;
        }
        */

        dist                    =   Math.round(cc.pDistance(pos, slf.duster.getPosition()));
        if (dist < slf.duster.getContentSize().width) {
            slf.mode            =   1;
        }

        return                      true;
    },

    onTouchesMoved:function(touches, event) {
        var slf                 =   event.getCurrentTarget();
        var pos                 =   touches[0].getLocation();
        console.log('Move : ' + JSON.stringify(pos));
        //console.log('PrevPoint : ' + JSON.stringify(slf.prevPoint));

        var dist                =   Math.round(cc.pDistance(pos, slf.prevPoint));
        //console.log(dist);

        for (var i = 0; i < dist; i += 5) {
            var cPos            =   cc.pLerp(slf.prevPoint, pos, i/dist);
            if (slf.mode == 0) {
                slf.drawBrushAtPoint(cPos, cc.color(240, 240, 240, 230));
            } else if (slf.mode == 1) {
                slf.eraseAtPoint(cPos);
            }
        }

        slf.prevPoint           =   pos;
    },

    onTouchesEnded              :   function(touches, event) {
        var slf                 =   event.getCurrentTarget();
        var pos                 =   touches[0].getLocation();
        var size                =   cc.winSize;

        console.log('End : ' + JSON.stringify(pos));

        if (slf.mode == 0) {
            slf.chalkSprite.runAction(cc.moveTo(0.2, cc.p(size.width * 0.7, slf.chalkSprite.getContentSize().height * 0.8)).easing(cc.easeIn(1.0)));
        } else if (slf.mode == 1) {
            slf.duster.runAction(cc.moveTo(0.2, cc.p(slf.duster.getContentSize().width * 0.5, slf.duster.getContentSize().height * 0.8)).easing(cc.easeIn(1.0)));
        }
                //this.duster.runAction(cc.moveTo(0.1, this.erasePoint).easing(cc.easeIn(1.0)));

    },

    drawBrushAtPoint            :   function(pt, color) {

        this.renderTex.begin();
        this.chalkBrush         =   cc.Sprite.create(res.chalkBrush_png);
        this.chalkBrush.setRotation(Math.random() * 180);
        this.chalkBrush.setPosition(pt);
        this.chalkBrush.setColor(color);
        this.chalkBrush.setScale(1.5);
        this.chalkBrush.visit();
        this.renderTex.end();

        this.chalkSprite.setPosition(cc.p(pt.x - this.chalkSprite.getContentSize().width * 0.3,
            pt.y - this.chalkSprite.getContentSize().height * 0.2));

    },

    eraseAtPoint                :   function(pt) {

        this.renderTex.begin();
        this.chalkBrush         =   cc.Sprite.create(res.chalkBrush_png);
        this.chalkBrush.setRotation(Math.random() * 180);
        this.chalkBrush.setPosition(pt);
        this.chalkBrush.setScale(10.0);
        this.chalkBrush.setOpacity(230);
        this.chalkBrush.setBlendFunc(  cc.ZERO, cc.ONE_MINUS_SRC_ALPHA );
        this.chalkBrush.visit();
        this.renderTex.end();

        this.duster.setPosition(pt);

    }

});

One thought on “Cocos2d-JS Tutorial – Chalk Board 2 – Erasing

  1. Pingback: Cocos2d-JS Tutorial – Chalk Board 3 – Drawing Grid Lines | Gethu Games – Blog

Leave a Reply

Your email address will not be published. Required fields are marked *