Write a Tetris game in JavaScript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Haha, Cool video Pomie.

But that youtube name seems awfully familiar :o.

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/fredstar1 ๐Ÿ“…๏ธŽ︎ Sep 09 2016 ๐Ÿ—ซ︎ replies

Oh, thats awesome. I appreciate the videos that you and mpj put out. Really helps beginners like me move to more intermediate / advanced topics.

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/fredstar1 ๐Ÿ“…๏ธŽ︎ Sep 09 2016 ๐Ÿ—ซ︎ replies

I've really enjoyed all of your videos so far.

The content is very well presented, and your personality makes it fun!

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/SkaterDad ๐Ÿ“…๏ธŽ︎ Sep 09 2016 ๐Ÿ—ซ︎ replies

I like your style and I loved playing Tetris. And I've subscribed. Thank you!!!

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/Cyclokitty ๐Ÿ“…๏ธŽ︎ Sep 09 2016 ๐Ÿ—ซ︎ replies

just subscribed. good stuff!

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/pacificano_au ๐Ÿ“…๏ธŽ︎ Sep 09 2016 ๐Ÿ—ซ︎ replies

So I've been developing some chrome extensions for different personal tasks and I made some online JS courses.

Is the stuff like "matrix" basic JS stuff that I should know or is it specific for some uses? Never heard of it.

Subscribed!

๐Ÿ‘๏ธŽ︎ 1 ๐Ÿ‘ค๏ธŽ︎ u/MrInka ๐Ÿ“…๏ธŽ︎ Sep 11 2016 ๐Ÿ—ซ︎ replies
Captions
hello welcome to math math method today we're going to do something extraordinary gonna write that tetris game and I'm gonna have to prepare 5th night so I give me a minute so this is an honor episode 2 mpj he loves function programming so today with all his coffee the feed gap we're gonna move through we're going to make a Tetris with functional programming and yes I need some more water where rectangle trapezoid textured oh oh Jesus ok these old commercials are really blowing me away here well Tetris is one of those games where you have to be born yesterday in order to not have played it but in case you're watching this in the future I'm gonna give it a run down so you have pieces of different configurations all of them before blocks in them and you put them on the ground they disappear when one line is filled let's your start we start with an index dot HTML that is almost empty we assess this Tetris title it has a canvas with ID Tetris it has a width of 240 and height of 400 then we reference Tetris to j/s in a script tag and Tetris to j s we have here the first thing going to do is access the canvas so we say Const canvas equals document dot get element by ID and I think it was Tetris to Chris and we need to get the context out because you can't draw on the Dom element so we say Const context equals canvas get context context 2d and just to make sure this works we gonna paint the context so first is a con text field style equals 0 0 0 here hex code for black and then we say context dot fill rect 0 0 top left and then the full width and height of the canvas canvas docked width and countless dot height I go back to the browser to check and we draw it so this is where we're gonna or tetris game is going to happen now we're going to have a data structure for pieces here so first I want to look up what the Tetris pieces like Tetris pieces and we're going to look at this one we can see the seven of them and I'm going to start with the T here you are not represent this in a two-dimensional matrix so I'm going to say Const many tricks equals array and then we have an array of arrays and then I'm going to fill up here with the with the boxes so I think this had first 0 no 1 1 1 now at 0 1 1 0 and top here 0 0 0 so here we have reputation of the T piece the reason I have an extra row here is because when you rotate it it's much easier to determine the center of the piece if we only had 2 rows like this the rotation would be a little bit weird it wouldn't rotate around the center it will just flip up and down and now I want to draw this first piece so we say matrix so for each and here we're going to get the row and the y index then we iterate over the row and here we're going to get out the value and X index in all jet risk game values of C row is going to be nothing basically transparent or whatever we call it so the first thing I'm going to do here is check that the value is not 0 if value is not 0 and then we draw because if it is 0 we'll skip it so we say here context dot feel style and I'm just gonna simply draw a red to begin with and then context I'll feel rekt and here we can simply say X index for left y for top I'm going to draw it one and one in set width and height here so we're going to get a tiny piece in the upper left corner I think oh no need to close this the loops whoo okay I think we have a tiny little bit there we're gonna zoom in to make sure we do yeah that's our tiny little piece here so let's make this bigger and we can utilize a thing built into the canvas that is the context scale so right after we got context out they must going to say context go to scale and I want to scale everything 20 times so let's make sure we can see something now yeah that's much better so that's the first piece now I want to wrap this matrix drawer in a function let me say function draw matrix and we take the matrix here and we are in dentist make it functionable and then here let's make sure this works we call the draw matrix function with our matrix so this is just a little bit of cleaner let's make sure it works okay good in this draw matrix function I want support an offset then we'll add offset here and then I'm going to use the offset for the top and left here so an X plus offsets dot x and then the same for y plus offsets dot Y and this means that I will able to move the piece later so let's just start an offset of five above Y and X here there we go so now I want to add a little bit of a player structure here we're going to say cones two player equals and it has acquisition which is going to be this value here and then it's going to have a matrix which is this value here and now we can call draw matrix with the play values instead play your load matrix and layer dog position good it works the same as expected so up here I won't add a general draw function I'm going to say function draw and it's simply gonna do the draw mix of the player not right now pick up it is up here and then we only call draw and this draw function we're going to use in our update function because now I want to draw the game continuously and we can do that with requestanimationframe so I'm going to create an update function here function update and the first thing it does is it calls draw and then it calls weakest animation frame and supplies itself to there and we initialize the game here by saying update so now we're going to continuously draw and effect that has is that if we move to play your position it's going to draw it again but obviously now we're not clearing it so this looks a bit weird so in our draw method we're gonna start by clearing the canvas them is gonna copy that first rows up here let make sure this worked so I draw it again there so now it moved instead which is must which is what we want and now we want to be able to have the piece drop and we can do that too with weakest animation frame here we will get the time from weakest animation frame I'm going to default this time to zero because when we call adopted initially we're not calling it WA nan and to show how this looks I'm going to log this time here you can see that we get the time in milliseconds that increments that is basically the total time since the page was loaded in order to be able to calculate some time-dependent things I want to get the difference in time in order to get that we need to save the last time we saw so I'm going to create a new variable here let last time and it's going to start at 0 and in here I'm going to create Const Delta time and it's going to be time - last time and when we have Delta time we need to update last time time so let's log Delta time here instead to see what that looks like now base we get a time dafair an incremental time and that is the better for our purpose so now I want to add two more variables here one that we call the drop the drop counter and it's going to be zero and one that I call the drop interval and that's going to be a thousand so this number thousand here is milliseconds so every one second we want to drop the piece one step so instead of logging this here we can say drop counter plus equals Delta time and if drop counter is more than drop interval then we say Laird of precision dot y plus plus and then we reset the drop counter to see a row so it starts counting from the beginning if I did my calculations correct now I share a piece that drops every second that's here tip tip tip tip okay this is good the next thing I want to add is some keyboard controls I'm going to put that down here now I'm simply going to say document dot add a belt listener key down and then we get the event out here and we can look at the land the advent the event so this piece of code is triggered every time I push the keyboard so if I press left here I get a keyboard event and in the key event I have a bunch of data most interesting is the key code with 37 this is the nicest way to know what key I pressed I think I also see that we have ever left here and key and stuff like that but I'm not as experienced with them so I'm going to use the key codes instead so that means we can say in here if event dot key code equals 37 we are saved player dot position of X minus minus mu player to the left and we check that the works yeah that works so let's do the same for the right and in order to help us with the key codes I'm going to open a little help wrap here it is called key code and all it does is show you the number of the key you type I'm going to strike right here I get the number 39 whoops and I copy this point and I paste it in the code so else if event does key code equals 39 we move the player to your rights let's try this out we can move the left and we can move to the right great stuff and now I want to add support for down key and down presuppose a dropped piece one step so let's find the number four down press it down and as E is 40 back to the code and we can say else if event.keycode equals 40 and I simply say player dove position again but y plus plus and in then I want to reset the drop counter to zero because if pressed down we don't want another growth to happen it means after we want that extra delay of a second let's make sure we got what we wanted the drop and a manual drop you can see that it goes back to the interval and even if I do this there's always one second delay until the next automatic drop but now we drop at two places so I want to consolidate this I'm going to create a new function that is called player drop I'm going to implement it up here function layer drop and it does the same thing we can copy that in here and then instead of doing this here we can simply call player drop here in the code so we should have the same behavior now but consolidate the one function okay automatic drop works and manual drop works good now I'm going to add the matrix where we save all the stock pieces so in order to facilitate this I'm going to create a function up here that I call create matrix function create matrix and it's going to take a width and a height property and in here we simply say equals two matrix empty array and then we can loop pair so while we have height value say while H is not zero we decrease H with one and then we do matrix so push a new array of length width and we fill it with zeros then return the matrix down here so now down here by the player I'm gonna say Const arena equals create matrix and it's supposed to be 12 by 20 20 units high and 12 numbers wide let's see what this looks like you can log it out with console dot log Reena and we can all say console dock table arena so here we have the log is an array of a race and all of them contain zeros shouldn't be a surprise but quite nice and the console table shows and Ray in a table like this so here's all our zeros and this is basically where pieces end up when they get stuck and now we can delete this again here instead I want to add a merge function so we say function merge arena and player this function is going to copy all the values from the player into arena at correct position so we say player dot matrix dot for each and we get the rope and the y index out we scroll down a little bit and then we want to iterate over row so we say Rho dot for each and here we will get the value again and X index ah once again values that are zero or ignored so we say if value is not zero then we do what we want and we want to copy the value into arena at correct offset say arena y plus player dot position dot y and X plus layer of position X equals value we close it here so I'm going to show you what merge does so we can go out here click this and now for run merge arena and player boom and then a console dot table arena which you see a tee here yeah so it copied the ones from or peace in Arina table here and now we want to have a collision detection function and we can implement the top here in alphabetical order so we simply say function call lives or we call us collide arena and a player first I'm gonna break out the player matrix in the player position so I say Const then I use this tuple assignor and then oh and it should take the player dot matrix and the player dot precision down down here I'm going to make a for loop for left let y equal 0 Y is less the matrix of length you say plus plus y then we make an inner loop here that loops over X left x equals 0 while X now well X is less than M of index y la dot length then we say plus plus X so now we are basically iterating over the player here the first thing is check on the player is if the matrix of the players Y row and X column is not 0 and we need to check if the arena is not 0 so we say arena y plus offset dot Y so let's make sure that the arena row exists and when we know it exists we can access its child there is a X plus offset dot X this shouldn't also not be 0 and I think we should wrap this in a another parenthesis here to make sure we get what we want so if the spot for Drew we know that we collide so we're going to say return true here and if no collision was detected here we return false in the end we check the player matrix on index y & x and if it's not 0 we continue and then we check if the arena has a row down here and has a column and if it's not if it has both of them and are not 0 then we turn true so in case it doesn't in case the row doesn't exist it means that we also collide so if we don't even have the row here that counts its collision as well so now I want to use the merge and collide function in the player drop so I go down here and if we drop and we collide that means that we are touching the ground or another piece so we test collide with Arena and player and if we do we need to move the player back up laird of position dot y - - and then we merge the arena and the player and we set the player back to the top with a player of position dot y equals 0 when the piece hits the bottom if you start from the beginning again so let's see here we go down here boom new piece here and there you saw that it if collision detected earlier so actually now we should have some T's there in the arena table you can see here is a here's the T and there's a T and there's a T but we can see them because we don't draw the arena currently but that's simple enough to fix so in the draw method we can seem to say draw matrix and we got arena here and we draw it from X 0 and y 0 see what we got so let's try this here boom boom bam boom looks good this is very Tetris like so far see what else we can do can we can we get in here oh nice but one problem is that you can go out here it's not supposed to happen your piece should be stopped before it reaches them we can do this in down here I'm actually going to consolidate this to a player move function so I'm going to say player move here I'm going to supply it with the direction I'm going to say - one copy this out and we do the same thing with the right player move plus one remove this then we implement player move up here function player move and we take a direction so instead here we simply say player dot position the X plus direction and if we have moved and we collide in the arena then we can simply move back so we can ask all player the position 2x with - direction - equals direction and this nice a plus equals direction now we should not be able to exit arena here and we can't exit to the left I can't exit your rights and it should also take into consideration other pieces because we have a very stupid collide function is simply checks if we collide or not and inhibit it I think is quite quite stupid but also quite elegant so what we missing now is rotation to rotate the matrix we need to do two steps first we transpose it which means convert all rows into columns after that we can simply reverse each row to get a rotated matrix let's create the rotation down here function rotate and it takes the matrix in the direction so first we need to say for left y equals zero and then while Y is less than matrix of length plus plus y and then the inner loop for left x equals zero while X is less than y plus plus X and then we're going to do a tuple switch here so let me demonstrate it here imagine you have two variables one a that equals a a a like this then let B equals B BBB and if you want to switch places of those two variables then normally we we have to say for 10 equals a then we'll say a equals B and then we will say B equals 10 so if the log console dot log a and B they have opposite values but we can do this a little bit simpler we can say a B equals B a and now let's switch them back so we get rid of the time value so I'm going to use this technique with the matrix here so we can write matrix X Y and matrix Y and x equals whoops that's not the correct bracket equals matrix and y and x and x and y I assume here see how we have a nice tuple switch and then we want to check the direction so if Direction is positive we do matrix for each whoops for each row and row dot reverse and else we also reverse the matrix so that's rotating our matrix and now we won't implement a play rotate we can do it here function player rotate and it don't take that direction and here we simply call rotate layer dot matrix and direction down down in our keyboard handler we want to bind this to Q and W let's check with keys they are equal Q 81 and W 87 so I guess we say down here else if event dot key code equals 81 you want to play a rotate minus 1 and otherwise if what's at 87 let's double check yeah it was then we want to rotate the other direction let's see if this works for us we should now have a rotating piece yeah it looks good but we have one huge flaw here and at least we can rotate inside the wall and that's not really good is it so we're going to fix that up to our player rotate function here and after we rotate we want to check collision again but we can't just check it once because we don't know what direction we need to move so I'm going to check lesion in a wire loop air so while collide re Reena and matrix then we want to do something and the thing we want to do is move the piece left and right basic to see if we had cleared obstacle the magnet is that were at the wall here and we rotate then we can check move it to the left and check you lied again in this case it will be but if it wasn't and imagine we had a wall here and we did like this then we will try to move like that and that would cause a collisions we want to move two steps to the left and then we'll continue like like this basically this one to the left those two to the right test three to the left tests for four to the right and do that until we have cleared obstacle so I'm going to initialize and offset variable up here left offsets and it's gonna start off at one then if we collide we gonna move the player by offsets player position dot X plus equals offset but if we still collide we need to have an order of that next time so now this starts out by moving to the right so next I want to move to the left so down here I'm going to say offset equals minus offset plus offset more than zero then we return 1 otherwise minus 1 so I think this algorithm would have something that goes up by one and negates it let's double check this in a browser just for fun so far offset equals 1 and then we have a does what if offset more than zero here so minus 2 3 - 4 5 ok it checks out let's go need to fix this thing here and of course we can't do this forever so we need to bail in case it didn't work so down here we can say if offset is more than player dot matrix the first rows length if it is that means that we basically okay we move so much that it does make sense anymore so we're going to rotate back player to me tricks - direction and we're going to return but we also need to reset the offset so I fear I'm gonna save the position and say player dot fish dot X here and then we just write it back and play this there we go so let's have a go see what it does so I'm moving to the wall okay already something destroy it a little bit let's fix that and player that matrix what's wrong here oh this takes a player here let's have a go again here now you can rotate out bugs and it jumps nicely out of the wall and we get into it so that's good now it's pretty tetris-like but a little bit boring because all pieces are the same so I think it's time to create more pieces so create a new function up here and we're gonna say function create piece and we take a type argument here and I'm going to use the same piece that we see here and I'm going to use the same labels oh is C L J and T so I guess we asked get started with this if type equals T and I guess we can copy the matrix from up here whoop remove this and return here let's try this for starters so basically what we want to do is down here is instead of say create piece T let's make sure we didn't break anything okay checks out so now we can add more pieces here what else do we have we have else if type equals oh just a big box copy this and the box is simply one one in doesn't this really doesn't really rotate what else do we have we have an L take it from up here and L look something like this then we have the J yes an inverted LS or horizontally inverted L what else do we have we have the i the big long favorite piece the one we will always be waiting for and so this I'm going to put in a four by four matrix because it's also because it makes it much easier to anticipate the rotation then we have the s and SC pieces so we start with s I'm going to copy this smaller three by three matrix in here and s should be something like this I think and then finally I think the sea peace so this should be seven and one two three four five six seven okay I think that looks good now we want to get a random of these every time so I'm going to create a player reset method here so function player reset and here we list all available pieces in a string so we say Combs whoops can't be this equals what is it i LJ o T s C and then we say player dot matrix equals create piece and we can say pss-pss dot length times math dot run done I'm Lorde then we also want to say put the player at the top and want to put there in the middle so we can say player dot position of x equals Arena first row length divided by two and floored plus no minus player dot matrix first row dot length length divided by two and floored so that will be something and then we need to run this play reset I guess in the what we have have something where we move down and collide Leah player drop so after the merge run player reset instead of this let's give it a shot so we drop we've got the new piece perfect okay looks kinda good whoops so this is something you should fix now when we fill up like this it means that the game is over and in order to detect this I think can do something simple with collide some thinking if we just reset the player and we collide immediately afterwards that should mean that the game is over so I'm going to say if call lied arena and player then we simply cleared arena we in a dot for each row and row dot filled with zeros so this just remove everything from the arena so let's try if this works this just we hold down we just stack up pieces and then clear okay cool that seems to work reliably now I think it should be nice with some colors there and the way we can express colors it's just instead of having a pawn here we can have a 2 and the 3 and then map that to color names so let's get started with this I'm gonna oh it's going to get the 2 and then the L is going to get 3 yay going to get for the AI is going to get index 5s is going to get 6 and Z is going to get 7 and now we need to set up this color map so I scroll down here and I'm gonna put it yes simply here it doesn't really matter homes colors and 0 is nothing so if we don't need a color hair is gonna Pat it with null then we can split some arbitrary colors there for now we say red blue violet green purple else you have orange and pink just the right amount zero one two three four five six seven yeah since checkout then in or draw matrix function instead of saying context of field sallykaus red we can say colors and value as we have so let's see if this does what we want okay red blue this don't boop-boop yeah seems to be working well the colors aren't really beautiful so I have prepared a set of coldest air that I like better let me copy them in here this is whoop Ariel ah it's a true work of wonder this let's play around a little bit oh the tetris Ave user should notice that we didn't collect the Rose so that's the part that's missing let's go and solve this problem now I'm going to add a new function and I'm going to call this arena sweep function arena sweep and in this one I'm going to have a for loop that says for let y equals re-enabling so we're gonna iterate from the bottom and up in this case it's actually arena dot length minus 1 then we'll do this while y is less than 0 and here we're gonna say minus minus y instead of plus plus as we usually do on the next row we're going to loop over X in the normal direction so you say for left x equals 0 while X is less than arena of index y dot sling and then plus plus X here and the thing we do here is wanna check if any of the rows have a serie in it if it does it means that is not fully populated so we can say if arena y and X equal 0 means that it is not fully populated then we can continue that means that we just go up here again you should continue as continuous the current for loop so in this case this does make sense but there is a little bit of an obscure tricks in your script if we set the label here that's outer column then we can call continue after down here we do like this will first iterate over the lines then iterate over X and assume we find a spot in the line that is 0 let's continue on the next row if we didn't find any spots we're going to be down here and now we can remove that row from arena to say arena dots splice and index is y and length of the splice is one and then we're going to do another trick here we're going to immediately access because splice returns all the rows it brought out of the array and by saying zero here we mean if they reference the index Y of this next row and we can immediately then fill it with zeros so if we say cons row equals this we should have an empty row here and that row we can put on top of the arena by saying arena dot on shift row so this line takes the arena row out at the necks why it fills it with zeros then we save that row in here and then later we put it on the top of the arena since we removed and index down here we will have to offset the Y's we seem to say plus plus y down here this arena sweep method we can also run in player drop layer drop so after we reset the player we do an arena sweep let's make sure this works so we don't have to wait for this we can say arena 19 dot filled with once so now if you like this should disappear then work at all that's so great guess we're going to debug top plate and we boom we get the debugger into arena sweep that looks fine three node length and so here Y is undefined and now Y is 19 so that means that oh we need to say well why is more than C where so little typo I guess so let's remove the debugger booger there we go so boom and we take another one for good measure the seed in both disappear plop great stuff when we sweep we want to count scores so I'm going to create a new element here where we can put score they name this with ID score and then we're going to add a simple helper function for this down here that's called update score function update score and it's simply going to say document dot get element by ID score dot inner text equals player dot score then of course we need to add a score holder here on player score zero and another thing which probably do while we while we're here is just to reset the player initially right now a little bit of weird default values here so let's call reset play around here okay reset so anyway I guess we go back out to our arena sweep and first I want to have a row counter left row count equals one and then when we have swept a row I won't say player box score plus equals row count times ten and for every row I want to double the score you get so here we simply multiply row count by to roll count x equals two then we also need to call update score when we have swept I think that is in the player drop function yeah so here we update score just for the sake of it and we should also probably reset the score when we have a disaster so this is in the player reset and we meet it glide we empty arena we set player dot score to zero and we update score see if we have some have any success with this okay we don't see okay there are in the score cam so I guess we need to bootstrap the game with update score once at least update score there we go that looks a little bit better and now let's see if we get score so now we should get ten because we have two lines I mean one line okay ten in score so let's feel some more lines that's sick - and now we should get first it because first 10 and done 24 next row yeah 30 let's go crazy here 18 19 17 and 16 now if you get I don't know even 150 so I guess that's 10 plus 20 plus 40 I can't even count this high but it's a lot of scores at least and now I think we have a red or good tetris here to be honest it could probably be a little bit more beautiful but let's just make sure it works so boom there mmm-hmm I want to tap this error perfect good piece a blue one we want that we want the box another box Oh boom oh this is nice and then let's see what happens if we break it boom we got serious core and they cleared well that's pretty Tetris II to me let's spend some time to style it up so we can do that here and I'm going to add a style tag style and here first I want to say both day and the background should be a little bit darker so I'm just gonna wing it to 2020 28 so it is a blue hint ish dark gray and the font should just be white so we can read the score easily and we of course want a sans-serif font family and we want a little bit bigger font size they set this to 2:00 a.m. I guess and then we want to text the line align everything whoops text and context align Center so dish should put everything in the center everything went wrong classic CSS this oh forgot to close a style okay it's centered and I think colors are fali okay just one more thing yeah we want to set the canvas to have a border or the solid point 2 a.m. and white and then we also want to set the height to 90% of the viewport height so there we go looks like we have a Tetris yeah this checks out it is the Tetris indeed so that status and mountain is how I create the tetris
Info
Channel: Meth Meth Method
Views: 362,629
Rating: 4.9198084 out of 5
Keywords: JavaScript, Web, Programming, Tetris
Id: H2aW5V46khA
Channel Id: undefined
Length: 51min 34sec (3094 seconds)
Published: Thu Sep 08 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.