//index keeps track of boxes index which can help us move and manipulate the grid
let index = 0;
//box class creates box objects which have the properties of x postion ,y postion , state ,previousState and index
//index helps us find new boxes
//box has a method called changeState() which takes in 3 possible states^ : "snk","mpt","pnt" .
// "note : the changeState() method can take in other states and will not result in an error
// ,but will cause rendering and logic issues in the game"
// states pnt for point, mpt for empty , snk for snake.
//the method changes the previousState to the current state and then changes the current state to the state we specifed
//each box has an unique index which we can use to axcess it
class box {
constructor(x,y,stt){
this.x = x;
this.y = y;
this.state = stt;
this.previousState = null;
this.index = index;
index++;
}
changeState(stt){
this.previousState = this.state;
this.state= stt;
}
}
//the game object keeps track of the ingame grid ,if there is a point present in the game,
//if the game has been lost
const game = {
grid : [],
haslost : false,
hasPoint : true,
points : 0,
}
//snake object
//directions "p","l","d","r"
function findBox (box,dir){
if(dir == "p") return game.grid[box.index-9];
if(dir =="l") return game.grid[box.index-1];
if(dir == "d") return game.grid[box.index+9];
if(dir =="r") return game.grid[box.index+1];
return null;
}
const snake = {
headbox: {},
tailbox: {},
boxes: [],
previousMove : null,
move:function (dir) {
if(game.haslost) return 0;
//find the new box
let temp = findBox(this.headbox,dir);
if (temp == null) return 0;
if(temp === undefined) game.haslost = true;
let tempCord = temp.y;
if(dir == "l")tempCord++;
else tempCord--;
if(tempCord > 8 || tempCord < 0 && (dir == "l" || dir == "r")) game.haslost = true;
if(temp.state == "snk") game.haslost = true;
temp.changeState("snk");
//add it to boxes
this.boxes.push(temp);
//change the headbox
this.headbox = temp;
//set tailbox
this.tailbox.changeState("mpt");
this.boxes.shift();
this.tailbox = this.boxes[0];
this.previousMove = dir;
}
,
eat: function () {
if(this.headbox.previousState == "pnt"){
game.hasPoint = false;
game.points++;
//find new tailbox in opposite direction
let oppositeDir;
if(this.previousMove === "p") oppositeDir = "d";
if(this.previousMove === "l") oppositeDir = "r";
if(this.previousMove === "d") oppositeDir = "p";
if(this.previousMove === "r") oppositeDir = "l";
let temp = findBox(this.tailbox,oppositeDir);
//change state & push it into boxes
temp.changeState("snk");
this.boxes.unshift(temp);
// update tailbox
this.tailbox = temp;
}
}
}
function start() {
let randX;
let randY;
do{
randX = Math.floor(Math.random()*9);
randY = Math.floor(Math.random()*9);
}while(randX == 4 && randY == 4)
for(let i = 0; i < 9; i++){
for(let j = 0 ; j < 9 ; j++){
let tempbox;
if(i == 4 && j == 4){
tempbox = new box(j,i,"snk");
snake.headbox = tempbox;
snake.tailbox = tempbox;
snake.boxes.push(tempbox);
}else if ( i == randX && j == randY){
tempbox = new box(j,i,"pnt");
game.hasPoint = true;
}else{
tempbox = new box(i,j,"mpt");
}
game.grid.push(tempbox);
}
}
}
function generatePoint(){
let randIndex;
do randIndex = Math.floor(Math.random()*80);
while(game.grid[randIndex].state == "snk");
game.hasPoint = true;
game.grid[randIndex].changeState("pnt");
}
start();
//logic rendering
//setup createsCanvas which will be rendered to
function setup() {
createCanvas(445,445);
}
//currentDirection is the direction the snake is moving and the nextDirectoin will be
//the direction where the snake will go.
let currentDirection = null;
let nextDirection = null;
//keyTyped() function handles the input/output of the game.It detects when a key is pressed
//and checks if the key was ether a,d,w or s and it also checks what is the current direction.
//If the current direction isn't the opposite of the next direction ,the next direction gets set to the
//the coresponding direction
function keyTyped() {
if (key === "a" && currentDirection != "r") nextDirection = "l";
else if (key === "d" &¤tDirection!= "l") nextDirection = "r";
else if (key === "w" &¤tDirection!= "d") nextDirection = "p";
else if (key === "s" &¤tDirection!= "p") nextDirection = "d";
}
//wait time is time between each uptade in the game it will either be 300 or 1000 milliseconds
let waitTime = 300;
//setInterval waits for waitTime miliseconds then updates the snakes postion ,makes the snake
//eat and updates the direction
setInterval(() => {
currentDirection = nextDirection;
snake.eat();
snake.move(nextDirection);
}, waitTime);
//draw()^ handles the rendering of the game and a few of its logical components
//"note:the draw function is in an infinte loop"
function draw() {
// we initlize wait time to 300 ms
waitTime = 300;
//if the snakes head is at the edge of the grid^ we set the wait time to 1000 ms so that the player has more time to evade loss
//"note: we can tell wether or not if the player is at the edge by looking at the x and y cordinates of the snakes head.
//if we at least one of the cordinates is 8 or 0 we know that the
//head is at the edge since we are using a 9 by 9 grid (keep in mind that indexing both in the y and the x direction begins at 0)"
if(snake.headbox.x == 8 || snake.headbox.x == 0 || snake.headbox.y == 8 || snake.headbox.y == 0) waitTime = 1000;
// if the game objects has lost property has been set to true we alret the user
if(game.haslost == true) alert('waage');
// if there are no new points in the grid we create one
if(game.hasPoint == false) generatePoint();
// we clear the screen of the prevous frame
background(155,122,33);
// counter helps us keep tract of which box we are rendering
let counter = 0;
//we use a nested loop itirate over each one of the grids elemnts in a way that we can have an easy time
//get the cordinates of the boxes which will match the i and j iterators
for(let i = 0; i < 9; i++){
for(let j = 0; j < 9; j++){
//nostroke() stops the game from making strokes
noStroke();
//c by default will be 255 but will change if the boxes state is ethier "snk" or "pnt"
let c = color(255)
if(game.grid[counter].state == "snk") c = color(99,205,11);
if(game.grid[counter].state == "pnt") c = color(153,23,144);
fill(c);
//calucaltes the rectangles postion and draws it
rect(5+j*45,5+i*45,45,45);
//update the counter so that we can keep trac of things
counter++;
}
}
}