paperJS (paper.js) JavaScript Library walk through by Brett Paufler - 9-10-13

JavaScript Primer & paper.js tutorial

BEG: Beg To Differ Bubble Drop Game - 06

Incrementing Number of Colors and Resetting Board

This is where I'm planning on stopping this project for awhile.  I think I'll come back in a few weeks/months and add some more functionality or make a new version that plays differently (more likely).  But in the meantime, here's the code complete for the Top Center Circle Control.

Most of this is old.  The remarks are highlighted red at the start of the newly added code.

function checkGameControlCenterCircle(event){

    // on retrospect, probably should have placed this if in the onMouseDown function
    if (gameControlCircle.contains(event.point)){
        // variable to counter whether controlCenterCircle is pressed rapidly in succession
        // this is reset to zero if a gamePiece is selected instead
        centerCount += 1;
        // if gameWon & repeatedly hit, game board resets  // this is all new, board resets on new game
        if (gameWon === true || centerCount === 3){
            project.activeLayer.removeChildren();  // existing is erased (otherwise the old board will appear when new goes invisible)
            headText[5].content = 'numColor = ' + numColors;
            gameWon = false;  // gameWon code has fired, so this needs to be false now
            centerCount = 0;
            return 0;  // rest of function need not fire, so return 0 to end
        // tallies number of gameCircles currently selected
        // this is another one we could pass to our newly created
        // loopAllgameCirlces(passedFunction) function
        var hitCount = 0;
        var dropCircle = true;
        var dropTempCircle = new Path.Circle(CP, 1);
        for (i = 0; i <= gTNV; i++){
            for (j = 0; j <= gTNH; j++){
                if (gameCircle[i][j].strokeWidth === 10){
                hitCount += 1;

    // most of this has been gone over in previous tutorials
    // this block extends fairly far down, another canditate for an external function
        // if 2 or more, selected gameCircles become invisible
        if (hitCount > 1){
            for (i = 0; i <= gTNV; i++){
                for (j = 0; j <= gTNH; j++){
                    // resets strokeWidth to zero, visible is new Marker
                    if (gameCircle[i][j].strokeWidth === 10){
                        gameCircle[i][j].strokeWidth = 0;
                        gameCircle[i][j].visible = false;
                        gameCircle[i][j].strokeColor = gameCircle[i][j].fillColor;               
            }  // close outside for, no marked, those that were are now visible=false

            // dropCircle code drops the gameCircles vertically       
            // dropCircle code, visible = false, is the marker;
            while (dropCircle){
                dropCircle = false;

                for (j = 0; j <= gTNH; j++){    // notice reverse order H vs V
                    for (i = gTNV; i >= 1; i--){    // notice reverse countdown
                        if (gameCircle[i][j].visible === false){
                            if (gameCircle[i - 1][j].visible === true){
                                dropCircle = true;
                            gameCircle[i][j].fillColor = gameCircle[i - 1][j].fillColor;
                            gameCircle[i][j].visible = gameCircle[i - 1][j].visible;
                            gameCircle[i - 1][j].visible = false;
            } // end bubbleDrop, wrapping while   
            // takes visible = false Bubbles and sets color to black
            // thereby taking them out of the game
            // eliminates last row error
            for (i = 0; i <= gTNV; i++){
                for (j = 0; j <= gTNH; j++){
                    if (gameCircle[i][j].visible === false){
                        gameCircle[i][j].fillColor = 'black';

            // slides empty columns over to RIGHT
            // essentially the second step of the dropCircle sub-function code
            var emptyColumn = true;
            while (emptyColumn){
                emptyColumn = false;
                for (j = gTNH; j >= 1; j--){  // note, stops at 1
                    if (gameCircle[gTNV][j].visible === false){
                        for (i = 0; i <= gTNV; i++){
                        gameCircle[i][j].visible = gameCircle[i][j - 1].visible;
                        gameCircle[i][j].fillColor = gameCircle[i][j - 1].fillColor;
                        gameCircle[i][j].strokeColor = gameCircle[i][j - 1].strokeColor;
                        gameCircle[i][j - 1].visible = false;
                        gameCircle[i][j - 1].fillColor = 'black';
                        gameCircle[i][j - 1].strokeColor = 'black';
                            if (gameCircle[i][j].visible === true){
                                emptyColumn = true;
            }  // right shift of columns wrapping while ends
            // from here down is new
            // this just retallies the number of gameCircles left in play
            //tallies number of remaining gameCircles, passes total to hitCount
            hitCount = 0;
            for (i = 0; i <= gTNV; i++){
                for (j = 0; j <= gTNH; j++){  // loops through all gameCircles
                    if (gameCircle[i][j].visible === true){
                        hitCount += 1;  // adds one for each gameCircle in play
                        headText[5].content = 'Game Pieces to Go = ' + hitCount;  // adds info to PointText for feedback

             // and if the number of gameCircles left in play is zero, the game has been won
            // if hitCount equals zero, game has been one
            if (hitCount === 0){
                gameWon = true;
                    if (numColors <= 9) {
                    numColors += 1;  // the results of victory, a harder challenge, ain't that always the way
                // gameWin text change
                headText[5].content = 'Congrats!!!  You Won!!!';
                headText[6].content = 'Hit Center Circle to try again with ' + numColors + 'colors';
        }  // end hitCount > 1 if block

    }  // end wrapping contain(event) if
}  // end centerCircle Control function

I think it's fairly straighforward, but the code is getting a bit long and out of hand, so...

Passing a Function to a Function

I used these two for loops a lot in this program.
            for (i = 0; i <= gTNV; i++){
                for (j = 0; j <= gTNH; j++){
                   // code to execute inside loop goes here

And as I was thinking about refactoring the program (huge chunks of unused code have been deleted and removed from under the hood in comparing this page to the last), I was wondering whether I could condense these two loops out into a function.  Unsurprisingly, the answer is yes.

So, here's the two for loops condensed as a function.  But to utilize, a function must be passed in to this function as a variable.
So please note the lack of () at the end of the passed function.  Without (), the function is being passed as a pointer.  Include the () and the function will fire and the result of the function rather than the function itself will actually be passed.

function loopAllgameCirlces(passedFunction){  //guess I misspelled circles, I do that a lot
    for (i = 0; i <= gTNV; i++){
        for (j = 0; j <= gTNH; j++){

And here's the function we will ultimately pass.  I has two declared parameters (i & j, which it will get from the loopAllgameCirlces function).

function testPassFunction(i,j){
    gameCircle[i][j].strokeWidth = 0;
    gameCircle[i][j].strokeColor = gameCircle[i][j].fillColor;

And here's the lot of it being used.
The new code is in red.
And it replaces the old code in blue (commented out).

In this case, there's not much code savings.  But I did this exercise more as a proof of concept than anything else.  I have now successfully passed a function to a function (for the first time, I might add); and therefor, I like to believe that I am that much closer to understand jQuery and other such function passing libraries.

function checkGameCircle(event){

        // elimates all strokeWidth Markings
        //for (i = 0; i <= gTNV; i++){
        //    for (j = 0; j <= gTNH; j++){
        //        gameCircle[i][j].strokeWidth = 0;
        //        gameCircle[i][j].strokeColor = gameCircle[i][j].fillColor;
        //    }
                // Above has been commented out, replaced by below for test
                // TODO - This is likely error spot, so change back if problems

       // all above, commented out
        loopAllgameCirlces(testPassFunction);  // here's the loop function, wherein the function we want to insert is called by name
                                                                    // once again, note NO () on the called function or it will fire
                                                                   // we are passing instructions, not the result of instructions

... function continues on, this is merely the insertion

Anhow, once the base functions are coded, loopAllgameCirlces(testPassFunction); is clearly much easier to write (or cut and paste) than all the code it replaces.

I've never done anything with Rasters, so I think I'll look into those next and put the bubbleDrop game on the back burner for now.

previous  -- BEG: Beg to Differ - Bubble Drop #5      paper.js tutorial index       next -- Intro To Rasters

Back to BrettCode Home

Brett Words
my writing site (Home to the writing of Celli the Happy Go Lucky Celaphopod, Eddie Takosori, Fritz Heinmillerstein, Morgan Feldstone, Kevin Stillwater, and of course, me, your host, Brett Paufler)

paper.js official site =

© Copyright 2013 Brett Paufler