Coding

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

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