I mentioned in my last post that I’d signed up for a course designed to guide me through the process of going from dabbler to professional grade material in the world of software development. This is no small task so I felt it a wise investment to sign up with someone who had been down the path themselves. And a wise investment it was, indeed.

So, let me get to the subject of this post, my first original build in JavaScript. Let me first say that this will not be about how I built my first app (although I’d be happy to discuss it should someone have an interest) but, more so, what the experience of building it was like. And that is because there is a very valid reason why any decent developer will recommend that, if you really want to improve, you should build something yourself. And the reason is this: in building something original, a deep and organic learning process takes place in your mind that cannot be replaced by anything. This is where you learn how to create code instead of just reading or writing it. But I digress.

For this app I was tasked with building a “Snake Game”, a classic in the world of mobile games but far trickier to build than you might think. You can  review my code here on GitHub or play the game for yourself here on CodePen. My instructor was kind enough to give me some resources in the form of online tutorials, articles and recommended books and a solid deadline of 4 weeks from starting to begin with but, after that, it was “go get em’ kid” for I was expected to build from scratch without the help of any libraries. The “deliverables” as they were called were the following:

Snake game ends when:

○ Snake touches itself

○ Snake touches the outside border

  • When the game ends, the gameplay should stop and the user should be notified that the game is over
  • The snake should grow one length whenever it eats the apple
  • The apple should randomly place itself on the board after snake consumes the apple
  • The snake should be controlled by the arrow keys on the keyboard
  • The game will show a score of how many apples have been eaten

When I first read all of that, I really questioned if I’d gotten in over my head. While I was no stranger to online tutorials or sticking with working on a problem long enough to fix it, the idea of making a responsive game that did things on the screen was beyond me as the extent of my coding experience extended no further than basic HTML and CSS.

However, after working through the recommended tutorials and reading and re-reading the code I’d written in following along, I learned to isolate certain elements in the form of functions and certain syntax that I thought could provide some of the functionality I would need for my snake game. When it came time to start building, however, I began to realize just how much I’d been relying on simply following a tutorial instead of building the code in as I thought it would be needed for the end result. There’s a subtle difference there but it tends to become rather large when you start working sans tutorial. With a tutorial, you can get a certain degree of confidence in building something but you are likely not absorbing the core knowledge and understanding of the structure of the code as deeply as you might think. Actually, you may not be absorbing it at all.

This becomes alarmingly obvious when you find yourself in front of the black screen of the text editor. Everything is up to you and you suddenly take on a new respect and appreciation for the subtleties and details of how software languages actually work. “Oh, yeah”, you think to yourself. “I should look at that again.” And, while code from other projects (whether you wrote it or not) can be helpful there is still the issue of adapting it to the specific structure of what you’re working on. And that can be quite difficult.

You need to be exceedingly clear about how you name and organize the elements of your work. Failure to do so can lead to hours of lost time and dangerous levels of frustration. Another thing I’ve learned is the value of the Chrome and Firefox developer tools as they can give you live feedback on how your code is actually functioning.

Alright, with all of that said, let me get into the nitty gritty of how my project went. But first, a quick disclaimer. While the text below accurately details my journey from the blackness of a new file on VS code to fully functional Snake Game, my repository commit history will likely reveal a much messier and troubled story. And that is because one’s first real original build is generally hard. Like, really hard. And that is not even mentioning the initial learning curve with Git (which is something I am still working on). So, baring that in mind, take my words below to speak not of the exact sequence of events but as of what came out of a tremendous amount of struggle in what often felt like fumbling around in the dark. And so, without further ado, my experience building my first custom JavaScript app:

  1. Building The Canvas

Nothing happens in the browser without and HTML file to support it. So I referred back to the tutorials I’d been provided to figure out how to get my “snake arena”/HTML canvas to display correctly. In my “snake.html” file I created the following CSS in the head section section:

<style>
    * { padding: 0; margin: 0; }
    canvas { background:    #000000;
display:block;
margin:0auto;
border-color:#A9A9A9;
border-style:dashed;
border-width:8px;
margin-top:80px;
}
</style>

This created, 80 pixels from the top of the browser viewport, a black background with a dashed, gray border of 8 pixels that resembles something like a brick wall (all the better for my snake to crash into).

In the body section, I wrote the following:

<canvas id="myCanvas" width="600" height="600"></canvas>
<script src="snake.js"></script>

Here, in the canvas id= tag, a square of 600 x 600 pixels is being declared. The next line is a script tag which contains a link, src=”snake.js”, to the source file where all of the JavaScript for the Snake Game was to be written.

2. Building The Animation Structure

This is where the power and majesty of the JavaScript setInterval() method really came to be realized. And where, as my teacher explained, browser animation came to be know as something more like a “flipbook” than an object moving fluidly across the screen. That is, the setInterval() method tells the browser how often to refresh the function being called instead of telling an object how often to “move”. Without this simple method being called, literally nothing would move on the screen. There is more to it, as I would painfully learn later on, but this was enough to get started.

To keep things simple, I created a kind of “Master Function” for all other functions to be called in. I called it “Draw();” and set the refresh interval at 100 microseconds/ one-tenth of a second. This is what it looked like:

Draw () {
//call all onscreen functions here :-)
}

setInterval(Draw, 100);

Simple, no? As time passed and I got more immersed in making the gosh darn thing work, I found that either increasing or decreasing the length of the refresh interval made test functionality much easier and faster. And I would end up doing A LOT of testing.

3. Building The Snake

For this, I started with declaring the snake as a hard coded array of 5 squares with a height and width of 10 pixels named “snake”. I then created a function called drawSnakePart() and called the array “snake” as the parameter/argument for it to work with:

function drawSnakePart(snake) {
     ctx.fillStyle = 'lightgreen';
     ctx.strokestyle = 'darkgreen';
     ctx.fillRect(snake.x, snake.y, 10, 10);
     ctx.strokeRect(snake.x, snake.y, 10, 10);
}

This function designates the color, size and start position of each element in the “snake” array. The variable “ctx” equals the JavaScript method getContext and defines the canvas, in the case of my Snake Game, as two dimensional.
I was very happy with all of this but, to my dismay, nothing would appear on the canvas. And that is because I needed to create a separate function that would loop through the snake array and actually call it onto the canvas. So, I wrote this:
function drawSnake() {
     snake.forEach(drawSnakePart)
}

Here, the JavaScript “forEach” method is calling the drawSnakePart() function as a parameter/argument and essentially printing out each element as defined therein. And the position of each element in the the array being called by drawSnakePart() is defined in the variable “snake”. It was at this point that I began to appreciate the interelatedness of variables, loops and functions in JavaScript. Honestly speaking, at the time of writing it, I had very little idea of what it was or wasn’t working. Now in retrospect and as I write this post, the logic of it is somewhat mysteriously more clear to me. Such is the value of review, reflection and the passage of time, I suppose.
So now with my “snake” array being called by the drawSnakePart() function which was in turn being called by the drawSnake() function I had (wait for it) 10 green squares on my canvas at exactly where they had been designated to be by the hard coded coordinates in the “snake” variable. Yay! There it was my snake. But, wow, did I have a lot more work to do.

4. Getting it to move

My next step was getting the snake to move. Again, I referred to the tutorials I’d been provided. Here, I believe I should say something about those tutorials. While they were very well chosen and gave me a much deeper understanding of how JavaScript works, both of them involved creating games with a ball. There is, I would learn rather thoroughly, a large difference in coding the movements of a ball (which is simply one element) and coding the movements of a snake/array (which is a successive series of elements). It proved to be exceedingly challenging but my teacher was incredibly gracious and skillful at leading me through it.

Here is what I started with:

function moveSnake() {
for(var i = 0; i < snake.length; i++)

snake[i}.x += dx
}

Basically, this function uses a for loop that creates a variable that moves through the length of the snake array. This allows any functionality you apply to one element of the array to apply to all of it. This can come in handy, let me tell you. Outside the for loop, the line snake[i].x += dx defines the motion of the snake as the value of the variable “dx” (10 pixels to the right) for every tenth of a second. 10 pixels, coincidentally, is also the width of each section of the snake thus giving it the impression of moving exactly one unit’s length each time.

Boy was I excited to test this! And what did I get? I got a bright green “snake” increasing by 10 pixels to the right every tenth of a second. It went from ten, to eleven then twelve, thirteen, fourteen, fifteen, sixteen units and on and on across the screen. Instead of “moving” as I had intended, it was simply “growing” in length. “Stupid snake!” I thought. “You’re supposed to move, not grow! What’s wrong with you?”. I was so frustrated I literally gave up for the day and walked away from the computer honestly wondering how I’d made it this far in life when I was so god damn dumb. But not before making a quick video outlining my situation, commiting my code to GitHub and creating a working replica on codepen for my teacher to see.

Well, later that evening while teaching a class, I remembered a section in a tutorial where after creating a ball in motion it rendered as a line increasing in length rather than a ball moving on the screen. It was the exact same problem. But, of course, in the tutorial it was fixed immediately. So, I went back to the tutorial’s source code and found this simple line of code:

ctx.clearRect(0, 0, myCanvas.width, myCanvas.height);

This method is what “flips” the book, so to speak, in the “flipbook” of browser animation in JavaScript. My issue was not that the snake wasn’t “moving” it was that it’s previous position(s) was not being cleared from the canvas. This made it look like a continuously growing line rather than a discrete group of 10 units. So, after pasting the above line of code in to my Draw(); function, my “nake” was moving across the screen exactly as I had wanted it to; 10 pixels to the right every tenth of a second. Yay! Then it went off the canvas and, according to the Chrome Developer tools, roughly across the street according to it’s x position which read something like 40500 pixels. Ha ha. I thought that was pretty funny.

5. Building the random replacement of apple, score increase and growth of snake into one action

This part of the game was initially quite intimidating. First, I needed an apple. So I wrote a function for it called drawApple();. This is what it looked like:

function drawApple() {
     ctx.fillStyle = 'red';
     ctx.strokestyle = 'darkred';
     ctx.fillRect(appleLocation.x, appleLocation.y, appleWidth, appleHeight);
     ctx.strokeRect(appleLocation.x, appleLocation.y, appleWidth, appleHeight)
    }

The variables for appleLocation x and y began as hard coded values to make testing easier. I later learned you could keep the initial hard coded position but change it based on other events and parameters should they arise. You know, all “dynamic” and what not. This fact took me some getting used to as I’d previously only worked with HTML, CSS and one tutorial on PHP.
The variables appleHeight and appleWidth never really changed but I came to appreciate the facility in encoding their size in a variable rather than always using the integer for the number of pixels. It’s a good way to be able to come back to your code and understand it even if you’ve been away for a few days. But I digress. After writing the drawApple(); function I called it in the Draw(); function and refreshed my browser. And, lo, there it was. My “apple”. A small red square of 10 pixels.
Its hard coded position was directly on the snake’s line of travel. I watched the snake get closer and then plow over the apple without even slowing down. It then went off again into… “pixel land” ? Hmmm. How to at least get something to happen when the head of the snake is equal to the coordinates of the apple? I needed a function (functions really are the best when you want your app to actually do something, no?).
I started with this:
function eatApple() {
     if (snake[0].x == appleLocation.x && snake[0].y == appleLocation.y) {
     appleLocation.x = Math.floor(Math.random() * 50) * 10;
     appleLocation.y = Math.floor(Math.random() * 50) * 10;
 }
}

As the first element in an array is 0, this became the default “head” of my snake. The if statement above essentially says “if the snake’s head x and y coordinates are the same as the apple’s x and y coordinates do something”. The “do something” part is defined in the next two lines:
appleLocation.x = Math.floor(Math.random() * 50) * 10;
appleLocation.y = Math.floor(Math.random() * 50) * 10;

Each of the two lines is remarkably similar to the other. The only difference is that one acts on the x axis of the apple and the other on the y. “Math.floor(Math.random() )” is a very common piece of code in JavaScript and one of the very few pieces in my entire project I could simply copy and paste without having to debug for an hour or two.
Essentially what it does is this:
Math.random() returns an integer lower than 1. That is, what is sometimes called a “floating point number”, or a number with a value extending past a decimal point i.e. not a “whole number”. Think “2.795601” or something like that instead of just “2” or “3”.
Math.floor() returns the value of a floating point number rounded down to the nearest whole number. So if, for example, you had “3.93” and called it into Math.Floor(), it would return “3”. This is because it always rounds down (to the “floor”) and never up (to the “ceiling” so to speak). However, if you were to just stop here with:
Math.floor(Math.random());

your result would always be 0. Seems like a lot of work to go through to get a zero, no? That is why Math.random() is usually multiplied by another integer and then run through Math.floor like so:
Math.floor(Math.random() * 50)

This will generate a random whole number between 0 and 49.
In my code, however, this value is multiplied again (in my case by 10) to create a larger and more random number. While the size of my canvas is 600 x 600, I chose 50 and 10 to limit the values between 0 and 499. I’m not quite sure if this was the right thing to do but I wanted to minimize the chances of the apple reappearing in the CSS border of my canvas, that would be terribly unfair for “snaky”.
A quick test in the browser revealed that the apple would, indeed appear at a random position on the screen after the “head” of my “snake” crossed over the same location as the “apple”. Yay! But it wasn’t growing and the score was not increasing when it did so. Another function, you ask? No, sir. What we need here is more functionality in our function. Yes, a more functional function, if you will.
After much hooing and haaing and questioning my intelligence and general worth as a human being I came up with, along with some much needed insights and suggestions from my teacher, this:
var snakeTail = snake[snake.length - 1];

snake.push({
     x: snakeTail.x,
     y: snakeTail.y
     });
     score++;

Here a local variable called “snakeTail” is declared within the function (just below the Math.floor stuff) and defined as “snake[snake.length – 1];”. That is, equal to the length of the snake minus one element (the head? I question this as I am, as of the date of writing this, not quite sure why it works. Honest much? Yup.).
This variable is then called in the push(); method (a method that adds one element to an array each time it is called), which is accessing the snake array (snake.push), and has the x and y values of the new element defined as equal to that of snakeTail so that the new element will appear at the end of the snake’s “tail” as part of that array and not break off, disappear or do something otherwise bizarre and frustrating.
At the bottom,
score++;
simply says to increase the value of the score variable by one. This is the final result of my eatApple() function:
function eatApple() {
     if (snake[0].x == appleLocation.x && snake[0].y == appleLocation.y) {
     appleLocation.x = Math.floor(Math.random() * 50) * 10;
            appleLocation.y = Math.floor(Math.random() * 50) * 10;

            var snakeTail = snake[snake.length - 1];
     snake.push({
     x: snakeTail.x,
     y: snakeTail.y
     });
     score++;
     }
    }

6. Getting it to turn and follow the head

This was by far the most difficult part of the project. And, if it weren’t for the guidance and support of my teacher, I very likely would’ve given up or, at the very least, lost most of my hair in figuring out how to do it. I’m not joking about that at all, Wow, was this part tricky.

To begin with, I started with building in a “keydown” event listener that looked like this:

document.addEventListener(“keydown”, keyDownHandler);
document.addEventListener("keydown", keyDownHandler);
This will establish a link between the document and a “key down” event ( a key on the keyboard being pressed) so that the game will “know” when the keys are being pressed (keydown). The exact dynamics of what happens when a key is pressed are defined in the function keyDownHandler (which is called as an argument in document.addEventListener(“keydown”, keyDownHandler);. This is what the function looks like:
function keyDownHandler(e) {
     if (e.key == "Right" || e.key == "ArrowRight") {
     snakeDirection = DIRECTION.EAST;
     } else if (e.key == "Left" || e.key == "ArrowLeft") {
     snakeDirection = DIRECTION.WEST;
     } else if (e.key == "Up" || e.key == "ArrowUp") {
     snakeDirection = DIRECTION.NORTH;
     } else if (e.key == "Down" || e.key == "ArrowDown") {
     snakeDirection = DIRECTION.SOUTH;
     }
}

Here, a relationship is established between keys on the keyboard and directions on the canvas. It is essentially a series of if and else statements equating arrow keys on the keyboard with cardinal directions on the canvas. Left equals “West”, Right equals “East”, Up equals “North” and Down equals “South”. “e” is called as an argument to connect back to the the event listener. However, there is, as of yet no exact correlation between the “directions” in the code and any change in the current direction on the canvas. There is only a correspondence between a variable (snake direction), a constant (DIRECTION) and the respective keys on the keyboard associated with each “direction”. The functionality is determined in a separate function, moveSnake();, shown below (relevant code shown in red):

function moveSnake() {
     //create copy of snake
     var snakeCopy = [];
     //loop through snake
     for (var i = 0; i < snake.length; i++) {
     //for each iteration, add snake body to snake copy
     snakeCopy.push({
     x: snake[i].x,
     y: snake[i].y
     });
     }
     for (var i = 0; i < snake.length; i++) {
     if (i === 0) {
     if (snakeDirection === DIRECTION.EAST) {
     snake[i].x += dx;
     }
     if (snakeDirection === DIRECTION.WEST) {
     snake[i].x -= dx;
     }
     if (snakeDirection === DIRECTION.NORTH) {
     snake[i].y -= dy;
     }
     if (snakeDirection === DIRECTION.SOUTH) {
     snake[i].y += dy;
     }
     } else {
     snake[i].x = snakeCopy[i - 1].x;
     snake[i].y = snakeCopy[i - 1].y;
     }
     }
    }
The for loop at the top of the relevant code establishes a loop through the entire snake array. However, we can see in the first if statement the following:
if (i === 0)
This serves to isolate the following logic to apply to the index position 0 in the array (the snake’s “head”) and that element only. The body of this if statement contains the equivalencies for the DIRECTION constants and actual changes in the snake’s head’s direction of travel on the canvas.
Here, I have equated snake[i].x (motion along the horizontal axis) with var dx = 10 and snake[i].y (motion along the vertical axis) with var dy = 10. So, essentially, dx equals a movement of 10 pixels per interval to the right (EAST) and -dx (the opposite of dx) equals a movement of 10 pixels to the left (WEST). Correspondingly, dy and -dy equal a movement of the same increment down (SOUTH) and up (NORTH), respectively.
At this point, I felt pretty good about how things were coming along and was excited to test the functionality. To my chagrin, it well kind of worked. That is, instead of the direction changing as it would in a snake (the body following the head), the entire array shifted at once. It looked a lot like a little green UFO. Fixing this, would prove the single most difficult piece of functionality I would have to build in the entire span of the project. And it would take days and the help of my teacher to figure out.
To be honest, I am still not entirely sure why or how this code works but here is my hypothesis. Within the function moveSnake();, the variable snakeCopy:
var snakeCopy = [ ];
(an empty array) serves as a means to more or less attach a copy of the snake to the movement of the head (I had noticed beforehand that the head would detach from the snake and follow the arrow key functionality by itself leaving the rest of the array stranded, as it were, and motionless on the canvas).
Next, a for loop is called to loop through the length of the snake:
for (var i = 0; i < snake.length; i++)
The body of the loop contains the following code:
{  //for each iteration, add snake body to snake copy
     snakeCopy.push({
     x: snake[i].x,
     y: snake[i].y
     });
Here, the .push(); method is called. This method, according to w3schools.com, “adds new items to the end of an array, and returns the new length”. In this case, however, the argument being called in the method is an object (running off the for loop written above) equal to the length of the snake:
{ x: snake[i].x,
  y: snake[i].y }
So far, this all made sense to me. However, the question remained as to why the entire length of the snake didn’t return at each iteration (interval of the browser refreshing every 1/10 of a second)? So far, the only reason I can think of is that their must be a link here between the setInterval value and the snakeCopy printing out in individual segments behind the head as designated by the push(); method. Perhaps things will become clearer with more experience. I would surmise also that the body of the else statement at the bottom of the function moveSnake(); also plays a part. It looks like this:
snake[i].x = snakeCopy[i - 1].x;
snake[i].y = snakeCopy[i - 1].y;
Here we can see, outside of the movement parameters designated to snake[0] (the “head” of the snake), the snake is equal to a copy of itself minus one index value. At the moment, I believe this allows for the snakeCopy to follow the head without adding an extra length to the array on the canvas.

7. Encoding collision functionality

I had some familiarity with how to approach this based on the tutorials I’d been provided. I needed to build something that would stop the game if A) the snake collided with any of the four walls or B) with itself. To do this, I created two separate functions, 1) collision(); and 2) snakeBodyCollision();. Originally, I took a shortcut by relying on an alert call in the browser that would drop down if any of the logic for the collision was met. My instructor advised against this and said, instead, to have the “GAME OVER” functionality appear on the canvas. This naturally led to a more challenging time but was helpful in the end.

Here is what I wrote:

function collision() {
     var headX = snake[0].x;
     var headY = snake[0].y;
     if (headX >= myCanvas.width || headY >= myCanvas.height || headY <= myCanvas.height - 610 || headX <= myCanvas.width - 610) {
            ctx.fillText("GAME OVER. You hit the wall. Poor snaky.", 120, 300);
            stopGame(gameInterval);//stop the game
            gameOver = true;
     } else {
     snakeBodyCollision();
     }
    }
AND:
   function snakeBodyCollision() {
     for (var i = 1; i < snake.length; i++)
     if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
     ctx.fillText("Oh, boy. You just bit yourself. GAME OVER.", 120, 300);
     stopGame(gameInterval);//stop the game
            gameOver = true;
     }
    }
   }

In the first function, collision();, I declared two variables to represent the x and y coordinates, respectively, of the “head” of the “snake” in order to isolate the first element in the array and limit any further logic to it alone (I’d struggled considerably with this in building the snake like motion of the array in the first place).:

var headX=snake[0].x;
var headY = snake[0].y;
Further, I also thought creating these variables would make building the logic a lot easier and less prone to throwing an error (always good). Next I wrote the following if statement:
if (headX >= myCanvas.width || headY >= myCanvas.height || headY <= myCanvas.height - 610 || headX <= myCanvas.width - 610)
Here you can see that if any of the four conditions are met ( headX or headY touches any of the four walls) the parameter for the if statement will be met and the following code will fire:
ctx.fillText("GAME OVER. You hit the wall. Poor snaky.", 120, 300);
            stopGame(gameInterval);//stop the game
            gameOver = true;
First, the text “GAME OVER. You hit the wall. Poor snaky.” will display at 120 pixels from the left border and 300 pixels down from the top border. Next the function stopGame(); defined as
function stopGame(interval) {
        clearInterval(gameInterval);
    }
would fire. Within this function the clearInterval() function would fire against the argument “gameInterval” a variable declared as:
gameInterval = setInterval(Draw, 100);
which has as its argument the main function through which all other functions for the games functionality are concerned as well as the interval of 100 milliseconds (the interval at which the “movement” of the “snake” is refreshed).
Next, the variable “gameOver” is set to “true” as a means of linking it to the the function handleMouseClick(); where the game can be restarted. Finally, after the if statement there is an else statement which calls the second function, snakeBodyCollision:
function snakeBodyCollision() {
     for (var i = 1; i < snake.length; i++)
     if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
        ctx.fillText("Oh, boy. You just bit yourself. GAME OVER.", 120, 300);
        stopGame(gameInterval);//stop the game
        gameOver = true;
     }
    }
In this function a for loop was necessary as the criteria for collision had to apply to the entire body of the snake in a more dynamic way than that between the snake’s head and the walls of the canvas. The walls, after all, never move and have static coordinates while the snake is in constant motion when the game is in play. So, what the for loop does in this function is essentially turn the entire body of the snake into a single responsive variable which the following if statement can act on. It looks like this:
if (snake[0].x == snake[i].x && snake[0].y == snake[i].y)
And basically says ” if either the x or y coordinates of snake[0] (the “head” of the “snake”) are equal to snake[i] (the body (and head) of the snake), execute the parameter of the if statement. And that basically follows the same logic as the function collision(); only the text now says “Oh, boy. You just bit yourself. GAME OVER.” instead of “GAME OVER. You hit the wall. Poor snaky.”
I thought it a good idea to call snakeBodyCollision(); within collision(); as it seemed to follow the principles of brevity and simplicity I’ve read so much about in keeping your code clean.

8. Refactoring

By this point, I had spent about 12 days building my Snake Game (after a week of working through tutorials). I probably could have done it faster but, you know, things like family, work and sleep do have a way of taking us away from our computers. Anyway, I couldn’t believe how much I’d learned in this short time or how challenging it had been. With what I’d done I felt it must be ready to go. After all, all of the “deliverables” for the app had been met, so why go against the age old saying “if it ain’t broke, don’t fix it”?

And this is where my instructor proceeded to unload a bedazzling amount of refactoring on my project. Refactoring, I would come to learn, is basically the equivalent of taking something you’ve already said and then saying it better and with fewer words. It’s the equivalent of editing for brevity in writing but no functionality is lost in the app. Really kind of amazing and something that points to just how flexible programming languages really are.

I won’t go too much into the details of how refactoring affected my code but I will share the following. Essentially, my teacher had me add my snake array object, snakeDirection, appleLocation, score variables and setInterval function into a new function called “startGame();”.

function startGame() {
	snake = [{
			x: 150,
			y: 150
		},
		{
			x: 140,
			y: 150
		},
		{
			x: 130,
			y: 150
		},
		{
			x: 120,
			y: 150
		},
		{
			x: 110,
			y: 150
		},
		{
			x: 100,
			y: 150
		},
		{
			x: 90,
			y: 150
		},
		{
			x: 80,
			y: 150
		},
		{
			x: 70,
			y: 60
		},
		{
			x: 50,
			y: 150
		}
	];

	snakeDirection = DIRECTION.EAST;
	appleLocation = {
		x: 250,
		y: 150
	};
	score = 0;

	gameInterval = setInterval(draw, 100);
}

This new function was then called at the very bottom of the file. I have read this can increase the efficiency of load times and interactivity as it allows time for the entire file to be read before executing crucial functions.

9. What I Learned Toward Increasing My Coding Gong Fu

As with improving at anything, coding, so I am learning, is a matter of revision, review and practice. It also helps to know how it actually works and why. That is a large part of why I wrote this post. Not just to show you, dear reader, that I understand it but also that I understand it. Unless you are lucky enough to have an audience willing to hear your ideas, there is really no better way to reinforce your understanding than by writing it down. That said, having written it all down, here are a few of the points I picked up in getting through this project:

Pseudo-coding your project can be amazingly helpful: there is a vast difference between two human individuals communicating and an application and the browser. In the former, much can be implied and each other’s understandings can morph and change based on the addition of new information and other, more intangible factors. This is not so with coding. Coding is utterly literal and computers simply do not have the ability to improvise or, in any way whatsoever, “get what you mean”. Having your application sketched out in its entirety before you start coding it can actually save you a lot of time, to say nothing of confusion and frustration, in the end. Pseudo-code is your friend.

Simplicity is beautiful and very difficult: the answer is often far simpler than we realize. The trick is to understand the situation exactly and to understand the solution exactly. Software languages do not allow for the same expression as human languages because they deal in discrete values, not abstract meaning. The more you can understand this, the easier and concise your code will be. I found that it’s often more about a minute detail in the logic than it is the structure of your app as a whole that is causing the trouble. Of course, a simple structure is helpful, too.

Ask for help when you need it: my teacher has been amazing. But, this being a remote course, I am more or less alone in my moments of struggle. When I’m really stuck, I admit it and make a video outlining my situation, what I want to change and what I’ve tried so far. I then push all my code to GitHub and send the repository link and video to my instructor. Document your situation, try things out, problem solve and then ask somebody better than you what to do. Simple.

Google is your friend but not all resources were created equal (or written very well): One thing I really started to cultivate during this project was a deep appreciation for documentation written by people who can write well. I was amazed at how rare this actually is. A lot of stuff out there assumes a level of knowledge and experience that is way beyond the level of Junior Developers. Other resources are half-baked, outdated and sometimes even counterproductive to look through. I’ll never forget the tutorial I found on Medium for a JavaScript Snake Game the code for which didn’t work at all. My point is, you need to be careful or very experienced before you can piece something together based on Stack Overflow comments and Medium Articles. Focus on the basics and ask people you know you can trust for resources and documentation that will be useful.

Learning how to use a software language is roughly on par with learning how to use a human language: I say this because I speak Japanese at a business level. It’s a long story but I’ve been living in Japan since December of 2007 and have been studying the language, at varying degrees of intensity, fairly continuously the whole time. Coding has a lot of similarities but seems to require the same level of effort, discipline and time commitment to make yourself useful and, hopefully, employable.

Coding is an amazingly creative and fun but challenging undertaking: I’ve mentioned before that shortly after starting to learn to code my first thought was that I wished I’d started earlier. This is because it incorporates a really fun blend of creativity, logic and applicability in daily life that would be hard to match any other way. This last point makes me happy because it’s often the underlying passion along with the discipline to keep going that helps us grow and eventually reach our goals in life. And my goal of becoming a Software Developer is definitely one, I am finding, that is going to take passion to achieve.

That’s it for this post. At the time of this writing, I am in the last stages of building an app using React and NodeJs to connect to the Twitter Standard Search API. It’s a real doozy in terms of learning curve and challenge. If it weren’t for the expert guidance and feedback of my teacher, I dare say things would be a lot harder. In my next post, I’ll be going over what it was like to get through it, how it works and what I learned from it.

See code for Snake Game on GitHub here.

Play it for yourself on CodePen here.

[/et_pb_text][/et_pb_column][/et_pb_row][/et_pb_section]

Comments

No comments yet. Why don’t you start the discussion?

    Leave a Reply

    Your email address will not be published. Required fields are marked *