How to Build Tetris in React - GameDev Tutorial (with React Hooks!)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to this tutorial we're going to build a Tetris game we'd react and the first question you should ask yourself is is react a good choice for making a game like this and to be honest I don't know it is probably better to build it with vanilla JavaScript but I wanted to do this for myself to test how this game can work out with react and sometimes I'll do these kind of products just to yeah kind of expand my knowledge and try things out and the idea for this started when I was looking at the tutorial at YouTube where this guy creates a Tetris game with vanilla JavaScript and it's in this channel that's called meth meth method and yeah you can think whatever you thought of that name the tutorial is really good actually and I learned a lot because I have to say this I'm not a game maker I create web applications and stuff like that and web pages so I'm kind of a rookie in the game development it was fun to create this game we'd react and see how it works and in this video he used canvas I'm not going to use canvas I'm using regular divs and a grid for this one because I wanted to try that out also and not use canvas and it's also good to see how good react performs cause there's going to be a lot of divs that we render to the screen because each cell in the Tetris game is Adam and I'm also going to borrow some of the code here and especially the one where we're going to check for collision when we rotate our tetromino that is the name of the blocks in Tetris big credits to this channel math math method and the video where this guy shows how to create a Tetris game in just I think it's 50 minutes or so yeah and it's a really good tutorial if you want to learn how to build a Tetris in plain JavaScript alright let's get to the app then and here's the tetris game that we're going to build our shoes to have kind of a retro style to it with this stores in the background this is just an image I found on unsplash and we're going to show the score at the rows and the level and then we have a start button so if we press Start again we can play the game and we're using the arrow keys on the keyboard for this one you rotate the Tetra minor with up arrow and you kind of go left and right with other arrows and down will make it go faster down there and there will be some limitation in this game because this is not a perfect Tetris game for example the key input we're just using the regular repeat here when holding down the down arrow key there should probably be a better function for this where we can control the speed of this one and also I will be using an interval for this one we could also use requestanimationframe where we can create kind of a more controlled animation so it will not be a perfect Tetris game but it will be a good practice in react and especially react hooks that so many people are talking about now on the Internet so we will be creating custom hooks and we will use state we will use use effect and use callback and also we're going to use react memo for minimizing or rear-end us of the cells so I think this will be a good practice in react and especially react hooks so let's get to it we will start creating the game in the next video we're going to start to build our tetris game now and we're going to use create react app and I actually use that one a lot cause it's great for bootstrapping your project and don't have to set up your web pack and Babel config and everything like that from scratch so I highly recommend you use create react app it's great and we create a project by go into our console in my case I'm using hyper and we just type npx create - react - app and we can cool our application react - Tetris this will create the folder that called react - Tetris and then press Enter and then we just wait it will take a second here alright we're good to go here and it's important now that you navigate into the new project folder you created so type CD react - Tetris and if we list the files you can see it has created some folders and files for us here and now I'm using style components for this game so we have to install that one also and we do that by typing NPM I styled - components all right some arrows here but I think we'll be fine it's just on my computer I can clear the console I have also included some files in the starter files that you have to copy to your project folder otherwise it won't work so make sure first of all that you download the starter files it's on github and the link should be provided to you and then in the starter files you have something that's called BD dot PNG that's the background image that the Stars you see here then we have deformed that's called pixel I found this one on the internet it should be free to use so I hope it is and we have something that's called use in the world of chaos and that's a custom hook that's created by Dan Abramov that I'm going to use when we create a game loop with the JavaScript interval so we just have to copy this one over and I'll explain it later in the tutorial first grab the BD dot PNG file copy that one and go into your direct folder and inside SRC the source folder we create a new folder that's called I am deed and that's for image of course and you can just paste the background in there all right then we have the font so grab that one copy that one and create another folder inside of your SRC your source folder and we can call this folder font go inside of there and paste the font inside of it and then we have the use in the world of J's file so copy that one and still in the SRC folder create another folder that's called hooks this is the folder where we're going to create our custom hooks so go inside of that folder and paste the use in the hojae's file and this should be it this is everything we need to get us started so in the next video we'll start to scaffold out some components and we'll continue with our application the first thing I do when I create the react application is that I scaffold out all the components that I need and that's what we're going to be doing in this video so first of all you can see that we have a lot of files here that was created for us with create react app and we're not going to use some of this stuff here you can yeah you can delete it if you want the logo the serviceworker the app test and stuff like that or you can just let it be because we're not using it now we are going to use the app dot JS file here and index dot JS file for now and the index dot J's file we don't actually have to touch that one we can just go inside the app dot J's file we can delete everything inside of there so as usual or application is going to start in the app dot JS file this is kind of the highest component in the hierarchy so we import react from react we import Tetris from dot forward slash components forward slash Tetris right so and of course this one we haven't created this one yet so we're going to create that in a minute and we create our app function I like to use arrow functions for this one you can use a regular function if you want to do that but we have con stab equals parenthesis and we're going to create an explicit return for this one so we just need parenthesis then we can create a div with a class name of app and we have our tetris components like so and then we export default app and that's our app component then we can create a new folder inside our SRC folder that's called components inside the components folder we are going to create five different components so you can just create the file names now so we create one that's called cell das make sure you have a capital letter here to start with or yeah maybe you don't name your components like that but I like to name them with capital because it's a component so we create another file that's called display doc das and we have a new file that called stage das and we have a new file that's called start button das and the last one is going to be the tetris doc yes file all right these are our five components the tetris dot JS file is kind of the heart of this application we can go into our cell dot JS file and start scaffold out this component so we import reacts from react as usual and we create the component cost cell equals two parentheses and we are going to have props for this one so we can create these ones also Ida structure the mouth we don't have a type for this one and we talked about this later on we make an implicit return for now and we can just have a div and yeah right cell inside of it and we export default cell like so so we say that one and then we have our display dot JS file we import react from react we have a Const that's called display equals and for this one we're going to have two props so we destructor them out one is called game over and one is called text and we create a div inside of here where we're going to have the text we create curly braces and text so grab that prop and display it inside of the deal export default display we will style these components later with style components so we will change some stuff inside of them we just scaffold them out now so we know what components we're going to have this game save that one then we go into stage 2 ts file we import react from react of course you can copy and paste a lot here also if you want to do that for this one going to import the cell component so we import cell from dot forward slash cell and then we create a Const stage equals two and with the structure to prop that we're going to have that's called stage and we make an implicit return for this one also and as you can see I'm not doing any prop type checking for this course you can add that in yourself if you want to do that to verify your props with prop types all right we create a div for now again an inside here we're going to map through our stage prop and create cells from this stage prop and we're going to do that later also so it can just have a cell for now inside of this and we export default stage like so and we save this one then we have our start button dot JS file so we import react from react and we have a cost start button and we have a prop that's going to be pull back for this one and we make an implicit return with a div that says start game and we export default start button like so we say that one and then it's the last one it's our tetris component or heart of this application so we import react from react like so and then we're going to have some components here we import our stage from dot forward slash stage we're also going to need or display from dot forward slash display and we import or start button from dot forward slash start button and these ones we can check them here this is obviously going to be the stage with the cells in it and these are the display components we have three of them and this is the start game button here so these are the ones we'll create and now they'll recreate our post Tetris and equals to an error function and we have curly braces for this one because we're going to have more logic inside of here and we can create the return statement here first we have a kind of a rapid Eve here and as I said we're going to rename these ones when we style the components then we have our stage and for now we're not sending in any prop because we don't have anything to send in to it right now then we can create an aside element that's obviously the sidebar here that we're creating and then we're going to have three different displays now for these ones we have a text prop and for now they can just say score you can copy this one and paste two times and this one can say rose and level all right you can also wrap these ones inside of a div and end it like that and below we're going to have our start button and it's going to get a callback prop but we don't have that yet either so we're not giving it that now so this is it and we export default Tetris like so okay then we can store this up to see what we've got so NPM start and we have all our components showing up here and that's great they are of course not styled yet but we're going to do that soon first we have to create the stage and or tetra- and we're going to do that in the next video before we do the styling so we can see the UI here okay we're going to create the stage and the tetra- in this video and to do that we have to create a couple of new files inside our source folder or SRC folder we can create a new file that's called game helpers ojs and that's a lowercase G on that one because this is not a component and we can also create a new file that's called tetra- ojs make sure you're inside a game helper cas file here we're going to create a stage and we are going to have two costs where we can set the stage width and height and we have to import these ones into our components so we have to export them from this file so we export cost and then with capital letters we can have stage width and we can set that one to twelve and we export Const stage height and we set that to 20 so that's our width and height but we actually need a function that creates the stage for us and the stage is going to be a nested array a multi-dimensional array that represents rows and columns and we have to export this function that creates the stage also cause we're going to need it in our components so we export cost create stage and it is an error function alright so how is this going to work well we're going to create a multi-dimensional array that represents the grid so we create an array from something and that something is another array that we're going to create from the stage height and this is going to be an empty array so it's not going to be useful for us so we have to do something where to fill this up with something we can do that by supplying an inline function here and that means for each row we create a new array from the stage width and we're going to fill it with another array there's a lot of a race here and for now we set it to zero and we have something that's called clear and these ones I'm going to explain it later on zero equals nothing on the grid we have the different tetra- each of them going to have a letter here so we know that the grid has that tetromino in that particular cell and we also have this clear property here that it's going to be set to merge when we have a tetromino merge into the stage that means when we have collided so the tetra- should stay in the stage and not be cleared in the next render and as I said I will explain this later on so I hope you understand this function what it's doing we're creating a new array from an array that we're creating here with a States height that's the 20 rows we're going to have in our grid and we're supplying an inline function that for each row create a new array with our cells and we're filling them up with this array here that has one value that is 0 and that's represent a clean cell there's nothing in that cell on the stage and we also have this string here that says clear for now and that means that there's no tetra minor that has collided in this cell and we should wipe it out from the stage in the next render okay so that's how we create our stage and if you remember up here in the components we had our stage here and we had our prop that's called stage and this is the stage we're sending in from the Tetris component so we can actually import this one here in the Tetris dot J's file we can import our create stage function here and we grabbed it from dot dot forward slash game help us like so and for now we can just send it into this one we have the stage prop equals curly braces create stage and parentheses because we invoke this function here just checking so we're not breaking anything here now and we going to this later on because we're going to have the stage in a custom hook and a state for this one but for now we can just send it in so it renders something inside a stage component you can remove this one and inside the div here we create the curly braces because we're going to use JavaScript now and map over our stage prop so we have a row and we also map through that row and then we get our cell and or X value for that one so what are we doing here well we have the stage that's the one we created we map through that and when we map through that stage array we get the row and each row is also an array that holds the cells so we map through that row also and we get the cell so for each cell we are going to render out the cell component we can set the key to X and our type are going to be the first value in the cell array and that's the one we created down here we're telling it when we initially do the render we're telling it that this stage is clean we don't have any tetromino in the stage so we grabbing this value here and that's a serie that we set it to initially go back into your stage component we have to close this one also this one should hopefully render out the stage for us but as you can see we didn't style it yet so it's just a lot of cells here in one column but we're going to fix that when we do the styling later on alright let's get back to our code that's our stage now we have to create our tetra- and we're going to keep them in a Const that's called tetra- and it's going to be an object so we export Const capital letter tetra- equals an object and we're going to have different properties with these ones first we can create a property that's called syrup because I'm going to use this initially when we store the application we don't want to show a tetromino on the stage but you could do it some other way of course but I think it's nice to have it inside of these tetra- object alright so we create an object we're going to have a property that's called shape and the shape is also going to be an array with a race I noticed that there's a lot of a race with a race when you create games like this so we have an array then we have another array and we just set it to zero and then we have another property that's called color and this is just going to be a string 0 comma 0 comma 0 like that so that's our clean cell that's what we're using when we're not showing any tetromino and then we have seven different tetra- we have the I DLL st and said so we can't start by creating the I so we create a new property that's called I and we create a new object for that one we have the shaped property that's going to be an array and inside of that array we're going to have another array and as I mentioned before zero equals nothing on the grid and we're going to use a letter where we want to show these tetra- first we have a zero that's nothing and we have a string with a capital I then we have a zero and the zero then we create another array with another zero and another I and a zero and the zero and this one is just going to be a four by four so we can copy this one and paste them in like that and as you can see these going to be the eye shape that is the long one the long turtle minor that's the only one that has four in width and we can make it a little cleaner here maybe I will not auto format is because it will destroy this formatting I've done here it's easier to see the tetromino here otherwise it will format it in just one line for me and that's no good so we have another property here also so we have the color and this is yet again a string and this is just an RGB value I'm going to use in the CSS later on so I'm setting the color for this one - 82 - 7 - 3 0 so this is the eye we have here well I guess we can just copy and paste this one make sure you make a coma deer and we create a J and a shape for the day is going to be we can remove these last ones because it's going to be three by three so we remove the last row there also change this once - j j day and we're going to have a j there also i hope you see this oops it's going to be string i hope you see this pattern here that this is a j and the color for this one is going to be 36 95 - two three all right then we copy this one and paste we're going to create the L shape and it's exactly like the J but we change this one and put it there instead and of course we should have an L also as a value in these streams and the Cora is going to be two to three one seven three and thirty six all right we copy this 1 make sure you don't forget that coma dear and we're going to create the shape and this is actually just going to be two values in so we have the Oh Oh like so and oh so we have a 2 by 2 array there and the color for this one is going to be 2 2 3 2 1 7 and also 36 for that one alright then we can grab the El up here copy it make another coma paste it we have the S shape and it's going to be a 0 and s don't forget that this is a string here so don't forget the ticks here and then we have an S and an S and a 0 and these ones are just going to be zeros like so and the color is 48 2 1 1 and 56 alright then we paste in yet another one and we have two to go we have the T and that shape is going to be 0 0 0 then we have a tea a tea and tea and now have a serie a tea and a serum a nice little shaped tea there and the curious one hundred thirty to sixty one and 198 and we have the last one and that's the said whoa kind of boring this but we have to do it otherwise we don't have any tip from - alright the set we have a said asset and a zero then we have a zero said an asset and then zero zero and zero and then we just have the color for this one and that's two two seven seventy eight and seventy eight all right so that's our tetra- and we have one more thing to do because we want to have a function that generates a random tetromino for us so we export cost random kept roam I know and we create the function for that one we have curly braces here so first we create the cost called tetriminos lowercase letters and we create the string with capital letters IDL OST set and this is of course the string with all our seven tetriminos now we create another cost ran the tetra minor like so we're going to grab a random letter from this tetra - string and we do that by typing tetra - that's the string Const and inside of here we do a little math dot floor math dot random times tetra - length like so and this is just a standard for generating random numbers of the length of this in this case the string so where the string length and we're getting a random number for this one and I misspelled this one it should be tetra - yeah so we have the tetra - string and we grabbing a random number for that one and that will return one of the letters for us and that's how we get to random tetromino because now we can return from or tetra- Rand tetromino so for example let's say that this will give us an L here so we have that one and we go to our tetra- object and we have an L here and that will of course grab the L property for us and return this one here the L tetromino with the shape and the color this is an object here so we get that object back and that's how we get a random tetromino type the serie here it should have cost beyond oh there and say this one all right this was a lot I know I know and I think that's why I don't do games but I recommend it to really go through this code and try to understand it as much as possible before moving forward in the next video we're going to create the styles with style component and after that we're actually going to start to do some heavy coding on the game we're going to do some styling now to get this sad look out of this Tetris game and if you're not a CSS person you don't like the style things you can just copy and paste the styles from the starter files into your project but you have to import them into your component as I'm going to show in this video and also change your divs to the components that we using from the styled component I'm going to show you this soon so let's get on with it first of all we're going to create the global styling and actually I've been trying to lace you for this one because you can't create global stars with style components but I'm actually just going to use this index dot CSS file that's yeah premade for us with great react app and it's imported in the index file and that's because we're going to have a font and it's a little bit more troublesome to import it with star components so if we go inside index dot CSS file first we're going to set or body we're going to set our margin to zero and then we are going to import a font so we have a font face and firmly is going to be call the pixel and we have a source SRC with or URL and we grab or font from font forward slash pixel - LCD - seven dot both we can also set the format to both like so and we say that one yeah and we will not see anything happening here right now but that's our global styling then we can move up to our components and we're going to style the tetris component first and what I like to do when I use star component is that I create this folder that where I place all of my styling and then I import them into the components so inside of the components folder create another folder that's called styles and inside a Styles folder create a new file and call it style Celsius I also like to name them like this with styled and then the component name and ojs so styled Celsius capital s capital C and first we have to import style from style components and then we need to export or style component because we're going to import it into the Tetris component when we created this one so export comes to style sell an equals style dot and this is going to be a diva we have backticks because this is a tag function and this is how style components works you have this tag function and you can write regular CSS inside of it and if you don't know style components I really recommend you to read more about it at their webpage I'm not going to go through everything with star components in this tutorial cause as I said before this tutorial is about showing you how to build a Tetris game we'd react and I assume that you know some stuff with react and yeah star components also otherwise it's not that difficult to use star components so I think you will pick up a lot just watching me create these come opponents all right and I just realized I created the styled cell now okay I said Tetris component but it's the styled cell I create a null so well let's create the styles for the cell component first done okay we're going to have a width and set that to auto then we're going to set our background and that's going to be an RGB a and we're going to grab this from the props that we send me into the cell component so for now I just type this out and we go to the cell component and I'm going to show you how these prop work so we have a dollar sign curly braces and props and an arrow function and a props we have one that's called color so that's how we get our RGB value and we set the Alpha value to 0.7 this is just regular CSS so we're going to come back to this in a second but first we save this one and we go into the cell component and I'm going to show you how this works with the props so first of all we import or styled cell that's the one we created and we grabbed it from Styles forward slash styled cell like so then we also going to need or tetra- so we import or tetriminos if you remember that's the one we created down here it's an object with different tetra- so we grab that from dot dot forward slash tetrominoes alright so now we got everything we want in this component we can now first change this one to our styled cell that's the one we create here and we import it in this component here so we use it here you could write the style component inside of this component and many people do it like that but I like to have them separated because I think this is yeah I like this structure of things so you can do whatever you want and don't have to do all this export and import stuff that I do here okay so this style sell is going to have a type prop and we grab the type from type we are sending that in here and now we're passing that prop in through our style component and now we're going to have a color and the color we can grab from the tetra- and the type is going to be the tetra- so we if we for example have the type of L it will grab the tetra- L for the color and of course we're also going to grab the property color because when we created the tetra- we have both a shape property and the color property so this is the one we're grabbing here is the color property from the tetra- all right so for now we can just we change this one yeah we can say on L because we're not sending in anything to this component yet because as I said I intended to do the tetris first but now we do the sell here instead and as you can see now we're getting the color here but it will color everything here and that's because this cell row you see it's the commit take up the complete weed here so the color is there but we haven't created a grid yet and that's because it's showing all yellow now because each cell is a hundred percent with right now alright let's go back to the styling we need some shadows on or tetra- so this is also how it works with props that you send into your style components you can grab them with an inline function like this because this is a tag function you can use a dollar sign and curly brackets and use expressions inside of these ones and by using this inline function we can grab the props that we send into our style components and we had one prop that is called color so we're grabbing that one inside of here all right so that's our background we also want to set our border yet again we have a dollar sign and curly braces we have our props and then we're going to do a ternary operator here we check if or props type if that one equals to 0 that means we not have a tetromino in this specific cell so we don't want to have a border so we set that one to null pixels solid I don't actually yeah I don't think we need solid here but yeah let it be there for now otherwise we set it to 4 pixels solid all right then we have our border bottom color and that is going to be on our DBA and yet again we have a dollar sign curly braces we have our props and we have our props color and we're going to set the Alpha value here to zero two point one we can actually just grab this one and copy and paste it in three times because now we have border right color and that one we're going to set to one and then we have border top color one also for the left color and we set that one to zero point three and this will give us kind of this shadow effect on the blocks yeah if you don't like them you can just play around with these and set your own shadow and this is also what I liked about star components because you can send lien props like this we can easily modify or CSS conditionally with props and that's really nice actually so what I'm doing here I'm just using the same color value as we set in the tetra- object but I'm just changing the Alpha value to get different opacity on the blocks all right let's go to our tetris das file now and do it in the right order here we are going to create two different style component here we have one that style tetris rapper and one that's called style tetris so we have a wrapper around here and we have the tetris also we can actually just type them out here so we can see the structure or it's here it's going to be a styled tetris wrapper like so and we close it down below there and it will complain our course we haven't created this one yet and then below we're going to have the styled tetris component and of course we have to move that down here like so and I will explain later why we have this wrapper here so these are the two star components so let's create a new file inside of the Styles folder that's called styled Tetris yes and inside that file inside style Tetris dot yes imports start from style components like so we also need to import our background image so we can call it BD image and we grab that from dot dot forward slash dot forward slash I am D V J dot PNG like so then we export Const or styled Tetris wrapper and that one is going to be a styled dot TV and we have our backticks because this is a tag function we set a width 200 viewport width and our height 200 view put height yeah this is just regular CSS now and I'm not going to explain the CSS here either I hope you know your CSS otherwise you can pick up some things here but I won't explain them yeah in detail and here we can set our background with a URL and now we can just use or BJ image and we do that by creating a dollar sign and code basis and inside we have obedia image we can set a default color to zero zero zero we have a background size cover and overflow is going to be hidden for this one and this is also great with star components cause otherwise if you set a background image you may have done some inline styling to get the image to show up as a background image but here we can just import it and use it in the star component like this so we don't have to do any inline styling on the component itself alright then we have our export calls to style Tetris and that's going to be a style deve also type function this is going to be a flex we align items to flex start we set our pairing to 40 pixels and we have a Morgan of zero and auto and a max width of 900 pixels the CSS here is not really optimized you can try to get a better look for yourself if you want to do that I haven't put that much time in the CSS styling I just wanted something to work fairly good so you could probably improve the CSS and get a better grid and stuff like that and inside here we have our aside and we're going to style that and this is also great with star components cause you can nest them inside of here just like you do in sass for example so we set up with 200% max width of 200 pixels we set our display to block and padding to 0 and 20 pixels like so and that is going to be our star component for the style Tetris no we just have to import it up in the component so we can import or star tetris rapper and/or style tetris and we grabbed him from dot forward slash styles forward slash style tetris and now it shouldn't complain here no alright and as you can see we are gradually changing this one to something else we see the space here now and we see that the cells are just yeah this tiny bits no alright then we can create another style inside our Styles folder that's called style stage das and we create the style first so we import style from style components then we export Const styled stage and it's equal a style div and we have backticks cause it's a tagged function and we're going to display a grid for this one we have a grid template rose it's going to repeat we grabbing from props or props dot height a coma and then we're going to do some CSS calculation here we have 25 viewport width and we divide it with we have dollar sign and curly braces cause now we're going to have another inline function another inline function to grab our props and we grab the props dot width and this is going to do some nice little calculation for us to make the grid look nice and we are doing this to keep the aspect ratio of the grid cells then we have our grid template columns that's also going to repeat and from our props yet again we grab our prop start with and it's going to be one fragment and of course that one should be there like so these calculations is because we want to keep the aspect ratio of our cells we want them to be perfect squares all the time and this is actually kind of tricky to do so yeah I've got it to work yeah fairly responsive but not 100% so if you come up with a better idea feel free to change it to whatever you want we want to have a grid gap of one pixel and the border going to be two pixels solid and we can set it to 3 3 3 we have a width of 100% and max width of 25 viewport width and a background of say 1 1 1 all right so that's our styled stage we just have to import it into the stage component so make sure you inside the stage component an import styled stage from dot forward slash styles forward slash style all right and then we rename this one to our styled stage we close it with the same and we're going to send some props inside of this course we had a width and that one we're grabbing from we are sending in the stage as props to this one so if we grab the stage and the first row and the length we know the width of our grid and the height we just grab the stage lengths like so and that will give us the height from our multi-dimensional array all right we save this one and see what we've got and as you can see we have something here so we're slowly getting there we can actually now also go back into the cell component and we can remove the text here we don't need that one and that's why we can just self close it like this and that will get us our grid and here you can see the shadows that we created in the cell component and it works fairly responsive what have we got left to do we go into style or display and or start button inside our Styles folder create a new file style display dot yes and import styled from styled components and we export const styled display and it equals a style div and yet again backticks box-sizing to border box we display flex we align items to Center why I'm using flexbox is to align the text in the different displays we have a margin of 0 0 or 20 pixels and 0 we have a padding of 20 pixels we have a border of 4 pixels solid and a triple 3 we have a min height of 30 pixels we have a width of 100% a border radius of 20 pixels and the color and that's why we're grabbing from props yet again we have a dollar sign and curly braces we have our props and we do a ternary operator cause we are using the same display component when we did play game over as we display the score and rows and things like that so we have a prop that's called game over and if it's game over we set the text to read otherwise we set it to some grace we set the background to black we have a font family of pixel that's the one we imported in the global CSS file we can sell it yeah some fallback fonts here and the font size of 0.8 RM like so and then we just have to import and use it in our display component so we import a styled display from dot forward slash Styles forward slash style display and then we change this div to our style display component and we also had our prop that's called game over so we send that one in like so and let's see what we've got and there's our nice displace and we have this retro formed inside of them and that's good we just have to style a start button and then I think we'll be good to go to do some heavy coding on this game so inside our Styles create a new file and call it style Start button dog guess import style from style components whoo getting boring boring boring but we have to do this so we export a Const and style Start button and we have a styled button double backticks and inside we write or CSS we have our box sizing and we set that one to border box we have a Morgan of 0 0 of 20 pixels on 0 we have a padding of 20 pixels a min height of 30 pixels of width of hundred-percent and a border radius of 20 pixels of border we set that one to none we have a color of white background for a triple three we have a formed family of pixel and some fallback fonts we have a font size of 1 RM an outline of none because we don't want to display that ugly outline when we press the button we set the cursor to pointer also and we say that one an inside or start button we are going to import this one so we import style start button from dot forward slash Styles forward slash style start button and of course we change this one to style the start button we are also going to have an on click Handler on this one so we can type it in now so we have the own click and it's going to be a call back alright so that's the start button and it's showing nicely but nothing is happening now because we don't have that callback created yet but we have something that looks like a Tetris we're just going to remove this yellow one from our cell because the type is going to be the type and here we also change that one to type because that was only to show you what we were doing here and as you can see now we have our grid here instead and that's nice cause that's our playing field and everything set up for us so we can start coding the real game here and we'll start with that in the next video so see you then okay we got our stage or displays and/or start button and it's time to code some logic for this game and how is it going to work yeah well we're going to have this stage of course with the cells here and we're going to have a player and we're going to use react hooks to create this game and two big advantages with hooks is that you can abstract them and you can reduce them and compose things together and that's really great and for this game we're going to create three own custom hooks and that's the use stage use player use game status and the use interval is the one that Danna remote created for us and the reason that I created these custom hooks is that I want to kind of separate out the logic for different things so we have all the logic for the player in the use player hook and we have all the logic for the stage in the use stage hook and we also have the use game status that is going to have yeah mostly the display logic that we're going to show like the scores and things like that and how many rows we cleared so that is how we're going to divide up the code and we have the tetris component that's going to be our main component as I said before that's the part of our application and as we creating a game we're going to have some kind of game loop and as I also said before we're going to use an interval for this one and not using yeah maybe the more sophisticated way where you get animation frames and stuff like that so we have this grid here that is represented by the array and we can actually console.log this one out so we can see what we have in our array so inside of here somewhere we can console.log create stage like so and I'm just going to show the console here and as you can see we have an array with twenty rows in it and each row has twelve cells and as you can see here we have a seer and that means that this cell is clear we don't have a tetromino in this cell and it's also set to clear as you can see now we just have a clean stage here so everyone here is clear and that means that we don't have any tetromino merge interest because when we collide with something we're going to change this one to merge and in the next render we're going to keep every cell that has merged here and that's the way we keep the tetra- that has collided I think it will get to much more clearer when we actually create the tetromino and how our game loop works because the game loop are going to do a couple of thing for us the first thing we have to do in our game loop is that we clear the stage and then we check for any merged cells here and we don't clear the merged ones so they are going to stay in the stage they're going to stay in the array for a stage and then we're going to check the position over tetromino and if it hasn't collided we are just going to set it to clear again and that means for the next render it's going to be wiped out and it's going to move and that's the way we get the illusion of movement here or maybe it's not an illusion it is a movement but the tetromino that hasn't collided is getting cleared on every render but if we have set this to merge it's going to stay in the stage and then we do this over and over again with our interval and that's the way we get the movement for our tetromino so that's the short very compact version of how this game loop is going to work and we also kind of have to look into the future because we are going to check the collision before we actually move the player so when we make a move if it drops or if you move it with the arrows on your keyboard we first check the collision before we make the move and if it collides we don't make the move because then we know that it has collided we always check the game field the stage one step ahead before we make the move and that is also going to be much more clear when we actually do this coding I just wanted to explain it shortly for you so you have a rough idea of how this is going to work all right so let's get back to our code we can start in our hooks directory in our hooks folder and inside of that folder we create two new files we create one that is called use player dot yes and one that is cool use stage EAS and as I said I always named my files as the component or in this case the hook itself and in react you always name your custom hooks with use before the actual name so in this case it's you stage and use player so we can start off in the use player JS file so make sure you're inside of that file and we import and we're not going to need react for this one we just need to use state state from react because this is not a react component so we just importing the you state then we can import our random tetromino function and we grab that from dot dot forward slash tetrominoes then we export Const and we have our use player as I said it's important to have use before otherwise react won't know that this is a custom hook I have an error function curly braces and we're going to create a state for this one and that's the only thing we're going to do in this video then we're going to build more up on these files in the next videos we're going to create the state now with a hook that's called you state that we imported up here and you state will return an array with two items in it for us and that's where we can use es6 destructuring to grab these two values so we have a Const and we have an array that we want to the structure and we can call it a player and we have the set player and we use state and this is the way that new state works as I said we get two values back we've got the actual state here and then we have this sector for this state you can call them whatever you want they don't need to be player or set player and this is just two values that weed the structure out here so this line here is actually short for all of this we have a cost with layer state maybe and we use state and then we or player and we grab players state and the first value in the array then we have our set player and then we have our player state and the second value in that array but by using es6 destructuring we can make it in one world here and that's very very convenient and that's the way you should do it when you do state so get rid of this we are also going to set an initial state for a player and you can actually send in your initial state to the you state when you create the state with it we're going to have an object so we have curly braces and inside we're going to have a property that's called post that's the position for a player we're going to have an x value and we set that to 0 and an Y value we set it to 0 also and then we have our tetromino and that's going to be one of them we created down here that we are always going to keep in this state for the player and for now we can actually just set the random tetromino so we call that function and we're going to grab the shape from the tetromino and if you remember we had one shape property and one color property so this is the one we're grabbing here that's the shape of our tetra mono zero equals nothing and the letter inside of here equals the cells that are occupied in our tetromino and i choose to have the letter of the actual tetra mine here you can actually have the same letter for every one of them it doesn't matter because we're just going to check if it's not 0 when we render the tetra minor to the stage alright so we grab a random tetra mono and the shape of that one and put it in our state for the player and then we're going to have a property that's called collided and we set that of false so that's our initial state for the player and now we're actually just going to return the player because we're going to import this custom hook into our Tetris component and then we're going to need the player inside of the Tetris component I'm going to show you this in a second for now this is it for the use player we're going to return to this file and we can now move on to our u stage hook and do almost the same for that one so we import use state from react so we import create stage from dot dot forward slash game helpers alright and then we create their custom hook so we export Const and we're going to call it use stage and it's an arrow function curly braces and recreate the state for this one also so we call it stage and set stage and recall the u stage hook and inside of this we're actually going to give it the initial stage and we can just call the create stage inside of here and it will generate the initial stage for us the clean board for again as we have here so that's of state for the stage and we're going to return we're going to need both the stage and the set stage for this one so we return on a handle you can see that I'll type u stage here it should of course be used state like so so we save this one and then we're going to do a little bit of coding in our Tetris component also so make sure you're inside your Tetris J's file we can actually remove the create stage for this one now we just had it before we're not going to need that one cause we're creating the stage in ru stage hook now so remove this one and we can actually make a little comment here this is a style components and then we're going to have our custom hooks so we import use player from node forward slash hooks and use player and then we to import or you stage from dot dot forward slash hooks you stage alright and we already have import to the components we are going to use some state in this component also so we have to import you state up here alright so we both importing react and your state and now we can remove this console.log but it would be nice to have a console log here that tells us if it renders so we can create that one console log we render it's always nice to have now we're going to create two states now actually because yeah we're not going to use them right now but we can create them as we were already in this component we're going to have one that's called dot time and one that's called game over and the drop time is the actual speed that we're going to modify depending on which level we're on and then the game over is yet simply going to tell us if the game is over or not so we're keeping true or false in a state for that one so we create the new state that called drop time and set drop time we have you state and for this one we can just initialize it with null and we have a game over and set game over and ru state and we set that one to false of course it's not game over when we start and then we're going to use our custom hooks and if you remember from a player we exported or player and that means that we can grab that one with destruction here Const player and use player like so and whatever stage and for that one we exported to different values in an array so we can distract them out also so we have our stage and or set stage or custom hooked called you staged and we send in the player to this one we're not using the player in this custom hook yet but we are going to need or play in this one so we're going to modify this to use the player later so that's why we can send it in already no because we have the player here so we send that one in okay and then we can remove this one because you're not needing that functional we already have a stage in our variable called stage that we get from new stage so we use that one instead here and we can actually also use this game over variable here because when the game is over we're going to show a display that says it's over so somewhere in the aside here we create curly braces we checked our game over variable if that's one is true we're going to show a display component with a prop of game over with sending that one into the display component because if you remember we're changing the color of the text to read if it's game over so we just simply sending the game over variable and we have the text that equals to game over and we self close the component there this is a ternary operator so if the game is not over we're simply going to display everything of this like so so if we have a game over we just display this one that says game over we don't display the score the rules on the level and if the game is not over we are displaying all of these so we save the file and it seems to be working we didn't break anything in the game and it's just complaining here because we're not using these values yet but that's fine in the next video we are going to create the player movement with the keys on the keyboard and we're going to do the stage update we're actually not seeing and a tetraman now but we will see it in the next video hopefully okay let's create the movement for the player and also the stage update so we can see the changes take place on our stage here first we're going to be working in the tetris JS file the tetris component and I'm actually going to take back some code we deleted in the last video we are going to use the create stage function in this one also so import it again sorry for that we import create stage from dot forward slash game helpers we're going to need this one when we restart the game we need to create a clean stage for that one so we're going to need a few functions now because we're going to create the movement for the player so down below here somewhere below the console log re-render we are going to need a function that's called move player and it's going to take in a direction as a parameter for now we just leave it empty then we're going to need a function that's called start game we leave it empty for now we have another one that we call drop and we leave that one empty and we have another one that's called dropped player yeah and that may seem odd now that we have two similar functions here but it will get clear to you when we have more code in this component and I'll explain why them and the last one for now is a function that's called move and we go into the structure out the key code for this one this is going to be the callback function when we press the keys on the keyboard all right we're going to fill them with code in a second but first I'm going to explain this style Tetris wrapper for you so we created this one with a width and height of the complete window here and that's because we need some way to take our key inputs and this one the rapid Eve here is going to be responsible for that so it's going to have a few Propst we need to set the role to button otherwise it won't respond to the key press and we need to have a tab index that equals to zero and we have an on key down and we go into call or function that's called move for that one and send in the event so that's why we have this style Tetris wrapper it's some kind of hell you don't see the deep here but it will cover the complete screen here and that's why when we for example click here it will register the key presses for us if we didn't have that one or for example just put the key press on this one you have to click on this to get the key presses to register let's go to a callback function that's called move that's the one we call here first of all we're going to check that the game isn't game over because then we don't want to register any key press so if parenthesis and not game over then we can do something here and then we check again if or key code with the structure that one out from our event because on our event we have a property that's called key code and if we destructor it here we don't have to type e dot key code a little win here because that's not too long to write an e but yeah and we're checking if the key code equals to 37 and that's the key code for the left error on the keyboard then we're going to move the player we call or move player with the minus one because we're moving to the left that's why it's minus one if our key code equals 39 that's the right arrow on the keyboard we're going to move the player to the right and that's why we have a 1 here so left equals minus 1 because we're moving minus 1 on the x axis and 1 equals right because we're moving one step on the x axis and then we have another LCF if the key code equals to 40 that's the down error on a keyboard we dropped because we pressing down so we wanted to go down so that's a remove function and in or drop player function for now we're just going to call the drop so we're just calling this one we're going to have another little special case inside of this later on so I'll explain that them then we have our drop function and we're going to create the function in or use player hook that's called update player pause and here yeah it will do what it says it will update the player position update player force and we're going to give it an object with the x value of zero and the y value of one because we're dropping out and I can see that I'm in the wrong function here so just copy and paste that one inside it should be in the drop function so as we drop in here we're going to increase the Y value of one and make the player tetromino go down and we set the collided to false all right it will complain because we aren't created this function yet and in the start game function we can just make a little comment here reset everything and we set the stage to create stage we call our function to create a new stage and we reset the player and that's also a function that's going to be in the use player hook and the start game is a callback function also that we're going to have on our start button so we can set an onclick handler and call the start game function so what we'll do when we press the start game button we will reset the stage and we will also reset the player and then we have a removed player function and that one is going to take care of the left and right movement so we call the update player process and we give it the x-value of direction and the y-value of 0 because now we're just moving left and right and we're giving it a value here minus 1 or one alright we save that file and it will break now of course because we haven't created these ones yet so we have to create the update player post function and the reset player function and we're going to place them in or use player custom hook and that means that when we call or use player function here we also want to get the update player posts and the reset player from that custom hook alright so let's move into our use player hook so make sure you in the use player J's file and we're going to continue write some code here we're going to create these two functions here so we have our update player force and it's going to be a function that takes in an object and we can the structure out X Y and collided from that one and we create an error function curly braces and inside of here we're going to set the state because now we're moving the player so we can set the player state here so we call set player that's the one up here and we do that with an update function if we do that we get the previous state here and we have to have a parentheses here because we just can't give it the object because it will think that these curly braces are for the block and that's why we have the parentheses here we spread our previous state we set apostle to the new one we have an X property so we set that one two or previs dot X plus equals x then we set a y-value previs dot y m+ equals y so we're adding the values to our state here and then we set our collided property like so so that's the update player position we just set in the state with a new x and y values here and our collided value alright then we need one for reset play so we create the cost reset player and for this one we're actually going to need a hook that's called use callback and that's because otherwise our game loop will go into an infinite loop we won't see it now because we haven't created one yet in or you staged hook where we're going to use this function but trust me we need to have the used call back here otherwise we will be in a mess with an infinite loop so we use callback and give it an inline function here it is going to be dependent on nothing because we just create this once so we set the player and in this case we're resetting everything so we won't need to have this update the function here and give it a previous state we can just set the state from scratch so our position or post or X property we set that to our stage width and we divide it by two I subtract two also to get it kind of in the middle because this one will position the Tetra minor in the stage so this one will give it yeah kind of in the middle and we have our Y property we set that one to zero because we want or tetromino to be at the top when we reset the player and we have a tetra minor and we will give it a random tetra minor and grab the shape so each time we call this we will get the random tetra minor and this is the way that the tetra- change randomly and we set collided to false like so we also have to import the you scroll back up here and use callback is a standard react hook and the last thing we have to do for now is also return or update player position or update player posts and or reset player and this should be it now so it's still working but nothing happens here because we're not drawing anything to the stage now and that's what we're going to be doing now so let's go into our do stage dot J's file or you staged custom hook and this one is going to be a little maybe complicated but I hope we will get through it and that's the thing with game making because as I said I'm not the game maker so yeah some stuff can be hard to understand when you're not a game maker but even if you don't understand everything that's game specific I hope you will learn some stuff in react okay so let's continue in this one we're going to take in our player and reset player as our parameters for this one so add these ones up here then we're going to use the hook that's called use effect Nats one is for creating side effects with react and it's kind of a replacement for the life cycle methods in the class components I won't go into detail with every hook here so you have to look up that yourself if you don't know how use affect works and what is for they have an excellent the text on the react homepage where you can read about all the hooks alright so we create our use effect and that one is going to have an inline error function where we're going to create everything for our effect and this is the dependency array for now we can just leave it empty we create another function inside of here that's called update stage we're going to give it the prep stage the previous stage and below here we're going to set the state of the stage with this function so we have the stage state here and we set it with the set stage so set stage and then we have our update function so we grab the previous stage state it's easy to be confused here with stage and state it's almost the same saying that so we call or update stage in our previous state and you can also see that we're placing this function inside of the use effect and by doing this we don't have to specify it as a dependency here so we can have it inside of this effect all right and now we have to do so things here because when we update the stage we first have to flush the stage we have to kind of clear it from the previous render so we create the Const with a new stage we take a previous stage of prep stage and we met through it so we get our role and we have an inline function here and we make another map on a row because this is a multi-dimensional array so we have to do two maps here it will probably be a little bit faster if we do this with just four loops but I think we will be fine here using map but if you care a lot about performance you shouldn't use map I think in a game like this you should use the for loop because that will be faster than the map all right so we have a row we've mapped over a row and then we get our cell and we're going to return on new cell value and here we're going to make use of the one I talked about here where we create the stage where we set it to clear or merged so I'll show you that now we create the Turner operator here we have a cell value we check the value in our cell array and I will go back to this again to make it as clear as I can it's this value here we're grabbing so we simply check if that one is set to clear clear then we are going to return an empty cell so we return an array with a zero and clear otherwise we are just going to return the cell and this is what I've been talking about before because if we haven't marked our cell - merged then we just swipe it out we just clear it and we return a fresh clear cell here otherwise we return the cell as it is and it will stay in the stage so that's the way we know what cells have collided tetraman in them or not so we have flushed the stage here then draw the tetromino so we flush the stage remove everything that shouldn't be there and then we draw the new stage for this render and we can do that by loop through our tetra minor and we have our tetra minor in our player if we check or use player we created the state here so we have the tetra Milo here it's in the object for the player and in our Tetris we are sending in the player to the u stage and we getting it here so that's why we can access the player in a real stage custom hook so we have our player and the tetra minor property for each we're not going to return a new one here we're just going to simply loop through it we have a row and we have Y value curly braces then we're going to map through a row because this one is also a multi-dimensional array so it's unfortunately a lot of loops here when doing this we have our value and our x value for that one and we have an array in line function it may be a lot to grasp now when you just typing it in like this so I suggest again you stop and just try to really understand what we're doing here because now we're looping through or tetra minor and now we're going to check which cells in the tetra minor that are occupied and that way we know the shape of the tetromino we have our value here for a tetra minor for our cell in the tetra mono so we can check if the value isn't 0 then we know that we're on a cell that makes up the shape of this tetra minor and then we also know how we can position the tetra minor on the stage we have our new stage up here that we flushed it's a fresh stage that we can use to draw or tetra minor so we have a new stage and yet this is a multi-dimensional array so we have to set the y and x value for this one first we have a rose that's our Y value so we have the Y value plus player force dot y then we have our x value plus layer force dot X this will give us the coordinates on the stage so we are going to set these ones to the value and the value here remember that it's the tetromino that we looping through so we get the value of the tetromino and in this case it's going to be yeah one of these values here let's go back to our u stage so that's of value and then we're going to do back ticks here two of them and inside we have a dollar sign in curly braces because we're going to check with the Turner operator if our player is collided then we set this one to merged otherwise we set it to clear and this is yet again how we know that we should clear this tetromino in the next render if we set it too much we know it has collided and this one when we flush the stage before we do this it will be set to merged and that way we know that we should keep it in the stage because it has collided otherwise it's set to clear and then we can just delete it in the next render before we do anything else all right this is beginning to be a long video sorry for that but we have to do this and inside our function here make sure you're in the right scope here inside or update stage function we are returning the new stage for now because we're not checking any collisions yet we're going to return to this one and as you can see here when I order for married this one it has filled in this itself these are the dependencies that we need for this use effect so we have the play not collided the plane or post attacks player dot postdoc Y and player dot tetromino we're using them inside of this use effect and that's why we have to specify them as dependencies here and we are going to use the reset player that we wrapped in our use call back later so that's why we have wrapped it because we're going to add it as a dependency to this one and it's this use effect that will go into an infinite loop if we don't wrap it in a use call back alright save this one and as you can see we have a tetra minor here now and that's great and if we reload this one we get a different tetra mono because we have randomized them and that's working great and is this working no okay let's check that out in our tab trees all right I see here it shouldn't be unclick it should be called back because if we look in our Start button we have the prop here that's called call back so make sure you're in the Tetris component and change this one to call back and I bet it will work now and it does and I think I saw a little bug there yeah it disappears and I think it is it's probably when we get the same tetromino as before and I think that is if we go into the youth stage custom hook we have these dependencies here so when we get the exact same tetra mono it won't rerender because this one is dependent of the collider the position X the position Y and the tetra mono so they are going to be the exact same in the next render if we get the same tetra mono and that's not good I think we can just change the dependency to player and save this one make sure you reload it it's working great now I don't think this will give us any trouble in the future so I haven't seen this bug actually before I think it had gone through everything but yeah that's the thing with code you always get surprised I think it will be fine to have the player there otherwise we'll change it later and I also saw some little other stuff here we have to adjust because when you start the game you don't want this one to show up here before we have pushed the start button and that's why I created in this file tetra- I created this zero here with just a blank little cell here and that's the one we're going to use for this now so if we go back into our use stage now into our news player you can see that we are just rendering a random tetromino here and that's not good if we import our tetra- also here then we can just grab the tetra mono and we grab the first one in the array tetra minor tetra - and we save it and as you can see now the stage is blank here and that's good and if we push the start it will generate a random tetromino for us to start with and of course also we have created the movement for this one so if you press left and right and the down button we can actually move the tetra minor now and as you can see we have not done any collision detection yet so it will screw up here but that's fine for now we will fix that later but at least the controls are working and that's also great so we have something here now we are getting somewhere and we will continue this one in the next video it's time to create some collision detection now for our game because now it isn't working here we can move outside the play field and it looks kind of screwed up here and that's not what we want so let's go back into our code and we're going to be working in the game helpers J is file for now that's where we're going to place the collision detection function it made sense for me to place it in that file but if you feel that you want to place it somewhere else you can do that of course but for this tutorial I'm going to create it here so make sure you in the game helpers dot JS file and we have to think about a few things before we create this function one of them is that it's probably better to use for loops because it will be at least a little bit faster than to use for example map or for each because we are going to loop through or tetra minor here again and we're going to have two loops for this one also so if we use for example for each we can't break out of that one and that's the downside for us because we want to break out of the loop as soon as we collide with anything so feel free if you want to experiment with this and try different ways of doing it I'm going to use for loops so we can start by creating or function now we need to export this one because we're using it in the components so we need to have an export Const and we call it check collision we give it a player the stage and we give it an object where we can the structure out the move X and the move Y so what I'm doing here is that I rename the X and y to move X and to move Y and that's because I'm going to use Y and X in my loops so I want to have a different name for these parameters here and it's an error function and we have curly braces so we're going to loop through or tetromino in this one so we have a for loop let y equal 0 and Y should be less than player tetromino dot length and then we just have the one plus equals one for each iteration and then in sorry we have another loop let X equal zero and X should be less than player dot tetromino and we can grab the Y value dot length and then we have the X plus equals one so we add one to this one for each iteration also and we could of course just say zero here because it doesn't matter which row we are checking a length of course the rows are the same length all right so what do we have to do here now first of all this is the tetromino we're looping through and we first have to check that we are actually on a tetra- cell and the 0 don't make up the shape of the actual tetromino so we have to check that the cell isn't 0 so we can make some comments here 1 check that we're on an actual tetra- cell like so and then we create an if statement and we check if player docked at romano and now we're grabbing a y-value and or x value from our loops and it shouldn't equal 0 right so that way we know that we're actually on a cell that make up the shape for the tetromino and we should check that cell if it collide with anything so what collisions do we have to check we make a little comment here again we need to check that our movement is inside of the game areas height that we're not moving the tetromino outside of the bottom of the stage so we can just make a comment check that or move is inside the game areas height and we can now set Y in parentheses and maybe also we shouldn't go through the bottom of the play area alright and we can actually specify the other things we're going to check before we create them so down below here create number three then we need to check that our tetra mono isn't moving outside of the game areas width check that or move is inside the game areas width and that's an X and then below here we have the fourth thing we're going to check and that is we're going to check that the cell isn't set to clear because this function will return true or false if it returned true we have obviously collided with something otherwise it's false and we haven't collided with something so if the cell is set to clear then we know that we're not colliding with anything and it will return false check that the cell we're moving to isn't set to clear because if it is clear we're not colliding all right so that's of things we have to check here we're going to do this with ashamed short-circuit whoa that was hard for me to say as I'm not natively speaking English you probably can hear that also but you have to live with it so if not staged and we grab the Y value plus player dot post dot y plus or move why we're looking into the future here you can always say like that because we're checking here if the position that we intend to move to is colliding so here we simply checking that our stages Y value actually has a value in it if it doesn't have that we know that we are outside the bottom of the stage and this will also return true because we're setting this to not with this exclamation mark so if it not find anything here in this stage row it will return true and we know that we are colliding with something and as I said we do a short circuit here so we do on or I actually don't know what these signs are called in English it's design for or in a short circuit okay then we need to check that our move is inside the game errors width so we have the exclamation mark we're checking that not why plus layer dot post dot y plus move Y and then we need to check the actual cell here so we check the X plus player dot post dot X plus move X and here it is complaining here cuz we of course need an if statement here also so wrap this in an if statement return true and we go back to this one we create another or am I going to do or fourth check here okay the fourth one we're going to check I misspell this check we are going to check if this cell is not set to clear and we can do that by typing stage and then we do the same thing here y plus player dot pause y plus move Y and then we have the cell so we have X plus player Foss dot X plus move X and then it's the second one in this array that we have to check so we type in a one here and we check that it isn't cleared like so and this one should of course be a capital y so here you have it that's everything we need for our child of simple collision detection I'll actually almost copy and paste this code from the math math method tutorial because I think this is a very simple and clever way to check the collision because with this collision detection we can detect if we're outside a stage and also if we collide with any of the tetriminos because we're looping through the Tetra minor that we have in play and check if any of the cells inside of that tetrominoes collide with any of the cells in the play field and that's how this function gets checked for everything that we want if we go outside the stage and also if we collide with another tetra minor that's merged to the stage so we save it and we see that we didn't break anything and we didn't do that and that's good we have to go inside or use stage hook and add a little collision detection here because when we have the new stage here with the new updated position we then check check if we collided like so so you can do a little if statement here if player dot collided then we just reset the player like so and it will need a new dependency here so we can add recept player because if we collide we just reset the player we move the player up to the zero Y position and the other one will stay in place where we collided because we merge it into the stage here the last thing we have to do here now is to go into our Tetris component and actually use our sheykh collision function first we have to import it from the game help us so we have our Czech collision import it there and we have to check the collision when we move the player and when the player drops so inside or move player we create an if statement and if we don't collide we send in the player the stage and the intended position we want to move to so we have an X value of direction and we have the Y set to zero because this move player function is responsible for moving the player left and right so yeah I probably should have named it something else yeah I realize that so you can change it to a more descriptive name if you want to do that then we can move this one inside of the if statement and this means that if we're not colliding with with anything we actually do the move otherwise we don't do anything here so we save it and we can see if it works we shouldn't be able to go outside the play field to the left and to the right and we can't and that's great so it will stop the Tetra monolayer because we are colliding with the sides of the stage then we have to check for collision when we drop the player so inside of the drop function we do almost the same here we check if not check collision we give it the player the stage and the intended move so we have the x value in this case it's zero and it's the y value that we're going to give of 1 because we're moving one step down each at a time and we can move this one up here inside of the if statement in this case we're going to have an else also in this case as we drop in we know that if we collide on something when we drop we also need to set the collided property to true in the player and that's because if we collide with something when we drop we know that this tetra- should be merged to the stage because it can't drop anymore so we we need to yeah merge it into the stage so we update player force we give it an x value of 0 and a y-value of 0 we're not moving anymore with you're setting the collided to true we can also inside of this else block create something when the game is over because if we're colliding and the player dot force dot y is less than 1 we know that we're colliding up here somewhere and the game should be set to game over so we can console log game over and then we're going to set game over to true and set drop time to no because we're not dropping any more so we set that a null and also up here in the start game function we can set game over to false because we're starting a new game here so it shouldn't be set to true all right we save it and see what we've got we're checking here and it's still working with a collision on the sides and if we go down here it should merge into that position in the stage and thus that's great and we can see if it will go into game over mode here when we are colliding at the top and it does also and that's really really sweet but now we have a kind of half working game it's not dropping because we haven't created it in the world and we can't rotate the player so that's what we're going to do in the next videos in this video we're going to create the rotation for the player and we're mostly going to be in the use player custom hook so make sure you're in the use player custom hook we're going to create two new functions in this one so just below our state here we can create one that's called rotate this one is going to receive a matrix and a direction so the matrix is actually going to be or tetromino so you can name it to that also if you want and of course we're going to have an equal sign and an arrow here then we're going to have another function that's called play rotate and we could actually do them in one function but I wanted to separate them out because the rotate here actually do the rotation and the play rotate are going to do some other things also because we need to check the collision here when we rotate the Tetra minor that's why I separate them into two functions so we have the cost play rotate equals it is going to take in the stage and direction and we create an arrow function and as I said before you can of course create regular functions if you want it's just me that yeah I like to create arrow functions instead but if it makes more sense for you to create a regular function you can do that also it doesn't matter here okay so first we create a rotate function and that's the one that's going to take in the Tetra minor and the direction and we want to rotate the Tetra minor and how can we rotate the Tetra minor yeah first of all we can make all the rows to become columns instead so we kind of shift them in the array and that way all the rows are going to be columns instead and then if we reverse all of the values in the rows we get the rotation so that is how this is going to work so first make the rose to become calls now we can call it this transpose okay we create a new Coast we can call it rotate the tetra all right so we take our matrix we mapped that one we're not going to use the actual value in this loop but we need the index then we map through the matrix again and we have the column and we return the call and the index and this one will make all the rows in the array to become columns so that's the first step in rotating then we need to reverse each row to get a rotated matrix or a tetromino in this case and this one we have to separate into two things because it depends on which direction we are moving how we do this if we move with the direction of value that's bigger than zero we know that we're moving kind of clockwise then we need to reverse all of the rows to get the rotation right otherwise if we move in the other direction if it's for example minus one it's less than zero then we just reverse the complete matrix or in this case the rotated Tetro as we call it I know that this can seem a little bit too much and I think this is one of the thing again with game making you do this stuff all the time when you rotate things I actually had to think about this twice or three or four times before I got it myself and he explained it quite good in the math math methods video on how he rotate things I don't do it exactly the same here in this function but the principle is the same we have transposed or array or matrix or tetromino and we have converted all or rows into columns and we save them in the rotated Tetro then we can check if the direction is bigger than 0 we return or rotated the Tetra that we're going to map and we have the row and all of the rows are going to be reversed for this one so we use the reverse function on this row and that's a built-in function in JavaScript otherwise we're moving in the other direction so we can just return the rotated petrol dot reverse okay now we can create or play rotate where we're also going to do some collision detection when we rotate the player and I'm going to show you why in a second but first as always we don't want to mutate or state or anything so we create a copy of our player we can call it cloned player we cannot do a shallow copy here so we need to make kind of a deep clone and you can do that with Jason dot force and JSON dot stringify layer so now we get a complete copy a complete clone of our player and that's good we don't have to work with the player that's in the state because we shouldn't mutate the state then we take a cloned layer and grab the tetromino from that one and we use a rotate function and we rotate the cloned layer dot tetromino and we give it the direction also and this will rotate the player and we can set the player to the cloned player we also need to export our functions here or actually it's just a player rotate we need to export we will get back to this in a second but first we have to actually create the rotation in the tetris component first of all we need to add the player rotate here so we get it inside our tetris component from the use player we're also returning this one then below here in our move function where we check the key code on what key is pressed and call a function we also need to add another elsif here so if the keycode equals to 38 that's the up error on the keyboard we call play rotate give it the stage and one because we are going to need a stage when we do the collision detection in a minute and this is the direction we're sending in so we're rotating it clockwise and this means that we have a functional that we can rotate counterclockwise also so if you want you can add another key here that will rotate the Tetra minor in the opposite direction that's very easy to implement if you want to do that I kind of play Tetris with just rotating it with one key so I choose to not implement two keys for rotating in different directions here all right let's see if this works and it does that's nice but if we go to this side here you can see if we rotate it it will rotate outside of the stage and that's no good and it will break it as you see here but it's rotating nicely we're going to fix this thing now so it can't rotate outside of the stage so go back into our code and inside our use player custom hook and inside the player rotate function we're going to continue write some code here that will solve this problem for us and this one I actually grabbed it directly from the math math method tutorial cause I think it's very clever how he does this so this code is straight from that one first we want to save or position in a Const so we have composts equals cloned player dot post dot X so that's the x position we save here then we're going to create a new left that we call offset and that equals 1 then we're going to have a while loop so we have while and inside a while we check collision we send in the clone player the stage we're not moving it anywhere so we just give it zero values in this object here with the X&Y we already import to the shack coalition up here so we don't have to do that again and now we're going to write some tricky code here actually and I'll try to explain it for you if we go back into our game and try to show you here so let's just place a few of the tetra- here and I try to explain it if we rotate this one here as you can see it will move inside of these tetra- and that's no good and this little function we're going to write now is going to take wait I'm going to create another one here it's going to take the Tetra minor when we rotate it and move it right and left and right and left and check if we collide with something and that's the clever little function that he came up with in that tutorial let's say we go right it will check or we colliding no then we go left or we colliding there no and then it will continue until we collide or if we don't collide we can actually rotate the player so that is how this is going to work in this while loop so we have our clone player we set the position dot x + equals the offset and this is how we keep track on how many steps we're moving to the side back and forth so we set the offset it equals to minus parenthesis offset plus the offset if it's greater than zero we set it to 1 otherwise we set it to minus 1 and it's this little row here that will create the kind of back and forth movement for us with the tetromino then we can create an if statement and we check if the offset is greater than clone player dot tetromino and we grab the first value in the array and length here we're just grabbing the first row and check the length of that one we don't need to do any more check here because we have looked through the complete length of the taproom then we just rotate the Tetra minor back because this move isn't allowed we can't rotate it if we have tried this back and forth more than the width of the Tetra minor then we know that we can't rotate so we just rotate it back because we already rotated it up here so we just rotate it back rotate loan player dot tetromino and minus direction we reverse the direction so we rotate it back every septic loan player dot post dot X 2 equals position and that's the one we set up here because we want it to have the same position as we had from the beginning and then we just return so this is see a quite a handful of a function I don't blame you if you don't get it especially this one it can seem a little bit tricky it took some thinking for me to understand this just think of it as this one will go back and forth and see if it collide with something when we rotate and if we do we can't rotate it that way and it will constantly move it away from that one when we rotate so we can save it and see if it works we can try this out if we rotate it now you can see that it kind of pops out from the wall it won't go through it and also if we do some rotating here it can't rotate through them and that's good so I actually think that this is the most advanced function in this tutorial because this is quite advanced don't blame yourself if you don't get it the first time just try out yourself try to change the code try to look at it read it try and change it again and you will soon get it how it works if you don't get it right away and if you get it right away well good for you and see you in the next video okay we have a kind of a functioning tetris game here just a few things left to do if we take a look here we see that we have some full rows here and they should be swept off the stage and it should give us some score at the end but it won't do that now because yeah we can just fill this up and nothing will happen in this video we will create the function that will kind of sweep the stage and see if there's any rows that needs to be cleared and also push down the other ones that shouldn't be cleared so that said go into our code again and into our u stage custom hook inside of this custom hook we first going to create another state so we create a state here that's called rows cleared and set rows cleared and this is how we're going to keep track of all the rows that we have cleared so we use state and give it an initial value of 0 okay and the first thing we want to do in this use effect is to set rows cleared to 0 then we're going to create another function here that's called sweep rows we're going to give it a new stage to sweep and it's going to be an implicit return for this one so we don't have to have curly braces we grab a new stage and we're going to do some reducing here so reduce this is the built-in reduce es6 function we have the accumulator at the row arrow function curly braces so we give this function a stage and we're going to map through it with reduce so we do that with new stage reduce and we get the row and accumulator if you don't know how reduce works I suggest you look it up and the first thing we have to do now is to check if our row just contains cells that are merged and that means that we can check if a row don't contain zeros and we can do that we'd find index so if row find index we have our cell and an inline function we check if the first value in our cell array equals to zero and if this one equals to minus one we know that we haven't found a value of zero and then we know that this is a full row and should be clear because fine index will return minus one if it don't find a match with the provided function inside of it if we're looking for the value zero and it won't find that one then it will return minus one and then we know that this role should be swept away from the stage so we first set rows cleared and we do that with an update the function because we're going to need the previous value and we just add one to that one then we're going to grab the accumulator that's the new array we're building up inside of this reduced function we're going to unshift an unshift let us add a new value to the array at the beginning of the array because if we look here if we for example remove these three rows here we need to add three rows at the top and we can do that with the unshift method so we remove these three ones here and if we add three empty ones up here it will push down the other ones and it will try to create the illusion that this one's just yeah pop out of the stage and disappear so with on shift we can add a complete empty row at the beginning of the array so we create a new array from our new stage zero dot length that will give us the width of the actual play field and we fill it up with an array of zeros and clear because these ones are completely fresh so this should be a zero and clear then for each iteration inside our reduced we have to return the accumulator also and this is if we find a matching row that should be cleared if we don't do that we just push the row into the accumulated array and we return the accumulator again like this and we could also give it an empty array to start with so this is the complete function here I will go through it again and tell you what it will do we give this function or stage and we take the complete stage and use the reduce method on this one by using reduce we can create a new array so we check if the row contains any zero if it does we know that this row shouldn't be clear because we haven't filled up a complete row but if we have filled up a complete row we first add a row to a rows cleared state then we add an empty a complete empty a new row at the top of the array and we return the accumulated array this works because we completely ignored to return the full row that we should remove from the stage and instead we return a new empty row at the top of the array so this will create the illusion that we remove the row on the stage and move the other ones down that was above that row and if we don't have a full row we just return the row as as it is in the array and that's the way it works we have to use this function somewhere and we can do it if we know that we collide with something we should do this sweep and see if we also have a full row so below the reset player and because this one returns a complete new stage we also need to return the function and give it the new stage so this one will take or stage we create here when we have done all the mapping with the tetromino and everything and if it collides then we call the sweep rows with this stage and this one in turn will return another stage for us when it has swept all the rows and check that there is no full row that needs to be removed from the stage okay so we'll see if it works I have to do some gaming here to get a full row and that's nice to be able to play some game here let's see if it works and it does nice it's kind of easy now when it's not dropping yeah and we know that it works now so I don't have to create another row here and we actually forgot to do something here and go back into our code and interview stage custom hook we also need to return or rows cleared because we're going to use this one in the Tetris component later on so make sure you add that one to the return statement here alright so that's it we'll continue by creating the interval for the petrol miners to drop by themselves in the next video we are going to set this game in motion and I think it's better we take a look at Dan Abramov site first overacted dot IO and then he has a blog post that's called making setting develop declarative with react hooks and it's 16 minutes read so I won't go through it here but I suggest you read this one because here he explained why it isn't a good idea to just use set interval with react hooks so he has created this custom hook that's called use interval that we are going to use and hopefully you copy this file over to your project folder as I showed you in the beginning of this tutorial here's all the answers to why setting the world is not good to use as it is we dragged hooks it's better to create a custom hook and use that one instead and one thing Y is not so great is because react hooks are heavily using closures and closures can be quite difficult to grasp if you're not that used to them he has created this use in well for us that we can just use in our game and that's what we're going to do now so back to our app and our code inside of our Tetris component we're going to be in that component in this video at the beginning here where we import our custom hooks we can import our use in a well from dot dot forward slash hooks and use in eval and that makes sure that we can use this one inside of our component ok and now we're going to make this one move by itself because now we can just drop it by pressing the down key on our keyboard and that's no good we want it to move by itself so we can set up this interval and below I think yeah here somewhere we can use our interval so use in a well and this one will take an inline function so we create an error function and we are going to call the drop function as we created up here because that's the one that makes the tetrominoes drop so we call that one and we can specify the interval timing here and we already have a state that's called drop time so we just send this one in to the use in a well because if we look at the use in eval it will take a callback and a delay and the callback is the inline function we created and the delay is our drop time so that's how this works and also if we set null into the drop time it will stop and clear the interval so that's good for us because that way we can control the interval all right back to the tetris component we have to do a few more things here to get it up and running because now our drop time is set to null we set it up here so now the interval is not active but we have a start button so when we start our game we can set our drop time and we send in thousand that means one second and we save it and then if we press start game as you can see it's moving really good here now and that's nice because now we have a working Tetris game great I want to do a few optimizations here also we created one extra function here that's called drop player inside now we just call him drop and that's when we press the down key on our keyboard I want to stop the interval when the player moves the Tetra minor down with the keyboard and that's easy we can just set the drop time to null and that will make sure that we stop the interval but we also have to activate it again when the play releases the down key so we're going to create a new function here that's called key up and inside of these we're going to take in the key code again so with the structure that out from our event and yet again we're going to check if the game is not game over and we can activate the interval again when the player release the down key so inside of here we check if the key code equals 240 that is the down key we will only run this if the player is releasing the down key then we set the drop time for now we just set it to thousand again we are going to create different speeds here later in the next video so that's a callback function for our key up event and we also have to make sure that we have this event here and we can create it on our style Tetris wrapper so we just add on key up and it equals key up and a little nice formatting here and we save this one and we can actually do a little console logging here because here we can console.log in the off and we copy this one and go to yup console on interval on make sure you're showing your console here whoops I misspell this one yeah my formatting here has added this one for us yeah that's nice so I can remove this one it should only be used in eval here okay so we start the game and I press the down button you can see that in eval off and then in eval on when we release the button and that's great because then it will not interfere with the keyboard when we hold the key down it will repeat itself and make the Tetra miner go down faster and that could mess things up for us if the interval also is activated them so that's actually all there is to it to create this movement this kind of game loop that makes the Tetra mono drop by itself in the next video I'm going to conclude this tutorial and we create some nice little displays here with score and rows and level and we're going to do that by create our last custom hooked we're almost finished now we're just going to create our custom hook for displaying scores rows and levels and we are eventually going to import it here in the Tetris component with the other hooks here but we will create it first so we have something to import here so inside our hooks folder create a new file that's called use game status doc yes are we going to need a few things here so we import you stay use effect and use call back from react then we export post use game status and we're going to need one parameter here that's called rows cleared that's the one we created in our youth stage we're going to send this one in to a use game status because we need it when we calculate our score and set the total rows that we cleared because this one here is just the rows that we cleared in the current render that's why we set it to zero here so we clear it on each render and then we're going to send this one in to the use game status where we can add it up to the rows we already have cleared before all right we have an error function and curly braces and then we're going to create three states here so we have a cost with the structure out score set score equals you stayed and we have a zero you can just copy this one paste it two times and we're going to call this one rose and set Rose ever going to initialize all of these with a zero and we have our level and/or set level so there you have it three states then we going to need a cost that's called line points and this is going to be an array with 40 hundred three hundred and twelve hundred and these are the actual scores I did some googling and found the scores from the original tetris game so we're going to use these to calculate or total score I don't know there's probably a lot of different versions so I don't know if this is legit that it's truly the original scores that we used and also the formula for calculating the score but I found this one I think it was on Wikipedia actually so you can have what scoring you want here if you want to change it so we have a cost that's called calc score and this is a function we're creating here because we're going to call this function in a use effect and we also going to need a use callback because otherwise this will go into an infinite loop and that's no good and I think that's also not a problem but I think it can be annoying because it's easy with react books to make them go into an infinite loop if you don't think about that very very thoroughly okay so first we're going to check if we have score if Rose cleared is greater than zero that means if we cleared any rows in the render that's the one with Sun in here because if it's zero we didn't clear any row so don't have any score calculations to do and that means that if this one is greater than zero we know that we cleared some rows and we're going to calculate the score and if it's zero yeah we know that we didn't hear any rows in this render and we don't need to calculate any score we are going to calculate a score and set our total rows so I create the comment here this is how original Tetra score is calculated so this is the formula I use I found that one on the internet and I'm using that here to calculate the score so we just set our score state set score we have a previous state and we use that previous state to add something to it and here's the formula we have the line points that's the array up here and this line points array have four different values here and they each represent one row cleared two rows three heroes cleared and four rows cleared and this is an array so the index starts at zero so we have to take a rose clear minus one because say for example that we cleared two rows we need to grab the value with index one in our array and we're going to multiply that with or level plus one and that's also because our level starts at zero so that's why we're adding one here so this is the formula to calculate a score and then we also need to set our rows where our previous stayed here and we take the previous state and add the new rows cleared to that one and that will always keep track of our total rows that we cleared all right and as this is a used cool back we have to make it depend on something so we have the dependency array here we have the level the line points and the rows cleared so this one is always going to change when the level line points or rows cleared or changing otherwise it will stay the same and that's why it won't go into an infinite loop because if we didn't have this used callback it will change every render and that will create the infinity loop okay and then we create a use affect we want this to fire off automatically and this dependency array is going to depend on the calculate score the rows cleared and the score we just calling the calc score here and as we using these ones in this function we have to specify them as dependencies here but then we have to return something from this custom hooked so there's a lot of things we're going to return e we want to score we want a set score because we want to reset the score when we start a new game we need two rows and we also need a set rows we want to set the rows to zero when we start a new game and also the same with the level so want a level and the set level like so so we save this one and go back into our Tetris component we import it where we import our other custom looks use game status from dot forward slash cooks use game status all right then we have to use this values inside of a Tetris component but first we have to call or use game status hooked we can do that below here so we have a Const and we are going to receive everything that we returned from this one all of these here we're going to receive here so we have to specify them we have the score set score rose set rose level and set level and we're going to call or use game status and we're sending in the rose cleared as we talked about before and of course we also have to grab the Rose cleared here from our youth stage hook see if I can make it a little bigger here I think we actually can move this one down here to make it a little nicer looking like so okay and now we have to use these values inside of our tetris component first in our drop function we want to change the level depending on how many rows we have cleared and that means we have to have something here that calculates that on every drop so I make a little comment here increase level one player has cleared ten rows I think that that also is the original Tetris but I'm not sure when you clear ten rows then we go up a level and the speed will increase we create a little if statement here we check if the rows are greater than level +1 that's because the level starts at zero just as before times 10 we set the level with our previous state and we just have the previous plus 1 we just increasing the level by 1 and we also want to increase the speed and this little formula I created here I don't know if it's optimal actually I'm going to set the drop time like so and then I have thousand that's one second I divide it with the level plus one and then I just added 200 here so it will not get too fast and you can actually play with this and try another formula and see if it works better for you so I don't know if it's good I think yeah it's working fairly nice but yeah probably there will be a better formula for this to use so that's how we calculate our level we can actually also set a few things here when we start again because we also want to reset our score level and rows so we can set our score to 0 set rows to 0 and we set our level to 0 when there's one more thing we have to do here we are going to take this formula here and copy that in the drop function where we set the drop time we have to also paste that in our key up function because now we're just setting it two thousand here so just paste it in there and we want to display or score rows and levels also so we can change these ones inside other probes we're sending in to the display components to recreate curly braces double ticks and we have our score and a dollar sign and curly braces and we grab our score then we do the same with the rows and the levels we can copy this one paste and then we change this once we have a rose and we have our level so this will make sure that we display the score rose and level and I think it's time to say this one and see if it works so it's already displaying the series here so we can start the game and it seems to be working nice so that's it we have a working Tetris game I just want to make a little optimization here and I'm going to show you why because if we go inside our cell component and for now I have to do like this because I want to console.log something out we render so what I'm doing here I'm just going to transfer logout rerender on each cell here so I save this one and as you can see we have 240 around us here and that's fine when we build this table for the first time but as you can see on each little drop here now on each rotation and everything we get 240 renders it probably won't be an issue here because react is fast but I want to show you here how you can create a little optimization for this one so we go back inside our cell component and where we export this one we're going to export it with react memo and this will make sure that it memorizes this cell component and only remembers when the cells actually are changing so we save this one and as you can see we just remembering the cells that actually change with the Tetra minor now and I actually think that this is a really good example to show you what react memo does in react because now it won't affect the cells that won't change on that render it will only remember the cells that change with the tetromino and that's good so we made quite an optimization here and reduce the renders here and that's good there you have it this is my this is my version of Tetris with react hooks and as I said a couple of times now I am NOT a game developer but it was sure fun to create this game and I think it's a good practice in react and especially react hooks to see how they work and I hope you enjoyed this one as much as I did and I'm grateful that you have followed me on this tutorial and I hope you learn a lot I initially created this one exclusively for free code camp and I actually record a lot of free stuff especially in react and fronting and stuff like that in my own YouTube channel so if we go to youtube and just search for vibe on 5w e ib e-m-f ALK you will see my pretty face here and you can just go to my channel and make sure you subscribe if you want free coding tips in react and other front-end stuff and i also create paid premium courses i'm going to move them to my own platform soon but for now they're up on udemy and it's a beginner react course and also course in Gatsby and how to create get besides with WordPress as a headless CMS this also free course on react Redux and this of course the hooks introduction course that were published on free code camp a little while ago and I'm also on Twitter just hooked me up there if you have any questions or just want to follow me there and I sure appreciate the support I can get from you I want to continue to create free stuff and do things like this so hopefully you'll see me again in another video but for now thank you and goodbye
Info
Channel: freeCodeCamp.org
Views: 104,560
Rating: 4.9417257 out of 5
Keywords: react, react tutorial, react course, react tutorial for beginners, reactjs, tetris, hooks, React.memo, useEffect, useState, useCallback, programming, web development, development, tech, react hooks, react hooks tutorial, react hooks course
Id: ZGOaCxX8HIU
Channel Id: undefined
Length: 154min 18sec (9258 seconds)
Published: Wed Aug 14 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.