/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://cisc1600.sketchpad.cc/sp/pad/view/ro.wfdOYiVAoUE/rev.700
*
* authors:
* Joey Ching
* Xiaowen Huang
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
//Project 2 - Snake Game
bool gameEnd;
Snake s1;
Food apple;
bool foodEaten;
int score;
bool run;
float R, G, B;
int count, speed;
/***********************Setup Function***********************/
void setup() {
size(300, 300);
rectMode(CENTER);
s1 = new Snake();
apple = new Food();
foodCount = 0;
speed = 15;
gameEnd = false;
score = 0; count = 0;
run = true;
}
/***********************Draw Function***********************/
void draw() {
frameRate(speed);
background(204);
R = random(255);
G = random(255);
B = random(255);
/****************** instructions ******************/
fill(0, 0, 0, 80);
textSize(15); textAlign(LEFT);
text("Instructions:", 10, 30);
text("Control the snake using arrow key", 10, 50);
text("Don't touch the black border", 10, 70);
text("And don't run into your tail", 10, 90);
/****************** instructions ******************/
if(run){
/************ border ************/
strokeWeight(3);
line(0, 0, 0, height);
line(0, 0, width, 0);
line(0, height-2, width, height-2);
line(width-1, 0, width-1, height);
/************ border ************/
strokeWeight(1);
/**** run game****/
s1.getDirection();
s1.move();
fill(R, G, B);
s1.display();
/**** run game****/
/***************************** food generator ******************************/
apple.display();
foodEaten = checkEaten(s1.snakeX[0], s1.snakeY[0], apple.foodX, apple.foodY);
if(foodEaten){
apple.newFood();
s1.addBlock();
score++; count++;
}
/***************************** food generator ******************************/
/******** show current score ********/
textAlign(RIGHT);
fill(0, 102, 153, 50);
textSize(20);
text("SCORE", 270, 230);
textSize(40);
text(score, 270, 270);
/******** show current score ********/
/***** increase speed gradually *****/
if(count != 0 && count%5 == 0){
speed+=3;
count++;
}
/***** increase speed gradually *****/
/******************************** check game end *********************************/
gameEnd = (hitBorder(s1.snakeX[0], s1.snakeY[0]) || hitSelf(s1.snakeX, s1.snakeY));
if(gameEnd){
run = false;
}
/******************************** check game end *********************************/
}
else{
again = gameOverPage();
}
}
/***********************Class Snake***********************
** Building snake with several pairs of x, y-coordinates *
**********************************************************/
class Snake{
int sLength;
int[] snakeX;
int[] snakeY;
char direction;
int speed;
Snake(){ //constructor
sLength = 1;
snakeX = new int[150];
snakeY = new int[150];
snakeX[0] = width/2; snakeY[0] = height/2;
}
void display(){ //display snake
for(int i = 0; i < sLength; i++){
rect(snakeX[i], snakeY[i], 10, 10);
}
}
void addBlock(){ //add one more block to tail
snakeX[sLength] = snakeX[sLength-1] + 10;
snakeY[sLength] = snakeY[sLength-1] + 10;
sLength++;
}
void getDirection(){ //get direction from keyboard
if(keyPressed == true && key == CODED){
if(keyCode == LEFT && direction != 'd'){
direction = 'a';
}
else if(keyCode == RIGHT && direction != 'a'){
direction = 'd';
}
else if(keyCode == UP && direction != 's'){
direction = 'w';
}
else if(keyCode == DOWN && direction != 'w'){
direction = 's';
}
}
/*if(keyPressed == false){ //disable auto running for test
direction = ' ';
}*/
}
void move(){ //function to make snake move
for(int i = sLength-1; i > 0; i--){ //shift blocks afterwards
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
switch(direction){ //and then make new head
case 'w': //according to directions
snakeY[0] -= 10;
break;
case 's':
snakeY[0] += 10;
break;
case 'a':
snakeX[0] -= 10;
break;
case 'd':
snakeX[0] += 10;
break;
}
}
}
/**************** Class Snake Ends ***********************/
/***********************Class Food ***********************
** Generating food randomly *
**********************************************************/
class Food{
int foodX, foodY;
Food(){ //constructor to generate first food
foodX = (round(random(295))+1);
foodY = (round(random(295))+1);
}
void display(){ //display food by drawing red dot
ellipseMode(CENTER);
fill(255, 0, 0);
ellipse(foodX, foodY, 8, 8);
}
void newFood(){ //generate new food location if eaten
foodX = (round(random(295))+1);
foodY = (round(random(295))+1);
}
}
/**************** Class Food Ends ***********************/
bool checkEaten(int snakeX, int snakeY, int foodX, int foodY){ //check if previous food is eaten
if(dist(snakeX, snakeY, foodX, foodY) < 10){
return true;
}
else{
return false;
}
}
bool hitBorder(int snakeX, int snakeY){ //check if the snake hits the border
if(snakeX <= 2 || snakeX >= width-2 || snakeY <= 2 || snakeY >= height-2){
return true;
}
else{
return false;
}
}
bool hitSelf(int[] snakeX, int[] snakeY){ //check if the snake runs into itself
for(int i = 1; i < snakeX.length; i++){
if(dist(snakeX[0], snakeY[0], snakeX[i], snakeY[i]) < 10){
return true;
break;
}
}
}
void gameOverPage(){ //displaying game over and final score
background(0);
textAlign(CENTER);
fill(200, 200, 0);
text("Game Over", 150, 130);
textSize(20);
text("Your final score:", 150, 150);
textSize(30);
text(score, 150, 180);
}