Text
Snake Game with JavaScript
Blog Post 2 – INTP-362
INTRO
Hello! If you came here after reading my first blog post (not necessary but it would be funny if u wanted to see my struggle) welcome back! It’s nice to see you again! If you diDN’T read the last blog post (the disloyalty smh /lh) hello! Nice to make your acquaintance!
If you aren’t aware what I’m doing here (tbh same life is definitely,,, A Thing™ for sure), I essentially ventured out to learn about game development in JavaScript (a coding language, often paired with HTML and CSS if you weren’t aware which is completely fair). I have previously had experience with JS in terms of website development but never really for game development. For the sake of this post and the catered audience, I’m just gonna assume that you know JS and HTML and CSS and all that jazz. If you don’t, my sincerest apologies (/s,,, kinda).
(The title of the game and display of the current score would be what is controlled by html and css while everything in the black box would be controlled in js)
MAKING DECISIONS
So, first thing I had to figure out which IDE to use. Now this wasn’t too hard of a choice, as I already have multiple different IDEs with options for JS, html, and css (by multiple I mean 2, the accursed netbeans and the modern and sleek vscode). For this project, due to its simplicity and familiarity, I chose vscode (I was gonna give a whole outline as to what vscode is but I’m not getting paid to do that so no thank you).
After getting my IDE decided and figured out, I had to find out what game I wanted to create. Of course, as I am overly ambitious (which I must admit is one of my fatal flaws) My initial idea was “hey, why don’t I make a short, simplified version of pokemon or a fighter game like mortal kombat or smash?” y’know, like a fool. While these goals may have been achievable if I had multiple months to do this and no sense of procrastination, it simply wasn’t possible to pull off unless I wanted to neglect my studies and focus solely on the game.
After hitting that miserable realization, I made up a list of games that I could make in the amount of time given and the amount of motivation I had inside of me (which,,, is not a lot actually). My list eventually came down to these games:
Snake
Pong
That one offline dino game on google
Tetris
and Flappy Bird
Now all these games were doable, however, when it came to applying the things that I already knew, I would have to choose snake. As I had learned previously (not in the last blog post tho) how to control the movement of a shape based from keyboard input and object collision and everything of the sort, snake seemed like the easiest option to me.
HTML
After creating the project, I immediately created all the files and game them appropriate names (tho they deffo could’ve been better but eH ‘twas a lapse in judgment). First thing after creating all the files was to set up the html page.
Just like any html page, I included the basic tags. The DOCTYPE, meta tags, title, a link to the css page and a script to the js page, a header with the extremely (/s) original title and a body with a div to show the current score and a canvas to allow me to draw in (canvas being the only new thing that has anything to actually do with my game).
CSS
Now I won’t bore you with the css details as most of it iS just setting the font, font colour, centering elements, placing elements side by side, and all that jazz hOWEVER, one thing that ig is really cool even though it’s not my original code bc in no way, shape, or form am I this cRACKED at css, would be the title.
(It’s the text colour animation effect on https://alvarotrigo.com/blog/css-text-animations/ )
DISPLAY WINDOW
Now here’s where it gets into the fun bit. The first steps to actually be able to do anything would be create the display and context. (Just for a little bit of unnecessary context, the code being presented is not in order of the actual project it’s just been copied and pasted to show you what I want you to see like those illusionists or something)
First thing we must do is create a grid in our minds. In this imaginary grid, each square is 25 pixels by 25 pixels, which has been assigned to the blockSize. Next we choose the dimensions of the display, I chose 20 blocks x 20 blocks. Then, as I had been taught in the past, we create the variables that are meant to hold the display information which is the width and height of the window and the context of the page just so that we can manipulate the window.
In the update function (the function that reruns every time the setInterval tells it to. This is the thing that I talked about last blog post that allowed for either a higher or lower fps.) we set the background colour as black using fillStyle and we draw the rectangle (square??? a square is a rectangle right?? geometry was rough) using fillRect. The first 2 values are the x and y of the top left corner of the display while the next 2 values are to set the actual size of the window.
Now, you may be like “hey, my guy, respectfully, you talked about display and setting the height and width and context and setInterval and actually drawing the window, but what about all the stuff in the middle? The change direction and foodRando and everything?” and to you, loyal reader, I say hush. It will all be revealed in good time impatient child.
DRAWING THE SNAKE
Next, we draw the snake.
Now just like the display, we get the X and Y of the snake head (obv not hardcoded bc we dO want it to move unlike irl). Next thing we add into the update function (don’t let the screenshot fool you this iS still the same update function as the last one). We also get the colour for the snake (I went fancy for this one and decided to do a hex code instead of just like,,, ‘green’ even though both would’ve produced similar results) and update the x and y of the snake based off of some things that will be talked about later on. We then continue to use fillRect again to draw the head of the snake.
Now the next bit is a bit more complicated then everything else shown previously (but if u know coding then its genuinely not that bad lmAO it just looks a bit spooky). In the for loop, we essentially create the variable i (you’ll see this bad boy a lot) and cycle through all the entries in the snakeBody to draw the rest of the body of the snake that way the snake’s body isn’t a fixed size. And can be increased depending on the entries in snakeBody.
Next we have the for and if loop that’s placed before the snake display. The for loop is used when the snake is moving. Basically, every time the snake moves (and especially when the snake is turning) it allows the current section of the body to get the placement of the piece in front of it and replace it and moves down to the head which is placed using the if statement right after which is able to move (mostly) freely that way u can get those crisp 90 degree angles when your snake moves.
DRAWING THE FOOD
Finally, the last drawing piece, would be the food.
Just like all the parts before this, we start with initializing the variables that are to be used when finding the placement of the food. In the update function, we do the same thing we did as before, we set the colour using fillStyle and fillRect to place the food somewhere in the window.
Now finally, for the part that I told you guys to wait for, the meaning of foodRando. What foodRando does is that it finds a random place on the window using Math.floor to ensure that the number chosen is rounded down to a while number and Math.random to find that random place. The for loop is to ensure that the x and y coords of the piece of food isn’t inside the snake otherwise it reruns until it lands in an empty space. This is ran every time a piece of food is eaten and when the website first launches.
MOVING THE SNAKE
And now we talk about the other part of displayScreen that you were (or were not idk I can’t tell… or can I? No I can’t don’t worry you’re safe for now).
The next thing after being able to draw all these components to the window was to figure out how to actually move the snake. This is there the changeDirection comes into play. Inside displayScreen, we have an event listener which listens for when the user’s finger lifts off of an arrow on the keyboard, specified with ‘keyup’. Once that action takes place, the event listener runs changeDirection which takes in an event. in this event, we determine which key was pressed and move it according to the key that was pressed by changing vX and vY which is just the velocity. -1 in the Y variable means up while 1 means down. In the X variable, -1 is left and 1 means right. For both, 0 means just not moving.
But what is the && for? If you recall from all those years ago (it’s okay grandparent I get it ‘back in your day’ or whatever) the snake can’t go from going up from going down immediately, same with left and right. This is because, if the snake were able to do that, it would just eat itself (and break its spine which isn’t really the best but who am I to judge) and immediately end the game. The && is meant to prevent that from happening. It’s a check to basically say “if you wanna do this, first we gotta make sure you ain’t doing the forbidden move”.
SCORING AND GAME END
Lastly (if you’re still here, hOLAY I’m barely even still here lmAO how do you dO it what is the sECRET?), dealing with collisions that cause the game end and keeping and increasing score.
For this last stretch, we state the variables for keeping score and ending the game, score and gameEnd. If you recall from the very beginning in displayScreen and in the html, there was some part with score in it. document.getElementById(“score”) is taking the variable from the js file and displaying it in the html so the reader gets some sort of validation beyond their snake getting longer (firstly, haha innuendo don’t look too deep into it. secondly, talk ab parental problems or something lmAO just like me frfr).
Next in the update function, we have the first if condition. In this condition we’re just specifying that, if gameEnd, the variable used to tell if the user has lost or not, is true, we end the game and restart using history.go (that’s something new that I learned I am but a tiny child) the page to allow the user to play again. The next if we have is to recognize when the snake has become fed and increase it’s size (like chickens to the slaughter) and increase the score. Once we have done that, we rerun foodRando, generating another piece of food.
Finally, we enter the game end conditions. The first if statement is used to identify whether the head of the snake has hit the wall (like the tiktok sound or something idk). The for statement after that is recognize that if the head of the snake hits another part of the snake, that means it’s game over. For both, it recognizes game end by changing gameEnd to true and then sending an alert to the user (with a kinda mean message I’m sorry but not really) informing the player that they had lost the game.
CONCLUSION
In the end, this game was fun to make! I think if I were to go back and restart the game or add additional features, I would include things that I wanted to but was too overwhelmed to add like a menu where you can choose your display settings or maybe just a whole different project as this one seemed a bit simplistic and easy :P. While coding I realized just how similar this is to java or any coding language really. Truthfully, the only difference would be that of drawing the shapes and figuring out logic behind collisions and the syntax but everything else: the if and for statements, the functions, and logic behind everything is still the same. I think that was why I would’ve appreciated if I took on a harder game or task but, in the end, it was pretty fun to play with.
THE FINAL PRODUCT
Now since you’ve all stuck with me for so long, here’s your reward: a gif demo of the actual game being used :D (if you want access to the full project, I have my github linked :) pls don't judge my abysmal snake skills).
0 notes
Text
Game Development with JavaScript
Blog Post 1 - INTP-362
So recently, I started learning JavaScript focusing on the game development side of it instead of just the regular website functionality stuff.
I'm going off of the assumption that you are from my class who has learned JavaScript in terms of website development before (if you aren't then hello!), I'm also gonna assume that you already know how to code and the basics of JS.
So game development using JavaScript isn't anything new, having been used in many beloved games such as Bejeweled, Pac-Man, Tetris, Agar.io, and so on and as game development has always been something that I've always wanted to learn, I figured why don't I try to make my own? "But why JS?" you may ask. Well here's the true answer, as cool as it would be to learn game dev in C or C++, those are simply just languages I'd rather learn on my own time without the pressure of meeting certain deadlines or having due dates for deliverables for while learning whereas I already am familiar with JS and it'll be easier for me to produce product that way :P (as this entire thing is currently kinda just for school and one of my subjects).
I started my journey learning JS game dev on a site called SoloLearn (a website that's whole purpose is to allow people to learn and practice coding). For the first couple weeks, the lessons were purely just recap of things I had already known (html, css, basic web dev stuff) and given the limited amount of lives that would be taken away if you answered the quiz questions wrong (which was embarrassingly more often than I'd like to admit. Turns out the recap was definitely needed lmAO) I only recently actually started getting into the new content.
From my limited time actually getting into the game dev side of JS, there's definitely a lot more math to be done. So far in our courses, I've found that we haven't really needed to get deep inside complex math (I'm talking trig and things to do with radians and pi and vexes and shapes bc let's be honest, that stuff is harder than calc or algebra I wiSH I could be doing calc or algebra instead of using pi bro) but I've found that JS game dev heavily relies on these aspects. Now of course, you don't need to manually do every single calculation to figure out every shape (circles make themselves essentially if you know what you're doing) but looking at all these numbers and tryna remember which axis is the x and which is the y after 2 years of not touching that pains me. I had to relearn how to convert angles into radians I'm in pain. But other than circles, the math was still necessary, especially given the short quiz questions that were handed out to me in which they gave us the x and y dimensions of the canvas (which is where all the cool shapes and stuff shows up) and we had to do math to figure out where a shape was supposed to be placed if we wanted it in a certain space on the canvas like the centre. While you may be thinking "Hey OP, that's genuinely not too bad, you simply divide the canvas x and y in half!" yeah, sure for circles but for rectangles/squares, it's a tad more difficult (or a lot more difficult if you have monke brain like me). In order to place a rectangle in the middle of the canvas, not only must you find the middle of the canvas, you must also take the width of the rectangle divided in 2 and then subtract that from the width of the canvas divided by 2 and then do the same for the length of the rectangle and canvas. Now while that may not be too bad, you must remember that my brain has the memory of chimpanzees (who apparently have the worst memory? Just like me fr) and I simply cannot remember that many numbers while still processing future math problems because I simply currently don't have the ability to (my memory is being reserved specifically by random minecraft and science facts).
Now that I've finished malding over the pain of numbers, onto what's kinda the neater part of game dev: the animating. I cannot explain to you the pain I went through when testing out different things. Fortunately, SoloLearn provides examples that you can run on the website while learning but despite the example being directly in front of me, I still manage to make mistakes when adding features to practice my understanding. Take this code for example:
A nice loading bar-like animation! For the longest time, I sat there wondering as to why when changing the value to blue, a portion of the line would flash blue before reverting back to red then doing the same thing again. This, of course, was because when I redrew the line starting from the beginning, the code to actually set x to 0 and to redraw the line in another colour was in the last if loop, causing the line to just restart drawing in red when the function was called again. Now while the solution was simple, as most of you have probably encountered before, actually finding the problem is a much more difficult process. I cannot explain the many errors and hours (it was more like max 5 mins but it deffo felt like hours to me) that it took for me to finally understand exactly what the problem was. But alas, my stupidity doesn't end there! Take another snippet of code and output as example:
The way that I viewed this animation was like watching cars go by or maybe the windows of a train or something of the like truthfully as it is, it can be whatever your heart desires it to be. Regardless of how you might view it, though, nothing can deny my pain when trying to code this. So the steps when coding animation for a moving subject is as follows:
Clear the canvas
Draw the object(s) in their new position
Update positions based on logic
Repeat
Along with the rule that whenever you draw another shape, you must always context.beginPath(). Pretty simple, right? Well admittedly, yes it is fairly simple HOWEVER recall my previous mention of my monke brain you will also have to remember that I fail do simple procedural things. Now I hope you have realized where this is going. When trying to code the blue moving square, I came across a problem. Suddenly my red square had disappeared like my hopes and dreams. But how could all the (extremely simplistic like a kindergartner's drawing probably worse if I'm being honest) cars looks the same? Where's the diversity? After hours (again, minutes) of searching my code to figure out who had been the cause of this devastation (it's me) I had finally found the reason(s). The first problem was that I had added another context.clearRect(). Because of this problem, I had completely erased all red cars from showing themselves, leaving a hole gaping hole where they would've been found. Now once fixing that problem, everything should be fine right? Wrong. I had accidentally forgot to include context.beginPath() meaning that while now there were the proper amount of cars, there was still a lack in diversity. Failing to execute this code causes the former shape to inherit the same characteristics as the latter shape which caused all my cars to become blue (kinda like white wash-). Finally, once that code was added into the correct place, it finally looked like as it should.
1 note
·
View note