> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.ipQA72Wf15u/rev.6551
 * 
 * authors: 
 *   Daniel Foster
 *   Laurie Brown
 *   
 *   
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



blocks = new Array();
cols = 10;
rows = 6;
margin = 30;
width = 640;
height = 400;
blockWidth = (width - (margin*2))/cols;
blockHeight = (height - (margin*2))/rows;
blockColorCount = 5; // Make sure you count them.
blockColors = 
{
    color(0xFFFF4444),
    color(0xFF33AA33),
    color(0xFF6666FF),
    color(0xFFEEEE00),
    color(0xFFFF9900),
    color(0xFFFFFFFF)
};
poppedBlocks = new Array();
popCount = 0;
cursorColor = 0;
holdTime = 0;
holdLength = 500;
score = 0;
string debugText;
isPressing = false;
isHolding = false;
prevSecond = 0;
currSecond = 0;
gameTime = 0;
gameLength = 150;
timeText = "";
isHighScore = false;
highScore = 0;

Start = 0;
Playing = 1;
End = 2;
gameState = Start;

btnW = 150;
btnH = 80;
btnL = (width*0.5) - (btnW*0.5);
btnR = btnL + btnW;
btnT = (height*0.5) - (btnH*0.5);
btnB = btnT + btnH;

Font uiFont;

void setup() 
{  // this is run once.   
    
    // set the background color
    background(130,0,120);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(640, 400); 
      
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);
    
    for (i = 0; i < rows*cols; i++)
    {
        blocks[i] = new Block(i);
    }

    uiFont = loadFont("calibri");
    
    currSecond = second();

    loadHighScore();

    update();

    noCursor();
}

void update()
{
    prevSecond = currSecond;
    currSecond = second();
    if(prevSecond != currSecond)
        gameTime++;

    timeText = "" + (int((gameLength - gameTime)/60)) + ":";
    if(int((gameLength-gameTime)%60) < 10)
         timeText = timeText + "0";
    timeText = timeText + int((gameLength - gameTime)%60);
    
    if(mouseX>margin && mouseY>margin && !isHolding && mousePressed && millis() - holdTime > holdLength)
    {
        isHolding = true;
        popTest();
    }
    
    if(gameTime >= gameLength)
    {
        gameState = End;
        if(score > highScore)
        {
            isHighScore = true;
            saveStrings("highscore.txt", {score});
        }
    }
}

void draw() 
{
    if(gameState == Playing)
    {
        update();

    }
    
    background(180,100,180);
    for (i = 0; i!= cols*rows; i++)
    {
        blocks[i].draw();
    }
    
    textFont(uiFont ,30);
    fill(0);
    text("" + score + " / " + highScore, 30, 25);    
    if(gameState == Playing)
        text(timeText , 555, 25);
     
    if (gameState == Start)
    {
        fill(180,100,180);
        strokeWeight(2);
        stroke(0);
        rect(btnL,btnT,btnW,btnH, 10);
        rect(btnL,btnT + btnH + 5,btnW,25, 10);
        
        fill(0);
        textFont(uiFont ,56);
        text("START",250,215);
        textFont(uiFont , 19);
        text("Clear High Score",258,263);
    }
    else if (gameState == End)
    {
        fill(180,100,180);
        strokeWeight(2);
        stroke(0);
        rect(btnL,btnT,btnW,btnH, 10);
        rect(btnL,btnT + btnH + 5,btnW,25, 10);
        
        fill(0);
        textFont(uiFont ,56);
        text("END!",260,215);
        textFont(uiFont , 22);
        text("Try Again",280,264);

        if(isHighScore)
        {
            fill(180,100,180);
            rect(btnL-20,btnT-45,btnW+40,40, 10);
            fill(0);
            textFont(uiFont ,26);
            text("New High Score!",235,142);
        }
    }
    
    textFont(uiFont ,18);
    text("By Laurie Brown!",520,395);
    
    fill(cursorColor);
    triangle(mouseX, mouseY, mouseX + 20, mouseY + 10, mouseX + 10, mouseY + 20);
}

class Block
{
    bool isMarked;
    int x, y, iter;
    int frontColor, backColor;
    bool isForwards;
    
    // Animation
    bool isAnimating;
    bool isClosing;
    int animationOffset;
    int animationStart;
    int animationLength;
    
    Block(int _iter)
    {
        iter = _iter;
        x = int(iter%cols);
        y = int(iter/cols);
        isMarked = false;
        isForwards = true;
        isAnimating = false;
        animationLength = 200;
        newColors();
    }

    void newColors()
    {
        frontColor = int(random(blockColorCount));
        backColor = int(random(blockColorCount));
        
        while(backColor == frontColor)
            backColor = int(random(blockColorCount));
    }
    
    int getColor()
    {
        if(isForwards)
            return frontColor;
        else
            return backColor;
    }
    
    void flip()
    {
        if(!isAnimating)
        {
            isClosing = true;
            isAnimating = true;
            animationStart = millis();
        }
    }
    
    void draw()
    {
        strokeWeight(2);
        stroke(0);
        
        if(isAnimating)
        {
            int timePassed = millis() - animationStart;
            
            if(isClosing && timePassed  >= animationLength * 0.5)
            {
                isClosing = false;
                isForwards= !isForwards;
            }
            if(timePassed  >= animationLength)
            {
                isAnimating = false;
                endFlipAnimation();
                fill(blockColors[getColor()]);
                rect(margin + (x*blockWidth), margin + (y*blockHeight),blockWidth,blockHeight,10);
                return;
            }
            
            if(isClosing)
            {
                offset = blockWidth * ((timePassed / (animationLength * 0.5)));
            }
            else
            {
                offset = blockWidth * (1.0 - ((timePassed / (animationLength * 0.5)) - 1.0));
            }
            
            fill(blockColors[getColor()]);
            rect(margin + (x*blockWidth) + (offset*0.5), margin + (y*blockHeight),blockWidth - offset,blockHeight,10);
        }
        else
        {
            fill(blockColors[getColor()]);
            rect(margin + (x*blockWidth), margin + (y*blockHeight),blockWidth,blockHeight,10);
        }
    }
    
    void endFlipAnimation()
    {
        if(isMarked)
        {
            if(isForwards)
            {
                if(gameTime > 120)
                {
                    
                }
                {
                    backColor = int(random(blockColorCount));
                    while(backColor == frontColor)
                        backColor = int(random(blockColorCount));
                }
            }
            else
            {
                if(gameTime > 120)
                {
                    
                }
                {
                    frontColor = int(random(blockColorCount));
                    while(backColor == frontColor)
                        frontColor = int(random(blockColorCount));
                }
            }
            isMarked = false;
        }
    }
    
    void pop()
    {
        flip();
    }
}

void mousePressed()
{
    isPressing = true;
    holdTime = millis();
}

void mouseReleased()
{
    isPressing = false;
    isHolding = false;
    cursorColor = 0;
    
    if(gameState == Playing && mouseX>margin && mouseY>margin && millis() - holdTime < holdLength)
    {
        x = int((mouseX-margin)/blockWidth);
        y = int((mouseY-margin)/blockHeight);
        blocks[(y*cols) + x].flip();
    }
    else if (gameState == Start)
    {
        if(mouseX < btnR && mouseX > btnL && mouseY < btnB && mouseY > btnT)
        {
            gameState = Playing;
        }
        else if(mouseX < btnR && mouseX > btnL && mouseY > btnB + 5 && mouseY < btnB + 30)
        {
            highScore = 0;
            saveStrings("highscore.txt", {0});
        }
    }
    else if (gameState == End)
    {
        if(mouseX < btnR && mouseX > btnL && mouseY > btnB + 5 && mouseY < btnB + 30)
        {
            reset();
        }
    }
}

void popTest()
{
    cursorColor = 255;
    
    x = int((mouseX-margin)/blockWidth);
    y = int((mouseY-margin)/blockHeight);
    
    popCount = 0;
    poppedBlocks = new Array();
    canPop(blocks[(y*cols) + x]);

    for(i = 0; i < poppedBlocks.length; i++)
    {
        if(popCount >= 4)
        {
            score += popCount * popCount * 5;
            poppedBlocks[i].pop();
        }
        else
            poppedBlocks[i].isMarked = false;
    }
}

bool canPop(Block block)
{
    block.isMarked = true;
    poppedBlocks[popCount] = block
    popCount++;
    if(block.x-1 >= 0 && !blocks[block.iter-1].isMarked  && block.getColor() == blocks[block.iter-1].getColor())
    {
        canPop(blocks[block.iter-1]);
    }
    if(block.x+1 < cols &&  !blocks[block.iter+1].isMarked  && block.getColor() ==  blocks[block.iter+1].getColor())
    {
        canPop(blocks[block.iter+1]);
    }
    if(block.y-1  >= 0 && !blocks[block.iter-cols].isMarked   && block.getColor() == blocks[block.iter-cols].getColor())
    {
        canPop(blocks[block.iter-cols]);
    }
    if(block.y+1 < rows &&  !blocks[block.iter+cols].isMarked  && block.getColor() ==  blocks[block.iter+cols].getColor())
    {
        canPop(blocks[block.iter+cols]);
    }
}

void reset()
{
    gameState = Start;
    prevSecond = 0;
    currSecond = 0;
    gameTime = 0;
    if(isHighScore)
        highScore = score;
    score = 0;
    isHighScore = false;
    
    for (i = 0; i < rows*cols; i++)
    {
        blocks[i].newColors();
    }
}

void loadHighScore()
{
    File f = localStorage["highscore.txt"];
    if (f != null) 
    {
        list = loadStrings("highscore.txt");
        highScore = list[0];
    }
}