Final Project-Snake!!

I can’t believe we’ve reached the end of our trial two week vestibule! You know what else I can’t believe? That I just coded Snake for my final project.

Sometime last week when I was coding a sunset or something it dawned on me that what I was doing was comparable to Snake. Controlling an object’s coordinates with key presses, that’s a Snake thing! I’m not sure why but since then it’s been a small goal of mine to make my own Snake.

And I did!

(take a break here and go play it.)

And guess what dear reader, it was easily the hardest thing I’ve coded to date. Way more complicated than that sunset. I seriously underestimated the complexities of Snake and that’s something I never thought I would’ve said about a 2003 Nokia game.

My first step was breaking down Snake by elements. I wrote a couple pages of what I thought I’d have to do Wednesday night, then started coding and realized that I’d forgotten certain things.

Most importantly, I never considered scale.

Snake runs on a grid, and increments its movement by a certain amount. If you generate the snake’s food at random, it could possibly generate at a decimal x or y value, which wouldn’t line up with the snake.

It took me a while to grasp this concept, but once I did I understood why I needed to create the variable “scl” and set my fruit’s and my snake’s size and speed according to it.

function fruitLocation() {
  let col = floor(width / scl);
  let row = floor(height / scl);
  fruitL = createVector(floor(random(col)), floor(random(row)));
  fruitL.mult(scl)

In the code above I’m creating a function that will generate my fruit at random x and y values that lie across my grid. The grid is defined with the variables “col” and “row”, both are the parameters of the canvas divided by “scl”, which I set to 20.

I spent more time than I’m willing to admit attempting to add the function shown above to my Fruit constructor, but it just wouldn’t work there. Ultimately I had to have it as a standalone function in order to be able to call the variable defined in it “fruitL” which gives me my random x and y locations for my fruit.

One of the biggest challenges in this project for me was that everything is interrelated and it gets very confusing rather quickly. I’m sure there are more streamlined ways to code Snake that involve more modularization, and I look forward to getting to that level… because my way was definitely the long way.

The most complex part about snake is that when the snake collides with the fruit the fruit must disappear and regenerate and the snake must grow in length. This means that the snake’s location needs to be tracked in regards to it’s distance from the fruit’s location, and when those two intersect actions need to happen.

this.eat = function(pos) {
    let d = dist(this.x, this.y, pos.x, pos.y)
    if (d < 2) {
      this.total++;
      return true;
    } else {
      return false;
    }
  };

The code above uses the function dist() to measure the distance between two x and y values, then says that if that distance is less than 2 the total variable will increase by 1.

this.update = function() {
    for (let i = 0; i < this.rattle.length - 1; i++) {
      this.rattle[i] = this.rattle[i + 1];
    }
    this.rattle[this.total - 1] = createVector(this.x, this.y);
    this.x = this.x + this.xspeed * scl;
    this.y = this.y + this.yspeed * scl;
    this.x = constrain(this.x, 0, width - scl);
    this.y = constrain(this.y, 0, height - scl);
  };

The above code was borrowed from Dan Shiffman (a man i’d never heard of two weeks ago who has come to be my personal hero). This is the code that applies the total number of fruit eaten to the snake’s length (rattle) causing it to grow. The array “rattle” is increased gradually in relation to the variable “total” and it is set as a variable to create a new x and y coordinate. When this function is called initially the i value is 1, then every time the total value of i increases as well, creating another increment of Snake.

this.show = function() {
    fill(0);
    strokeWeight(.5);
    stroke(255);

    for (let i = 0; i < this.rattle.length; i++) {
      rect(this.rattle[i].x, this.rattle[i].y, scl, scl);
    }
    rect(this.x, this.y, scl, scl);

  }
}

The code above is creating my snake, which initially appears as a 20×20 black square. By incorporating the rattle array into the x and y values, we are calling back to the update function where they were defined.

Admittedly, my grasp on why and how this part of the code works waivers. I have moments of complete comprehension but they are fleeting.

Ultimately this project was beyond my scope but I’m happy to say that working through it I really learned a lot. I’m glad I took on something ambitious because it caused me to grow as a coder. I feel much more confident about objects, constructors, and modularization now then I did before. I understand arrays but I am not a master of them, not yet anyhow. But I my understanding of them did grow through this project.

And all of this in 2 weeks! That’s wild!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website with WordPress.com
Get started
%d bloggers like this: