> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.Vwbn4Hm8Oio/rev.799
 * 
 * authors: 
 *   Eugene Lee
 *   

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



color head=color(255);
color body1=color(235);
color body2=color(215);
color body3;
color body4;
color body5;
color body6;
color body7;
color body8;
color body9;
color bottom;
color food=color(#FF0000);

ArrayList<body> bodies;

int foodPosX=-1;
int foodPosY=-1;
int multiCount=1;
int foodEaten=0;
int realFoodEaten=0;

int newBodyX;
int newBodyY;
color newBodyC;

boolean loopEnabled=false;
boolean gameStarted=false;
boolean gamePaused=false;
boolean gameOvered=false;
boolean titleEnabled=true;

int snakePosition=0;
int snakeNewPos;
int snakeSpeed=10;

int title=50;
int words=16;

void setup()
{
    //canva's settings
    size(600,450);
    background(0);
    strokeWeight(2);
    stroke(0);
    frameRate(snakeSpeed); 
    noLoop();
    
    //create first three bodies
    bodies=new ArrayList<body>();
    bodies.add(new body(29,37,head));
    bodies.add(new body(28,37,body1));
    bodies.add(new body(27,37,body2));
}

void draw()
{
    background(0);
    
    //draw snake
    for(int i=bodies.size()-1;i>=0;i--)
    bodies.get(i).draw();
    
    //draw food
    fill(#FF0000);
    rect(foodPosX*6,foodPosY*6,6,6); 
    
    //draw starter
    if(titleEnabled==true)
    {
        fill(255);
        textAlign(CENTER,CENTER);
        textSize(title);
        text("Snake Game",400,100);
        textAlign(LEFT,CENTER);
        textSize(words);
        text("Use arrows to control your snake,\nSpace bar to start/pause.\nFull screen will be your best choice.",270,170);
        text("If you're ready, why not start?",270,300);
    }
    
    //draw pause
    if(gameStarted==true&&gamePaused==true)
    {
        fill(#FF0000);
        rect(190,200,220,50);
        fill(255);
        textAlign(CENTER,CENTER);
        textSize(title);
        text("PAUSED",width/2,height/2);
    }
    
    //draw gameOver
    if(gameOvered==true)
    {
        fill(0);
        rect(140,100,320,50);
        rect(200,255,200,40);
        fill(255);
        textAlign(CENTER,CENTER);
        textSize(title);
        text("GAME OVER",width/2,height/2-100);
        textSize(words);
        text("Your score is "+realFoodEaten+".\nPress Space bar to restart.",width/2,height/2+50);
    }
    
    //test titleEnabled
    if(titleEnabled==true)
    noLoop();
    
    //test GamePaused
    if(gameStarted==true&&gamePaused==true)
    noLoop();
    
    //test GameOver
    if(gameOvered==true)
    gameOver();
    
    //set newBody
    newBodyX=bodies.get(bodies.size()-1).returnX();
    newBodyY=bodies.get(bodies.size()-1).returnY();
    if(bodies.size()>=10)
    newBodyC=bottom;
    else
    {
        switch(bodies.size())
        {
            case 3:
            newBodyC=body3;
            break;
            case 4:
            newBodyC=body4;
            break;
            case 5:
            newBodyC=body5;
            break;
            case 6:
            newBodyC=body6;
            break;
            case 7:
            newBodyC=body7;
            break;
            case 8:
            newBodyC=body8;
            break;
            case 9:
            newBodyC=body9;
            break;
        }
    }
    
    //move snake
    snakePosition=snakeNewPos;
    if(snakePosition==0)
    {
        for(int i=bodies.size()-1;i>0;i--)
        {
            bodies.get(i).setSnake(bodies.get(i-1).returnX(),bodies.get(i-1).returnY());
        }
        bodies.get(0).setSnake(bodies.get(0).returnX()+1,bodies.get(0).returnY())
    }
    else if(snakePosition==1)
    {
        for(int i=bodies.size()-1;i>0;i--)
        {
            bodies.get(i).setSnake(bodies.get(i-1).returnX(),bodies.get(i-1).returnY());
        }
        bodies.get(0).setSnake(bodies.get(0).returnX(),bodies.get(0).returnY()-1)
    }
    else if(snakePosition==2)
    {
        for(int i=bodies.size()-1;i>0;i--)
        {
            bodies.get(i).setSnake(bodies.get(i-1).returnX(),bodies.get(i-1).returnY());
        }
        bodies.get(0).setSnake(bodies.get(0).returnX()-1,bodies.get(0).returnY())
    }
    else
    {
        for(int i=bodies.size()-1;i>0;i--)
        {
            bodies.get(i).setSnake(bodies.get(i-1).returnX(),bodies.get(i-1).returnY());
        }
        bodies.get(0).setSnake(bodies.get(0).returnX(),bodies.get(0).returnY()+1)
    }
    
    //eat food
    if(bodies.get(0).returnX()==foodPosX&&bodies.get(0).returnY()==foodPosY)
    {
        bodies.add(new body(newBodyX,newBodyY,newBodyC));
        while(multiCount>0)
        {
            multiCount=0;
            foodPosX=random(2,98);
            foodPosY=random(2,70);
            foodPosX=int(foodPosX);
            foodPosY=int(foodPosY);
            for(int i=0;i<bodies.size();i++)
            {
                if(foodPosX==bodies.get(i).returnX()&&foodPosY==bodies.get(i).returnY())
                multiCount++;
            }
        }
        multiCount=1;
        foodEaten++;
        realFoodEaten++;
    }
    
    //enlarge frameRate
    if(foodEaten==1)
    {
        snakeSpeed+=1;
        frameRate(snakeSpeed);
        foodEaten=0;
    }
    
    //eat itself
    for(i=1;i<bodies.size();i++)
    {
        if(bodies.get(0).returnX()==bodies.get(i).returnX()&&bodies.get(0).returnY()==bodies.get(i).returnY())
        gameOvered=true;
    }
    
    //eat wall
    if(bodies.get(0).returnX()<0||bodies.get(0).returnX()==100||bodies.get(0).returnY()<0||bodies.get(0).returnY()==75)
    {
        gameOvered=true;
        for(int i=0;i<bodies.size()-1;i++)
        bodies.get(i).setSnake(bodies.get(i+1).returnX(),bodies.get(i+1).returnY());
        bodies.get(bodies.size()-1).setSnake(newBodyX,newBodyY);
    }
}

void gameStart()
{
    while(multiCount>0)
    {
        multiCount=0;
        foodPosX=random(2,98);
        foodPosY=random(2,70);
        foodPosX=int(foodPosX);
        foodPosY=int(foodPosY);
        for(int i=0;i<bodies.size();i++)
        {
            if(foodPosX==bodies.get(i).returnX()&&foodPosY==bodies.get(i).returnY())
            multiCount++;
        }
    }
    multiCount=1;
    decideColor();
    for(int i=2;i>=0;i--)
    bodies.remove(i);
    bodies.add(new body(30,37,head));
    bodies.add(new body(29,37,body1));
    bodies.add(new body(28,37,body2));
}

void gameOver()
{
    noLoop();
    gameStarted=false;
    gamePaused=false;
    for(int i=bodies.size()-1;i>=0;i--)
    bodies.remove(i);
    head=(255);
    body1=(235);
    body2=(215);
    bodies.add(new body(29,37,head));
    bodies.add(new body(28,37,body1));
    bodies.add(new body(27,37,body2));
    foodPosX=-1;
    foodPosY=-1;
    foodEaten=0;
    realFoodEaten=0;
    snakeSpeed=10;
    frameRate(snakeSpeed);
    snakePosition=0;
    snakeNewPos=0;
}

void decideColor()
{
    int colorNum;
    colorNum=random(0,6);
    colorNum=int(colorNum);
    if(colorNum==0)
    {
        head=(#FFFFFF);
        body1=(#EBEBEB);
        body2=(#D7D7D7);
        body3=(#C3C3C3);
        body4=(#AFAFAF);
        body5=(#9B9B9B);
        body6=(#878787);
        body7=(#737373);
        body8=(#5F5F5F);
        body9=(#4B4B4B);
        bottom=(#373737);
    }
    else if(colorNum==1)
    {
        head=(#FF0000);
        body1=(#EB0000);
        body2=(#D70000);
        body3=(#C30000);
        body4=(#AF0000);
        body5=(#9B0000);
        body6=(#870000);
        body7=(#730000);
        body8=(#5F0000);
        body9=(#4B0000);
        bottom=(#370000);
    }
    else if(colorNum==2)
    {
        head=(#FFFF00);
        body1=(#EBEB00);
        body2=(#D7D700);
        body3=(#C3C300);
        body4=(#AFAF00);
        body5=(#9B9B00);
        body6=(#878700);
        body7=(#737300);
        body8=(#5F5F00);
        body9=(#4B4B00);
        bottom=(#373700);
    }
    else if(colorNum==3)
    {
        head=(#00FF00);
        body1=(#00EB00);
        body2=(#00D700);
        body3=(#00C300);
        body4=(#00AF00);
        body5=(#009B00);
        body6=(#008700);
        body7=(#007300);
        body8=(#005F00);
        body9=(#004B00);
        bottom=(#003700);
    }
    else if(colorNum==4)
    {
        head=(#00FFFF);
        body1=(#00EBEB);
        body2=(#00D7D7);
        body3=(#00C3C3);
        body4=(#00AFAF);
        body5=(#009B9B);
        body6=(#008787);
        body7=(#007373);
        body8=(#005F5F);
        body9=(#004B4B);
        bottom=(#003737);
    }
    else
    {
        head=(#FF00FF);
        body1=(#EB00EB);
        body2=(#D700D7);
        body3=(#C300C3);
        body4=(#AF00AF);
        body5=(#9B009B);
        body6=(#870087);
        body7=(#730073);
        body8=(#5F005F);
        body9=(#4B004B);
        bottom=(#370037);
    }
}

void keyTyped()
{
    if(key==' ')
    {
        if(gameStarted==false)
        {
            if(gameOvered==false)
            {
                loop();
                gameStarted=true;
                titleEnabled=false;
                gameStart();
            }
            else
            {
                gameOvered=false;
                titleEnabled=true;
                loop();
            }
        }
        else
        {
            if(gamePaused==true)
            {
                gamePaused=false;
                loop();
            }
            else
            gamePaused=true;
        }
    }
}

void keyPressed()
{
    if(gameStarted==true&&gamePaused==false)
    {
        if(key==CODED)
        {
            if(keyCode==RIGHT&&snakePosition!=2)
            snakeNewPos=0;
            else if(keyCode==UP&&snakePosition!=3)
            snakeNewPos=1;
            else if(keyCode==LEFT&&snakePosition!=0)
            snakeNewPos=2;
            else if(keyCode==DOWN&&snakePosition!=1)
            snakeNewPos=3;
        }
    }
}

public class body
{
    int x;
    int y;
    color c;
    public body(int x,int y,color c)
    {
        this.x=x;
        this.y=y;
        this.c=c;
    }
    public void draw()
    {
        fill(this.c);
        rect(this.x*6,this.y*6,6,6);
    }
    public int returnX()
    {
        return(this.x);
    }
    public int returnY()
    {
        return(this.y);
    }
    public void setSnake(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
}