Multiplayer TicTacToe Game using Flutter, Socket and MongoDB | Rahul Agarwal | Skillshare
Search

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Multiplayer TicTacToe Game using Flutter, Socket and MongoDB

teacher avatar Rahul Agarwal, Flutter Developer & Trainer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Course Introduction

      0:49

    • 2.

      Create a new Project

      8:34

    • 3.

      Work on Main Menu UI

      7:23

    • 4.

      Work on Responsiveness

      4:12

    • 5.

      Register Named Routes

      4:45

    • 6.

      Custom Reusable Widgets

      7:18

    • 7.

      Create and Join Game UI

      10:11

    • 8.

      Setting up a Node Project

      9:08

    • 9.

      Create an Express Server

      6:54

    • 10.

      Setup MongoDB Atlas

      8:00

    • 11.

      Install Socket IO Client

      7:26

    • 12.

      Socket Method Class

      4:34

    • 13.

      Socket Server Connection

      5:10

    • 14.

      Creating Room Model

      12:50

    • 15.

      Work on CreateRoom Event

      9:02

    • 16.

      Room Success Event Listener

      7:09

    • 17.

      Room Provider Class

      6:54

    • 18.

      Join Room Listener

      8:56

    • 19.

      Work on Join Success Event

      10:50

    • 20.

      Player Dart Model Class

      7:41

    • 21.

      Player State in Provider

      9:23

    • 22.

      Work on Waiting Lobby

      7:04

    • 23.

      Listen to UpdateRoom Event

      6:22

    • 24.

      Work on Scoreboard

      7:55

    • 25.

      Create the board UI

      5:54

    • 26.

      Keep track of game values

      10:04

    • 27.

      Displaying X and O

      9:28

    • 28.

      Playing according to turns

      7:25

    • 29.

      Check Winner of the Game

      10:53

    • 30.

      Display Winner in DialogBox

      7:32

    • 31.

      Play Again Functionality

      11:02

    • 32.

      Listen to Winner Event

      5:05

    • 33.

      Listen to EndGame Event

      6:45

    • 34.

      Test the Complete Application

      4:41

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

3

Students

--

Project

About This Class

In a world where digital connections are more important than ever, how about building something fun and engaging? Introducing 'Build a Multiplayer Tic Tac Toe Game using Flutter, Socket, and MongoDB.

Imagine the thrill of challenging your friends, family, or even players from around the globe to a game of Tic Tac Toe. With this course, you'll learn how to leverage Flutter's powerful framework, Socket io's seamless real-time communication, MongoDB's flexible database, and Provider state management to create an immersive multiplayer gaming experience.

Whether you're a beginner or an experienced developer looking to expand your skills, this will guide you through every stage of the development process. We'll start with the configuration of Flutter and Node js, ensuring you have a solid foundation. Then, we'll dive into Socket io to establish real-time connections and sync game data effortlessly. But that's not all!  You will understand how to build your own custom backend, giving you full control and flexibility over your game's functionality. No more relying on Firebase alone.

Upon completing this course, you'll have all the skills necessary to develop your own multiplayer games with build custom backends. You'll be equipped with the ability to create memorable experiences and entertain people worldwide. So without wasting any more  time, let's get started on this exciting adventure together!

Meet Your Teacher

Teacher Profile Image

Rahul Agarwal

Flutter Developer & Trainer

Teacher

Hello, I'm Rahul. I am skilled in building cross platform application using Flutter. I am freelance developer as well as conduct workshops to share my knowledge with the community.

See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Course Introduction: Are you ready to unleash your creativity and bring people together through the power of technology? Look no further. This comprehensive course offers everything you need to become a skilled flutter developer. Imagine the thrill of challenging your friends and family to a game of detecto. With this course, you will learn how to leverage latter's powerful framework, Sake Do Ao seamless real time communication, Mongo Davis flexible database, and provide the state management to create an immerse safe multiplayer gaming experience. You will understand how to build your own custom back and giving you full control and flexibility over your data. That means no more relying on fireway all the time. Whether you are a beginner or an experienced developer looking to expand your skills, this course is designed for you. So without wasting any more time enroll now and let's get started. 2. Create a new Project: Hi. Welcome to the very first video of the course, where we will learn how to build a multipletic techo application using platter, no Js, Mongo DV, and socket D IO. When it comes to building rail world application or any serious start up, big companies prefer custom backends rather than firebase because obviously, it is cost effective, as well as there is no issue of vendor lock in. So In your skill share, you must know how to build your own back end. You should not rely only on fire base. So in this course, obviously, you will learn everything by the end and hence can work for any big companies or startups. So let's get started. Now, the first thing we will do is create a new flutter project. I'm assuming that you have already installed flutter S DC in your system. So simply go to your desired directory. And then a terminal and write the command flutter, create tack tacto. So I'm giving the project name this. Obviously, you can give it anything you want. Also, I would like to show you what flutter version I am using because obviously, every after few weeks, they are releasing some kind of updates. I am using flutter 3.10 0.1. So make sure you use this or if there is any breaking changes in the future, you must adapt to it. So, this is the project. Now, open it in VS code. Simply open folder. Letter cos and tto. First thing we can do is we will structure our application in an organized manner. So inside folder, create three new folders, such as screens, badges and utils. Obviously, I hope you know all the basics of platter, that is what does p spect that Yamal does. What is the use of main function? Because this course is not for the beginners. You must have basic understanding of platter and as well. Then inside screens, create a new screen know as main menu screen. This will be the starting screen. When the user opens our application, this screen will be shown to him. Let's material then create a state less rigid here. And. And name it main menu screen. Just for now, give it a scaffold and in the body, give a visit and in the write me. Inside utils folder, create a new file known as Colors do Dart. This file will usually contain all the colors of your application. But in our app, we will have only one color, so simply first of all import material. And write constant BG color is background color, is equal to color from RGB O then 161334, and give opacity as one. This is just a color, nothing else. Se it's a shade of black color. Obviously, if you want, you can change the background color of a game. Now, in the main do dirt file, first of all, remove this comment. It doesn't look good. Then below the M app, that is this homepage, remove everything from the line 23 till the end. And then here in the home make our main menu screen as the home page, then let's change this title to tick tack tack to tick. T to then Debug banner is the falls. Theme should be theme theta dark do copywed. I will use the dark theme with these properties, and here I will add sca background color as BG color. That is, I want the background color to be black. Now, I will use a android simulator And here, also, I will just change the app names. I guess the app name is Ditto. It shouldn't be an issue. We have Android app source main. Yeah, Ditto is it's fine. So simply start debugging. Let is run your application. This is the first time though it might take some time. Also, it depends upon your system as well. So the app is running and see our main menu screen is there. So that's it for this video. In the next video, we will work on the I of the main menu. Thank you. 3. Work on Main Menu UI: Hi, welcome back. So what I want is in the main menu, there should be two buttons. One to create a game that is create a room and second, join game room. So let's create a separate custom widget part button so that we can use it at multiple places. So simply Inside widgets folder, create a new file custom button dart and import material and stateless widget, make it a stateless widget and write custom button. In a button, we need the text, that is what should be written in the button, as well as the function that it will execute. Let's take these arguments in the constructor. Write final that is void cab on tap. And final string text. Now, this void call back simply means a function, but it doesn't return anything because if you write here function, then also it's fine. But since we know that we won't be returning anything, so I'm using void call back. Now here, make the properties required which is this on tap, re this dot text. Now here, return and elevated button. In the press property, we will give the ont function. And in the child. We will give text as that text property and give some styling to it. Text style size at 16. Also, we will give a minimum size to the button. For that, first of all, let's get the size of the screen media query. Dot of context do size wd. With this, we get the size of the screen. Here below the press, I will simply write style elevated button style from minimum size would be size gid width will be the width and height make it 50. So it will take the complete wit, which we will change later on. That is, we will give some responsiveness as well. But this is our custom button. We have, everything is fine, I believe. Okay. Now let's go to our main menu screen. Here, we will create two buttons to allow user to create or either join a game room. So first of or at the very top, I will give this screen a route name. That is static string route name is a go main menu. So we will be using name routes. That's why I'm writing the routes here so that it is not confusing, and we can simply call this route name without creating an instance since it is a static variable. Now here, remove the center git and give a column. Column main axis alignment, main axis alignment center then children. First thing will be a custom button, our own, which we created. On tab will be empty for now. We will work on it later, first one will we create. Then Inside the children, give you a comma and then write sized works. Make it size works, give some height of 20, and then again create a second custom button. See, this is how our button is useful so that we don't have to repeat our code. And here simply write join room. Let's see the UI. We have the two button. Just give some padding. Here, wrap the column with a padding here and give padding of 20 pixels. Say it is looking decent enough. So that's it for this video, see you in the next session. 4. Work on Responsiveness: Hi, welcome back. Our application is looking good in this Android emulator. But what if I try to open it in chrome as well? So let's do it. You can run the application in two devices simultaneously. So that's a good thing. Okay. O C. Here, if the app runs in web or desktop mode, then we can see that the buttons are stretched and take the whole wi, and it doesn't look good. So we will create a responsive widget, which will add constraints to it. Let's work on that. Create a new folder inside inside ib, and name it s onsive. And then inside it write responsive dot dart. Import material and create a state gid name is. This gid will accept a child, which will be a gid property data type, and here simply required this do child, and here in the deterrent sim center Child constrained box. Here we can give constraints. Constraints will be cont box constraints. Max width would be 600 es. It should not be greater than this, if less than it's fine. And will be. Okay. So now simply wrap the column inside main menu screen here. This column simply wrap it with responsive like this. In the child, we are adding or in the child, we have this column git. Let's save it. Let's see which one is getting saved. I'm not sure. Yeah, S. So in the Android emulator, it is looking good and also in dektop or as well as web mode, it is also looking decent. So you can change it. This is 600. You can do whatever you want. So this is how you add responses in a very basic manner. So in the next video, we will create more routes as well as registered those routes in our Main dot dot file. Thank you. 5. Register Named Routes: Fi. Now let's create screens for create room and join rope. Inside Screens folder, create a new file, and name it create room screen. And also we create a new file join room screen dot dot. Inside create room screen, simply import material. Then create a state full. Name create ro screen and simply return an empty scaffold for now, and similarly here in join screen as well. Import material, then create a state full did. Name join screen. Then return an empty scaffold gin. Empty scaffold. Also, just as we write route name in main screen, Min venue screen similarly inside create screen, we static string route name to slash create room. This is the route name and go to join room here as well, static string route name is equal to join room, like this. We have the routes. The only thing remaining is to register them in main dot file. Go to main do file here. Now Below home simply routes, then give it a map. Here it's a key value pair. Route name, and then that route name point to the screen. Simply main menu screen, route name. It redirect main menu screen. Yes, it should be paced. Similarly for create room screen, the route name. It red to create room screen. Then join room screen. It redirect to constant join room screen like this. And when we are using name routes, so we should not use this home property instead after route, simply write initial route and give it main menu screen do route like this. And then restart the application because we have changed that route. But if you as that, everything is working perfectly like before. But now we have name routes in our application. Thank you. 6. Custom Reusable Widgets: Hi. Welcome back. Similarly like custom button, let's create a custom widget for text as well. Since we will display text multiple times. So go to widgets inside widgets, create a new file text dot dot. L et's first import material, create a custom text. Here, this will be a text. Here we will return text. The first property will be what will be the string? Let's ask or accept that in the constructor. Final string text. Then we need to font size as well font size. And just for styling purpose, we will give shadows as well. List of shadows. Shadows. Now make these things required. A are required properties. Then assign them to the text. The first will be the string, then give some styling textile. Color will be colors white. Font weight, will be font weight dot bold. F size, will be the pon size which is in the constructor, and then shadows will be the shadows property like this. This is a custom widget for text. And then also, we will be using text file wigd multiple times. Let's create a custom widget for that as well. Inside wigds, simply create a new pile, and name it custom text fill dot dot import material greatest less custom text failed. Now, this will be text fails, the properties which we will be accepting are first will be it controller then final string hint text. The final B is ready. Is read only, s read only. This is a property where the user cannot edit the text field. This will be used later on. But now let's re all these things in the controller. Text required easy read only. Now here return a text fill. Controller will be read only property will be es read only. And this read only will not be required here, it will have a default value of false. So only one text res. That make it false for other text fills. And here decoration input decoration. Pill color should be background color. Field should be true. Hint text should be hint text in the constructor. This one. Now, this is fine, but I want to give some shadow effects. Simply wrap this with a container, then here give some decoration constant box decoration, then give some box shadows here. Right box shadow color colors blue blood radius S five, spread radius S two. This decoration will only give a shadow effect behind or around the text field. That's it. These were the two custom widgets I wanted to write. In the next video, we will work on the UI creating game room as well as joining game room. Thank you. 7. Create and Join Game UI: Hi, welcome back. So now let's work on the UI of Create Room screen. We will have a text widgit, then a text field, and then a button. So let's start working on it. Here within the scaffold. In the body, I will wrap it with the responsive wig from the starting because I want it to have constraints to the width. Then I will a single child scroll view then Tile will be container. Inside the container gives a margin as costs in sts dot symmetric horizontal S 20, then the child of the container will be a column, of which main axis alignment give it main axis alignment dot center, cross axis alignment, cross axis alignment dot center, then the children. Now, the first element in the children I will give is a custom text. Here, text will create room size will be 70. Shows I will be listed with only one shadow property with blur radius 40 color as colors the blue. Like this. Simply save it Now, I I I want to say because I want to go to that screen. So if I go to create button, so let's go to here. No. And then in the custom button here. Let's say navigator dot of context, do push name. I will go to create room rota If I go to C, I have the text which has the glowing effect and this is looking very good. Now again, go to the text. Sorry, to the create screen. Let's will this text. We require that custom text fill first give some size box, height will be height and we need the size property as well. At the top, create text editing controller name controller is equal to text editing controller. Then dispose this controller to dispose. Then In the build have a size property similarly like this media query dot of context dot size. And then give this size box as height size height multiply by 0.08. Then I want a custom text field. Controller will be name controller. H in text will be enter player name. Below this custom text will again give a size box. That is some spacing. Eight. This time size height, multiply by 0.05. And below eight give it custom button. On tap d t and text create. Save it and let's check out and see, our create room is looking decent. We have the proper shadows around the text field as well. Similarly like this, let's create the UI for join room as well. Simply copy and paste everything from create room. I want to wit. Let's go here. First of all, I will copy the build method. B as well as text editing controller. I will just paste everything here. Then it all the missing libraries Okay. Now in the join room, the player has to enter his name as well as the room ID. So here I will add final text editing controller, game ID controller is equal to text editing controller. Then dispose this as well. Then here, custom text will be join room custom text here, this one will be the same interplayer name, but below this custom field, give a sized box 20, make it cost below this, again create a custom text because we need two texts, Controller will be game ID controller. H text will be game ID. Then in the button, simply change it to join. Now, If I go to main menu screen, and then in the on tap of Join screen here, I will write Join screen dot route name. Okay. If I go back and click on Join Screen C, we have the Join room. It is asking for the player name as well as game ID. So both the UI is done. In the next video, we will work on the No GS server side. Thank you. 8. Setting up a Node Project: Hi, welcome back. So now it's time we work on our back end so that the room data can be saved in the database, because obviously we will Whenever we create a room, we have to save those data right. So for that, first of all, go tongs RG and download the recommended version. So I I have already downloaded it, so I will show you the website here. Simply click here according to your O S and download the No GS recommended version. And NPM will be automatically installed with no GAS. So you don't have to install it separately. And also just to check whether no JS is successfully installed or not. Simply type in the terminal node V. C, I have the version 18.15 0.0. So I'm using this version. So no GS is installed, then let's create a no GS project. Now here, I'll just show you in the root directory, that is ti teco directory, create a folder name server. And obviously, you can choose any location, but I am just creating the server inside our plate application. Remember, this server is outside the lib. Now in the terminal, simply change your location to server folded the CD server and initialize NPM by typing NPM it y. This initializes a package JS file, that is an empty NPM project. Now, we will need an entry point for our new GS server. Just like in flutter, it is the main dot dot file. So inside server folder, create a new JavaScript file called Index do GS. And also in package JCN file. You can see the main entry file by default is index do JS. You can change this name as well. That is suppose this is server DGS, then make this file server JS as well. But this is not important. Also, all the external packages that we will install will be shown in this package JS file. When talking about packages, let's install our first package. I will use Express package. Express GS is a framework that works on top of no GS web server to simplify its APIs and add helpful new features. It makes it easier to organize applications functionalities with middleware and routing. So in the terminal inside the server folder type NPM install Express. Using this command, you can install any external packages and see in the package or JCN file. Here, it's written the express dependency and all the modules related to the express packages inside the nod modules. Now the next package we will install is called node moon. So if we start the node server now, then whenever we make any changes in the code, then we have to stop the server and restart it again and again to see the update. This is not a good development experience. To solve this, we will use a package known as node moon. From the very beginning, it will allow live refresh of the server that is when we make changes and s, it will restart the server itself and reflect the changes. In the terminal, simply write NPM install G node one, and press enter. So here I am installing this using the g that is G syntax so that it is installed in your system, not only in the project, and you don't have to install it again and again. So press enter, and I already have it installed globally, so I'm not installing it again. After adding this package, we have to write a script in package JN file in this file. Here we have the script. I don't need the test script. I will write a script called Start, which will execute the code node index S, and for Dv, it will be Nd one index. So whenever we type NPM run D, then this code will execute and our server will run using the Numon package. And if you deploy this server in the C or railway app that is in the live server, then by default, this t method will be called. So there this development Nudmon won't work. The next package we want to install is bongos, we will be using Mongo DVs database to connect our N JS application. So for that purpose, we will use bongos. It will help in creating data models and store in the database and also provide CRD methods which are very easy to use. So simply again in the terminal, Rate the code, NPM, Install Mong Gos MON GOOSE. So this is also installed. Here we have express, here we have Mongo. Now the final package to install now is Socket IO. We will be using Socket IO package to establish a real time connection, which simply means that the front end will keep listening to any changes in the database and reflects it without restarting the app. In simple, you can see the Socheat IO as streams if you're coming from fire bays. Ve. In the terminal NPM install socket IO. This is the package NPM package name. That's it. We have the three packages install Express Mongo and socket dot IO. In the next video, we will start working on the API and progress it with the Mongo DB database as well. Thank you. 9. Create an Express Server: Hi. Now, the first thing we have to do is create a server. For that, we have to tell our project that we will use Express. So go to Index or JS file and import all the necessary packages. First of all, I will write constant Express to require. This is how we import packages in Java script. Then so is equal to require IO, then HTTP al to require the HTTP package. This is by default in the No JS project. We don't have to add another dependency for HTTP. Then we have to initialize express package, and we just add cost app is equal to express and this. This is the we're initializing it. Then Create server and so I. I will write server is to STP create server. And passing the express app. And then write R IO to socket, and we will pass the server to this socket. Whenever you are using socket IO, this is how you create a server. But if you're not using socket that Io, so then you don't have to write these two lines. Directly, we can do app do listen and all. Then the next code I want is a middleware. And I hope you know what is middleware. It is simply right. It manipulates manipulate data coming from client to server. So whatever data is coming from client to server, you can use Middle was to go through this Middle wa first and then hit our server. So what I want is I will use app dot use express dot JS. What does it do? It will convert all incoming data to Jasen form. So this is a required fill. You can also use a package called body parser. It's up to you. But obviously, this express dog is a process. Next, we will need a port to start our server. You can directly write 3,000 here. But if you plan to deploy this server, so simply write process env, and if it is null, then use 3,000. That is, if you deploy this server to Hiroku or any live server, then this code will be executed because this is how the No JS deployment works, and in development phase, this 3,000 this 3,000 will be the value of the port. Now, simply write server listen. We will listen to the port that is this port variable. Then Next one is the IP address. We will write 0.0 0.0, that is four zeros. And this means that the app can be accessed by everyone instead of just my own IP address. And then in the callback function, simply write console dot log Then I will use bat, that is the key in your keyboard above the tab. Button, you can find this coat that is here. We can simply concatenate string as well as variables. I will add on pot, then I will con this port variable. And save it. No. Sorry, this is not Yeah. Save it. Now to run the server in the terminal, clear it. And now here right NPM run the inside the server folder. And see the node moon has restarted, and S is running on p 3,000. And now, suppose if I make any changes and save it, the server will restart automatically. So this is the power of nodemon. So that's it for this video. See you in the next session. Thank you. 10. Setup MongoDB Atlas: Hi, welcome back. So in this video, we will work on our Mongo DB database. So first of all, I will just stop our server using Control C. Then open up your browser and go to Mo DV slash Atlas slasbase. We'll be using a Cloud database that is Atlas, then here, simply sign in or sign up with your account. I already have an account I will directly sign in, but obviously, you have to sign up for a new account. If you If you create a new account, you will be asked to give a name to your organization, and then select Wong DB Atlas option from there. So he, I have given the name of my organization as Raja G. That's it. And after that, you will be sent to this dah. You can pause the video if you want. After an organization, here, click on a new project. Then give a project name. I will name it tick tack to and click on next. Then simply click on create project. Then here we have to create a database, click on this button, build a database. Then use a template here, select. O that is free zero. Choose A S. Choose the region nearest to U. I will not change the cluster name. If you want, you can change it. It's up to you. I will just leave it to cluster zero, and then click on Create. After the after here, make sure you create a new user name and password for your database. These credentials will be required later on. So I will simply write it username and here password is one, two, three, f. That's it. And click on Create user. Here, choose local environment. In the IP address, give the IP addresses 0.0 0.0, then again zero, then zero. This IP address obviously means that anyone can access this server because obviously, when we are building an application, we want other users to use it. So if we restrict it to just my own IP, then only I will be able to use my game application. Simply click on, finish and close, then click on, go to database. You can see our cluster is ready. In the upcoming step, we will require a connection string to connect our app. That is to connect the letter app to this database. Just simply click on Connect button near the cluster. Then choose Bongo VS code and connection string. Okay. Okay. That's it. Go to your VS code editor, and now let's establish connection between our flutter app and Mongo DB. Sorry, not the flutter app, I will say, the new GS and that Mongo DB. So below this app dot. First of all, we have to require Mongo package. Mongos like this. Then here, let's past the connection string. The user name is correct. But here we have to write the password as well, like this Ra one, two, three, four. And at the very end, I will write the database name as t tat. This is the cluster is different, but within a cluster, the database will be tact. After that simply write mongoose dot connect. We have to pass that DB and after it is connected, we get a callb and here we will simply write Log. Mongo DB DB connection successful and also we will catch error. Catch within it, if there is any error, I will console log, the error. That's it. Save it. Now if I go to the terminal, and right NPM run Dev. Then I have the server running as well as Mongo Divi connection successful. So our NJ server is successfully connected to Mongo DV database. Thank you. 11. Install Socket IO Client: H i. Now it's time we work on configuring socket IO. We will be using the package socket IO client in flutter to connect with sockets in the server. So this will work on the client side. So here I will, first of all, stop the server, then change the directory to the root folded gist tto and write flutter pub a socket IO client. We have the dependency. If you go to prospect dot YML file, C, we have the socket IO client flutter dependency. Then we have to work on the socket functionality in the client side. That is the flutter project, go to folder, create a new folder called resources. And inside it, create a file socket client dot dot. First of all, import the package socket client, and we will import is as IO. Then we will create a class, which will return instance of the socket IO client. It will be singleton. So the only one instance is created. Here class socket client. Then of all, the IO socket data type and name it socket, then esthetic variable, which is the socket client instance, and this is private. This is private, you will understand, then make the constructor constructed as private using this internal Now here, simply initialize the socket which socket IO IO. We have to pass the IP address of the server. Now here, you cannot simply write local host 3,000. Since whenever we are using any emulator or your real device, it doesn't know this system. That is the MACOS. So you have to give the IP address of your system. So In windows, I guess, it was IP configure or something like that. You can simply search it on your own. In MacOS, simply go to system settings, Then network, sorry, network Wi Fi, then whatever Wi Fi you are connected, simply click on network settings. And here you will get your IP address, simply copy it and paste the IP address. In the end, write 3,000 ss. This is the port. In that is later on, if you plan to deploy your server, you have to add the server link in this IO. And we have to give some things to this IO client. Simply right here. Transport as trap as socket in a array, and this socket. Make sure the spelling is right. And this one will be transports. And then Auto connect will be false. And then simply right socket. This is not null and connect connect the socket. Then create a getter instance that create a getter for this instance variable so that whenever anyone tried to create an instance of this socket client, he will always get that one particular instance. Simply socket get instance If instance is null, then write socket internal initialize it, and then return in the instance. So I know this code can be a little tricky. Before moving forward, if you want, you can search about how to create single ton in fltter. You will understand everything within five to 10 minutes of this kind of Google search. But just understand that this code simply creates instance and return it whenever asked, and only one instance will be sent. That's it for this video. In the next video, we will work on creating methods for the sockets. Thank you. 12. Socket Method Class: Hi, welcome back. Now we have the socket o client package. Also, we will need functions to interact with the socket. For that, let's create a separate class for all the methods related to socket in the client side. Here inside resources folder, create a file socket methods do do. L et's first of all, we have to import We have to import the socket client. That is the one week just created in the last video. And then write class socket methods. Then create an instance of the socket client. Socket client is equal to socket client instance. See, we are not initializing like this and that. We are just simply calling the instance getter. This is a private variable. Let's write socket, which is coming from the socket IO client. And I will create a getter for the socket client in this file only. Socket client. And this should be instance socket like this. This is how you get in instance of the socket client. Then let's create our first method for storing a new room data. D create room Ting, we will ask for the player name. Then if player name that is not empty, then simply emit an event so that server can listen to it. I will write second client emit name the event name will be create o then we'll pass the data player name as the player name variable. But this is how we work with sockets. Whenever you want a server, to do some action, I will emit an event and pass data. Then this data will be passed to the server, and then the server can use this data and save it in the database. So in most in upcoming all the videos, we will just work on first emit either from the server or from the client. That is when we are emitting an event from the client, then the server will listen to it. And if we are emitting an event from server, then the client will listen to it. That will be the whole logic behind this tacto. You must get comfortable with this terminologies. That's it. This was a very short video. In the next video, we will work on the socket IO in the server side as well. Thank you. 13. Socket Server Connection: Hi. Now we have to configure node server as well to establish this socket connection and listen to events. So go to index dot JS file in the server folder. Here. We have the ovariable, that is a socket. Simply write io dot on connection. That is, if connection is successful, we'll get a socket and then first of all, write console dot log socket socket connected And then, as I told in the clients socket method, we emitted this create room. So let's listen to that event and simply we could do it but socket on create room, that is the event name. If this is emitted, then here, we will get the data, that is player name as I sent this player name key. I'm destructuring it here like this and simply write console dot log player name. So just for testing purpose, we are doing it. Also, go to create room screen here. Let's bind the socket method to create a room. At the very top, create an instance of socket methods. Socket methods. Socket methods is to socket method like this. Then in the custom button of create room here, simply write socket methods create and the player name will be roller. That's it. This was the only thing we have to do. Now, first of all in the terminal, go to the server folder and NPM run there to start our node server. Also, you have to run your application in your device so that you can check the connection between the front end and the back end. It Let it connect here. So I will simply write on schema, not starting with Alpha. What? Okay. I remember. You have to add HTTP. Here in the socket client, you have to add HTTP because obviously it's a server link. Just how we write google.com like that. Simply again, click on D. Okay. Now if I click on create through, S, socket connected is there. And if I write as player name and click on create. See this data is successfully sent to the server, and we can see it in the terminal as we did it consol dot log. So that means we have successfully established a socket connection between the front end and the back end. So that's it for this. In the upcoming videos, we will create on modeling room data and schemas and a lot of other stuff. Thank you. 14. Creating Room Model: I. So our socket is working. And now the next thing is whenever we create a room, we have to store the data in Mongo DV. We will store data in collection named rooms. So to model data for Rooms collection, create a new folder inside inside server that is here, create a new folder called models. And inside it, create a file Room dot JS. We will be using mongoose for data modeling. So at that top require mongoose, then we have to create a schema for room model. Schema means what pills will be there and data types or any properties. So write room schema. This is a variable name, then new Mongo dot schema like this. Inside it gave it a Javascript object. And now let's give us what fails a room will have. So first of all, a room will have occupancy. Occupancy type will be numbered, only number can be saved in this field, and default will be two because only two players will be allowed to play in one room. That is a ti te game only allows two players. So this occupancy occupancy means how many layers can be in a game room. Okay. Then we have Mx rounds. Again, here type will be number type will be number, and the default will be three. This is how long the game will run after which we will top eight. So just remember, suppose we are playing one game of Ditto. The first round, I win, then I will get one point. Then again, if I click on play again with the same player. In the next round, again, if I win, then I will get two points. So in simple words, whoever gets three points at the stretch, then it will be the maxt round. So it will be best of three. That's it. No best of three. You have to get three points. A then round. Current round obviously, we have to know which round the users are playing required will through type number default one. This is round we are now in the game. Then Next thing. Next thing, we will have player information as well. Obviously, who are the who are the two players ping? It will be an array. And now Mmm. We need to store players data as a filled inside room model. Either you can define player properties in the room schema here directly. I suppose, like, players, then it will be list. And then again inside it, it will be a player name like this, this, this. Either you can create the schema here, but I prefer a cleaner approach which is creating a separate file for player. Remember, this will not be a model, just a schema. Inside the models player. Then again, require the Mongos ve Oh, sorry. It should not be dot dot. So it's a habit of me as a plot developer. Mos. Then let's have the players similarly Mos and inside it, first of all, I need player name. It will be type string, and trim to true, that is no extra space in the letters. Suppose he cannot write space a space. It will be trimmed to only ah. Then socket ID of the player, that is obviously he will make a connection to the socket, so we will be able to retrieve its socket ID. Ring that's it, then points. So in every in every round, he will get an increment of one point. Default will be zero. Then p type. This is something different. It's symbol, you can say, symbol, either X, or like this. So we will save this here so that it will be easier to keep track of who the winner is and everything else. Type string. Now, simply export Export this player schema so that we can import it in the room file. Rom s here. These players will contain a array of player schema, and we know that there will be 22 playera. Next, we have to check if room is joinable or not, which simply means after two players. It will be false. So we will write is join like this. Type will be Boolean and default will be true. That is, at the very beginning, people can join this game room. And when there are two people, that is obviously first person will create this room, and whenever the second person joins, then this will be false. And we have to check which player's turn is there, and it will change every round. So simply turn and we will see the player schema here. And then whoever creates room, that player index will be zero or one. This will help in tracking turns. This final property, this turn index does this job. Right now, you might be a little bit confusing, but by the end, you will understand, this is the use of this field, and every field will have its use. Now, we have the schema here. Before exporting, we have to convert schema into model. Simply write cost Ru model is equal to Mongos do model. I will name it R and the schema will be this and simply export it. That's it. This is our room model. So I hope you have understood everything that what each field does, occupancy, Mx surrounds. At least, you should know what is the use of this field for now. So that's it. For this video. See you in the next video, we will work on events that is emitting events into sockets. Thank you. 15. Work on CreateRoom Event: H i. So we have the room model ready. Let's work on what happens when Create room event is emitted. So I hope you remember in the socket events, when the user click on Create room, then this event is emitted from the client that is fluttered to the server. So now we have to work on the server side to listen to this event. So simply go to index the JS here. And we won't be logging it. First of all, what we have to do is make this function a syncins. Since database functions will be called, then wrap everything in a catch block. C log error. Now in the tri blog. Let's work on it. This is our listener. First of all, we will create a room object. Here, create a room object. We have the model, so simply write R is equal to new room object. Then let's create a per schema, this player is equal to. We know what fills are required socket ID is socket ID. We will get the socket ID from this variable. Socket that ID. Then name will be player name. It is coming from the client itself here, then player type. Will be x. Since this is the player who is creating the, so he will get the symbol x. Then t we will add properties that is values in room object. So simply now in the room object, we have players field, which is a list. That is why we will write players ph and this player value. That is this because if you go to Rom here it is accepting list of player schema. We have to create that schema and send it here. Okay. Then next thing is room the n is equal to this player's turn who creates the room. And this is simply ph. Since it's an array. That's why we are using push and not the equal sign. Then save Rom theta in Mongo d V with this command. It's very simple variable is equal to a save. That's it. Oh then we have to save the room ID, which is returned after saving, that is simply save room ID value. And this underscore ID is always created or returned by Mongo DB when a new document is created, this underscore ID is by default. After saving. So here simply const Rom ID is equal to R dot and the score ID dot two string. Now, after it simply write socket, the join this room ID, which means this socket will listen. On when only whoever emits events in this room ID. So because obviously there will be there can lot of players be playing simultaneously. So I don't want suppose if someone players step on it, the other player who is not even playing in that room will get that event. So that is why we have to make sure this. And now, finally, I will use IO do to Rom ID that emit. Now I will emit an event from the server. Create Rom success, and I will send the room ID. Sorry, Room data, which is already in the JavaScript object form because I know data coming from Bongo dV is in the Javascript object form. That is JS format. And here, let's tell client that room has been created and Io send data to everyone in that room whereas socket sends to yourself. So what I mean is, suppose everywhere, it was socket dot join, and if I write socket dot M. So only the person who is sending this request will get the event. But suppose in the room ID, there are three players. So from here, all the three players will get this event so that we can make the changes in all the screens. Remember, if I use socket dot m, then only the person who is sending this, that is suppose who is creating this room will get the update. This was a difference. And this was how we listen to events and similarly how we admit event. And in the next video, we will listen to this green room success event from the client that is flatter side. Thank you. 16. Room Success Event Listener: Hi. So after successfully creating a room, we will navigate player to the game screen. So go to the lip folder inside screen, create a new screen game screen dot dot. Here simply import material then a state full gid. Screen. I will have the route name here. The string route name is equal to slash game. Then simply give it scaffold, return a scaffold body center. The child give it a text of game screen. This is just temporary for now. Game screen. Save it and register this game route in main dot dot file. So here simply below the join room screen, Gamcreen do route name, and it will send the user to game screen. Next thing is just in the server, we listen to create room event. Similarly, in the flutter side, we have to listen to create room success event. Let's create a new function inside socket methods here below this create void create success listener. And we will ask for the bell context from the user so that we can use a navigator. Now using the socket client, we will simply write on the event name is create room success. And we will get the room data as we remember in the server side. Then simply print the room data as well as use nor the of contexts, the ph named game screen route name. This is a listener for create room success, which will navigate the user to the game screen. Obviously, we have to execute this listener. Go to create room screen here in the in state. The init state, we will call socket methods that create room listener and we will pass the context. That's it. Whenever it is continuously executing or listening to this socket event, and whenever it is emitted, we will. Let's test it If I click if I go here, then click on create room. I'll give the room name to Rah. Now I'll just clear that terminal and click on Create. L et's see what is happening. Okay, Rom is not defined. We got an error in the server. Okay. While creating this o I forgot to let's go F to require then go to models and require room like this. Let's save it. It the app as well. Let's say what happens. Does it work or again, I will get some T. We have been navigated to game screen, and in the terminal, you can see all the data. That is occupancy players, MAX rounds, which players turn the alls thing. And we have this underscore ID value as well. So that means our create room event is working, and now we are able to create a new room in our Mongo DV database. So it's a success for us, you can say, because at least it gives us the base, and now we can work on this more on the application. Thank you. 17. Room Provider Class: Hi, welcome back. Now it's time we install and focus on state management as well. So we will be using provider package in flutter to manage state in our application instead of passing data through constructors. So for that, what you can do is a p terminal in the route projects. I will just top it or you can I can just go to put here provider. Provider should come in the first, then installing. Either you can use flutter pub a provider in your terminal, or I will just copy this and go to pubs dot yaml file, and here paste it in the dependencies like this. H, let me just talk the side of as well. Since this is a new package, I will stop the flatter application and re run it. Go to start again. Also in the terminal, I will change to server folder and PM run the Okay. We will be storing room data in provider so that it can be accessed easily within the application. Inside the folder, create a new folder called providers and inside it write room eta provider do. Let's import material, and we will write class Rota provider extends change notifier provider. So I hope you know this concept. And sorry, this should be change notifier. Yeah. And this comes from the material library. First of all, the first data, which we will have string dynamic room data. We know that data is coming in JCN format from the server. Then this is a clave variable make a getter for it, string dynamic get Rom data. Room data like this. And obviously, we will need a setter function or can say an update function update Room data. We'll get MAP string dynamic data Room data is active data and notify all the listeners. I'm again saying that I hope you know the concept of provider state management and how we make changes and notify all ear listeners. Next thing we have to do is register is provither inside Mined do dart file. Here, wrap the material with a igid, and it will be change notifier provider. And inside it, it gives us create in the context. And here we have to write the provider, which is room data provider. And in most of the time, you will use multi provider. But in our application, there will be only one provider. That's why I directly use change notifier provider here. Finally, let when room is successfully created, and the client listens to the create room success event. Then execute the room this update room data to store data in the provider. So go to socket methods. In the create room success here, simply write provider dot of context. We have the context here, and which provider we want to listen room data provider and make sure I don't want the changes to be listened. Then simply call update room data, and we will send the room data, which is coming from the server. So that's it. That's it for this video. In the next video, we will work on joining room functionality as well. Thank you. 18. Join Room Listener: Hi. Now let's create a function inside socket methods where we will emit an event from client to the server when player tries to join a room. So here below the create room success listener. I void Join room. String layer name string room ID. These are the two details. Obviously, we are mentioning in the join room screen. Simply, I will check if er name is not empty and room ID is not empty empty. S's not empty. Then we will emit an event the socket. That is join room, and we'll pass the data. Play name. Play name and Room ID RooD, like this. So Here we are emitting A data when the player tries to join room, but we obviously have to listen to that event in our node server. So go to index the JS file now. Okay here below this create room listener. We'll work on socket on Event name is Join Rom. It will be in a sing function and we will be getting theta plane and room ID. We'll now do that try catch block again, try catch Cleg Then I will hear this code is very simple. This check I Rom ID is a valid mongoose ID or no. This is the rejects check. You can I have just copy pasted it simply write ID match then inside it. I will have to write like this. Then 0-9 A F A F $24. Remember, this code, if you want, you can add, you can remove as well. So only check if it is a valid Mongoose ID. So Sock error occurred. Please enter a valid room and return from here. And we have to check, have to make sure it is not match. It is exclamation. And if it is okay, then we will write R is equal to a model find by ID. This is Mo's query. We will find that document by its ID. Then we'll check if the property is join. That is the person can join it. And if not, else, I will again write socket occur, and here I will pass. The game is in progress. Try another room. That means two players are already playing in that room, you cannot join it. If it is joinable, then first of all, again, I will create a player schema lay name name so ID so ID. Then type. This time, it will be. Then I will write socket join this socket also join that same room ID. Then I will push the player room players do push that is this new data player data into this room object. Then change the room dot is equal to false, and I will save these changes. A room dot save like this, these changes will be saved in the database. And finally, I will emit to the whole room that is I room ID Join join room success, and I will send this room data to the platter application. This was the listener to join room event. It first of all, it will go to the Mongo and get the room, then create a new player and insert that in the room data model, we have the players array, and again push this player. That is now we have two players in that array. Then I will change the property to false, then I will again save it, and then this latest data, I will send to the front end via this socket event. In the next video, we will listen to this Join room success event. Thank you. 19. Work on Join Success Event: After players successfully join a room in the last code, we have emitted an event join room success. So now let's create a listener for that as well, and also for this error occurred event. Go to socket methods the Dart file. And here below this join room. Wide join room, success listener. Bill context. We will ask for the bill context, then simply write so client dot join room success. We will get the room data. And this room data, we will update in the provider. Provider of context. Room data provider, listen to false and write update room data, and we will send the room. And after that, we will simply write navigator do navigator of context, the push name, and we will send this user to the game screen as well. That is the person trying to join it. Since now, I hope we have understood the use of this provider. We have that data this provider, and then we can use that data in the game screen. Similarly below this joined room listener relate wide error occurred listener context client that on error occurred. We get the data which is in the string format in this case. And we will simply show a snack bar messenger of context that show snack bar, then the snag bar. It will be text containing the data. That's it. We have the two listeners. Now, add this listeners in that joint room screen. Create an innate state and write socket. Here, I don't have the socket methods, so simply go to creates and copy the socket methods. The join room socket methods Join room success listener and similarly socket methods ers occurred listener. Also just for testing purpose, let's show the room data in game screen. Go to game screen here. In this, I will write provider of context. It will be room data provider. Listen room data two string. I'm just outputting the complete room data in the screen so that we can see it. Now first thing we have to do is create a I will name it A create and see here, we have each join is equal to true then player name and only one player information is there. Here If I try, I don't think I can copy it from here, I have to go to the MongoDB last. I have to copy the room ID. I. Firstly, let's sign in. If I click on browse collections, then rooms. And this, Let's see, I will I guess this one. I will copy the ID. And if I again restart the app and try to join it. That is first of all. I'm not able to paste it, M. Let's do it 647a3 362d eb09 cf3e ob6e and write on click on join. Let's see, I hope there can be some error I'm not sure why is not working, but let's say if I go to join room, then here I guess, in the tab, nothing is happening. You have to call this joined room function in the join room screen circuit method Join room. Pla name will be name controller text. It will be gay MD text. David, So spelling mistake is there as well. What you wish. What is the mistake here? Okay. I guess I don't think so there is that mistake. If this code is not working, I will remove it in the next video. I guess I have to check the code again. Thank you. 20. Player Dart Model Class: Hi. In the last video, we got some issues. I have solved those things. So For the Android emulator, I just deleted it and created a new emulator with the latest version, that is pixel, Excel and whatever, it solved the copy and paste issue. And in our index dot JS file, there was a typing mistake here. This should be Rom dot E joint is equal to false. Earlier, it was minus. So it was just a bug or equates a typing mistake. And also, I have added this line that is if room is equal to null, emit error. There is no game room found within ID. Suppose the user entered a valid Bongo ID, but the room is not available. Suppose he by mistake, remove the last word or suppose the last letter, then in that case, there is no such document in the database. So we are checking that as well. So let's try it again. I will click on Create Room. Then created room. I will go to the database. I refresh. And say we have each join is equal to two, and in the players array only one player is there. I will copy the ID, and then now try to join the same room. Join then suppose some different name. And now I have this in the clipboard and if I click on join. S. I have successfully joined the room, and if I go and refresh, Then you can see e join is false, and in the players, we have two players and both have their socket IDs and all. So that means joining a room is also working perfectly. Now, let's work on a model class. In the room provider that is this file. We only have room data property. But we will also add player data as a property in this provider class because we will show players name as well as their points in the game screen. So instead of accessing player data from this room property, we will create a new player's property, so it will be more convenient for us. And first of all, I will create a model class that is that model class for the player data. So inside lip folder, create a new folder models and inside it, create play dot dot. Let's write it player then final string player name one property. And these are exactly the same names which are written in the pla JS model in server side. And sock ID. Final double points final string play type. Then let's create a constructed rename. Require this suck ID. Points. Require this player type. Then let's create methods for serialization as well. That is converting from map to that object as well as from that object to map. First of all, I will create map string dynamic to map function. It will return a map Then we have that play name. I'll play your name. Then socket I socket Id. Points the clear type clear type. And then if factory function display from map. I will accept a map. This map will be coming from Mongo DV. Then rely turn lay on here. Will be mapped plain this copy paste and then socket ID points clay that. Again, saying that these keys will be same as the index JS file. I'm just checking for the null so that I make sure that there is no issue. Okay. So that's it. That's it for this video. S in the next session. 21. Player State in Provider: Hi. Now let's add this player property or you can say state in our provider class that is room data provider. Here below this room data, right player layer one, two, model. And here I will just leave everything to empty for now. D empty 0.0 or you can say I know the players, one will be X. And similarly, for the second player, write cla two, and here symbol will be zero, then create a getter method, get cla one is equal to p one. Player 22 player two. Should play two. Then similarly, let's create a function to update Player one and a player two, first of all we data. We will receive data in map. In map form string dynamic player one data. This we will be getting from the server. Pla one, Physical two play map and player one like this. And then similarly created Player two. It will be same like above string dynamic. Player two data. Player two is equal to play map. Player to Data, and make sure you write notify listeners so that the front end gets updated. Okay. Now go to Index to JS file, and here emit players data from the server. Here simply below this room success. I will write IO two Room ID dot m update players. And I will send dot players. That is the data. And now we are emitting an event from the server. Obviously, we have to listen it to the client. Go to socket methods here at the very bottom per state listener. I will ask for the bill context. Then socket client not on update players player data. And also, I will say, remember here player data is an array of player map. So it's an array. So obviously, to get the per one data, you have to go to the index zero and for player two Index one. Provider of context Room data provider. The update player one, p player data at the index zero. And make sure do listen is to falls. And similarly, you do update Player two Data, and here index will be one. So I hope you have understood that and this will be updated only when someone joins the room. Because when creating a room, obviously, one of the value will be null, but when the person is joining, then both that is both the players data will be there. Ba while creating this value will be null. That is at the one index. Finally, let's test this functionality. First, we have to assign this update clear state listener in the init state of join room screen. So here, I will write socket methods, and so many tying mistakes. The update clear like this. And then in the game screen, I will display the names for testing purpose. So here, a center. I will write column, main axis alignment, main axis alignment dot center, children. Then text in the text, it will be provider of context. Room data provider as files dot player one, do player name. And similarly below it, I will write player two per name. Let's of all, I will just go and remove the so that it's clear to me which one to copy. Then I create. Obviously, right now, nothing will be there. But if I copy this ID. I copy this ID and try to join the room. And here, first of all, I past the ID and write J and join then see. Both the player's name can be displayed in the game room. So that means this functionality is also working perfectly. In the next video, we will work on the waiting lobby screen. That is whenever someone creates a game room, he should be seeing a screen that is waiting for another person to join this room. Then only the game room or the game screen will be shown to them. Thank you. 22. Work on Waiting Lobby: Hi. When the first player creates a room, we want that he must wait for the other player to join it. So for that, let's create a new screen. I won't say screen. It will be kind of wigid. So inside widgets folder, right waiting lobby dot dot. And here, first of all p material. And create a stateful visit. Im waiting lobby. Since this is not a screen, we don't have to write the route name. Wait. Here we need column but also we will need a controller because we will be showing the room ID in this visi. Text editing controller Rom ID controller. In it state, simply write room ID is equal to text editing controller, and the text value will come from the provider provider of context Room data provider. Listen to false and then write that room data, and we want the ID. That is underscore ID. Remember, this underscore ID. And it is a map data. That is why we are writing the key here. And also dispose this room ID controller that dispose. Now, in the body, we will simply output a circular progress indicator with a text telling to wait for another person to join and also displaying the room ID, which he can share with his friend. In main *** alignment that center in the children circular progress indicator, give it color colors that white. Give some spacing, size box, height, the text waiting for another player to join. Then C again, give some spacing of 20 Finally, we will have that custom text will Controller will be room ID controller. H text will be empty. But here this read only will be true because I don't want the user to edit the room ID and also wrap this column with a padding and give it padding all size of 20. This is the code Now, let's test this lobby, go to game screen. And here. Let's create a room provider at the top. What I want is, I will copy it and room data provider is equal to room data so that we can use this provider wherever we want. In the body, of scaffold. I will remove this dummy code, and I will check if room data provide dot Rom data is joined. Is true. That is still no one has joined. So I will show the waiting lobby. Or else I will show constant center child Game starts. Just for now, I will just write game starts. Later on, we will work on the game board as well. Now, also what I will do is open a chrome so that it's more easier for me to test with two devices. I will create a room. I will I will copy it then the join room. I will should be the n this time. As the room and click on. And see here you can see the waiting lobby skin. So it is looking very nice. If I click on join, then the game starts. The second player is sent to the game start, but obviously, the first player has not received the update. So in the next video, we will work on this thing as well. Thank you. 23. Listen to UpdateRoom Event: Hi. As you saw that, if we try to join the room, then the first players law waiting lobby is not updated because we are only listening to Join room Success event in the Join room screen, not in the create room screen. Also, we cannot use the same join room listener since it is navigating from game screen, which player one is already in. To solve it. We have to emit another event from the server, go to index do JS, and here I will emit IO dot two room ID, emit and I will update Ro and I will send the complete role. And we have to listen to this as well, so go to socket methods. And now I think you are comfortable with this thing because of everywhere we is emitting and listening. That's it. Let's write id update room listener. Then Bill context contexts suc client on eve is o. We get the data here. And then I will again call this provider and write the update room data. We are updating the room. Finally, listen to this as well as in game screen. Go to game screen. Here in the state. We write. First of all, we need the socket final socket methods. Kate methodical to suc methods. And then suc methods update room listener. First of all, this one, and then update player state listener. These two listeners we want. Player state as the points will update. And and this room listener, because obviously, when the first players joins the room, the game should be updated. So let's test it. I'll go to Chrome as well. Mm started. Obviously, it will show some error. I have to go to the home page again. Okay. Now, if I click on this time, I will write name Bill. Copy it Join is to and here write. Jeff. Then let's see if I click on join. Then this game is started. But this is taking some time, let's see if there is any error. It might take some time. State what had happened the plant on a rough I'm sending the Okay. I don't know why. In the next video, we will see what is the issue here. Thank you. 24. Work on Scoreboard: H i, welcome back. In the last video, we were facing an error that is whenever player one creates a room and send a room ID to Player two and player to joins it, then Player one doesn't get the update, and he's not sent to the game Start screen. He's still in the waiting lobby screen. So the issues in my code were First of all, in the game screen dot dot, you must remove this listen false code because obviously I want this game screen to listen to the provider changes. That is whenever we do notify listeners, this screen should rebuild. And second changes in the server side that is index dot S. I did a mistake in the create room screen. Here in the line 32, that is constant room ID is equal to room ID dot. String. Here, it should be brackets as well. That is why the room ID was not correct and sockets were not joined to that room ID. So let's start the server. S server and PM Run D. Let's try it out. If I click on Create, then a copy go to Join screen. I I write and paste and click on join. See. Now both screen got the update, and both are sent to this. That is the lobby room has been removed. So from now on, let's work on the scoreboard I in the game screen at the very top, we will show the scoreboard, which will contain the player name and the points. For that, let's create a new file inside Widgit. Here and right score board dot dot. Let's start by boding material, then I state less rigid. I will am board Then first of all, what I want is the root provider. A of context. And it should be room data provider. Then let's return a row gid, then main axis alignment. Then in that I will again have a column. Main axis alignment, main axis alignment, center C Then what I want is two text field together. That is name and the points. That is why in a row, I have used column. You will understand room provider. The player one, the player name style C textile. Fun size will be 20. Font weight will be font weight dot bold. And similarly Billow eight, it will be player one, points, the two in the two string. And he font size will be 20, but it won't be bold. And also to this column, wrap this column with a padding wig and give it 30. Then create another column within this row for the player two data. Here simply copy this padding past it below that padding get. Now here, it will be to player name, and it will be player two in two string. Let's save it and finally, show the scoreboard in the game screen. Here, I will remove below this scaffold. I want to remove the center widget and I will write safe area. Then child, will be column. M axis alignment start. Children and the first widget I want is the scoreboard. That's it. Save it. Let's go to a screen and see. It is looking very nice. Now, I hope you have understood that this was a row, and within the row, we have two columns. And within this column, we have two text. That's. That's why it was row and they're inside two columns. So our scoreboard is also working. In the next video, we will start working on the thick tacto board so that the players can play with each other. Thank you. 25. Create the board UI: Hi, welcome back. In the game screen below the scoreboard, we will show the T thick tacto board. So let's work on the UI first, create a new file inside Widgets folder. And write the name T T two bod. Okay. Import material. Stat full gia bod Then here, we will create the board using a grid view builder because it will be much more easier to create boxes with this rigid. Let's do it. Grid view builder. First of all, item count will be nine. Since it is a three by three board. That means three on the horizontal side and three in the vertical side. Then grade delegate will be cost sliver grad delegate with fix cross as count and cross exist there should be three. There should be three elements. Cross axis means. In the vertical side. And bill context context, and we get the index. Then return a container. Now, now the container will be a box. That means it will have borders from all side. And inside, it we will show either X or O game value. So let's give some decoration box decoration border. Border all color colors white 24. And inside inside child, we will have center the child. Then text wig right now just hard cote the value X D style. Textile color colors dot White font weight font weight dot bold. Then font size give it 100. And I will give some shadow just for the styling purpose. Shadow Bl radius for color colors dot blue. Okay. Now, also, since we are using grid view builder to avoid render size error, wrap the grid view with a constraint box. Constrained box and constrain box constrain Max height. Now for height, let's have final size equal to media query media of context size and max size will be size into height that is height multiplied by 0.7. And Max with will be 500. These are the Mx wit value. Finally, call this board in the game screen below the scoreboard. We simply read constant tick to board and save it. Now let's go to the game screen and see. I is looking decent. Obviously, I haven't refreshed the browser Chrome browser. But as you can see, now it looks like the game at least. In the next video, we will work on displaying X O conditionally. Thank you. 26. Keep track of game values: Hi. Now we have to work on displaying X and values in real time. So whenever we click on a particular grid, or you can say container, the grid view builder gives a index of which container was clicked. And then we will send that index to the server. That is, suppose this is zero, one, two, three, like this. We will send that to the server and server will emit and update to all the clients in that room. In the socket method, L et's create a new function which gets executed whenever player makes his move in the game and emit an event from the client to the note server. Let's create a wide tab grid. We will get in index string room ID, and this will be something different that is a list of string display elements. So here display elements will keep track of all the nine grid values. That is something like this. Suppose z, then something will be empty like this for all the nine spots. It obviously, this will make us easier to upgrade or update the grid value in all the screens. Now, first of all, I will check if display elements in this index is empty. That is no value is there, then I will emit an event called tap. With the value index index, and Rom ID, Rom ID. Obviously, it should be one dot. Say simply, we will emit an event from the application to the server. Now to keep track of elements or grades, we need new property and methods inside our provider. Go to room data provider, and here f of all, let's write list of string. Display elements. And here, give empty string nine times. So it's one, two, three, four, five, six, seven, eight, nine. Okay Also, we need an integer for filled boxes. Why this filled boxes because we cannot use length of display elements variable. Since it's filled with empty string. That means the length will be nine. By default. So we will keep track of how many grades are using paled boxes state. This is the concept. Now let's create getters. It is a list of strain. This play elements. And it should be getter. And for the field boxes as well. Now we have the state. Let's create functions to insert or update value. Wide update display elements. I index string choice. That is x z. I will write display elements at the position index 02 choice and make sure this is x or. Then I will do boxes plus equal one and notify all the listeners to update it. And below it, create another function that is set w boxes to zero. So it is very clear that it just restarts the game. That is after the round ends. We can play again. L this. Now, let's make the grid containers taable and then bind tab grid function. Here we have the tab grid function. Go to tie board. In the item builder, that is here, wrap this container with gesture detector, and on tap. On tap. First of all, now we need the socket method variable socket method instance. Socket methods. Then below this size, get the room provider. Why the of contexts. Rom data provider. Then in the on tab socket methods, do tab grade. Index will be index. Room ID will be room data provider, Rom data and inside underscore ID. Display elements will be again Room did the provider the display elements. So that's it. That's it for this video. In the next video, we will work on listening to events in the note server. Thank you. 27. Displaying X and O: Hi. Welcome back. So now make sure to listen to the tap event from the client. That is here. We are emitting this tap event, right? So we have to listen to it in the server. Go to index the JS file below the join room here. You will write socket on tap. Then we will have an async function. And we will get the value index and a room ID. Let's do that try catch. Log A. In that, again, creo. I do fine ID. Room ID, then let choice then, whoever turn it is and player type. That means either x or. This is how we get the symbol. Now I'll write if the turn index equal 20. That means player one tabbed. We will simply change the turn to player two because since player one has already tab Rom player one, room turn index is equal to one. I player two tapped, then we will do the opposite. That is change the turn value to zero index and the turn index to be zero. I hope you understood the logic. If player one tag, then save the role. And now here, we will emit an event to the room ID that t and we will send the value and These three things. We will send to the client. Again, I'm just checking room sic to this choice either x. If cla one tab, then change the claer, then save and then admit. Now we have to write a method to listen to this tab event. Go to socket methods. And here wide tab listener. Bill cont contacts Scit client go on tab we get that data then from the provider Okay. What we will do? We will update the display elements. Room data provider that update display elements. We get the index theta as well as that choice. That is the symbol or the value you can say. Then room data provided the update room data, and we are also sending the complete room. This is the tab listener function. Now, bind that tab listener function in the innate state of detecto board here in the in states right socket methods, the tab listener. And here, remove this at coded and write o the display elements index. In the textile, I will change the color here according to the value that is here, I will write. Room did the provider the display elements index if it is. O. Then give colors blue. Sorry. Yeah, if it is you can colors red. Color. This can be constant. Okay. Save it, save everything. Let's open it up pen the crow. I will rest that rome as well. Now, let's see whether it will work or not, I will create a new room. Suppose Jeff copied in bill paste, join. Now if I click here, S, X is there. If I click here, Oh value is there. X is there. O value is there. It is working in real time, at least. Now we can see our progress and it is pretty good. In the next video, we will work more on the functionalities of the board. Thank you. 28. Playing according to turns: Hi. Our real time game is working, but we can play the whole game from one device only. But obviously, it is a turn based game. One player should not be able to tap on the game twice and wait for his turn. To solve that, we will be using absorb pointer widget. Wrap the grid view builder which is here in the t teco board. Wrap this grid view builder with a absorb pointer de. It is a ge which prevents its child from being clicked, scrolled, or respond to how. So it's very simple. That is this absorbing value. If it is true, then you cannot click. And suppose it is false, then you can click. So here, the logic will be room data provider, the room data. Turn the socket. Let's compare the socket socket ID, not equal to socket methods socket client ID. So if it is not equal to is true, That is simply if turn socket ID and socket ID is equal. Then it should be false. That is absorbing should be false so that he can click on it. Simply means if true, then cannot click. If false, then it's clickable. This is the logic. You have to make it according to that. That's it. Also, it's dest it. I will write a name here is a random name Copyright join on join. No first turn will be his care. S X is there. If I try to click here again, then nothing happens. But if I click here, then see O is there. If I try to click here again, then nothing happens, but if I click here, then X is there. So that means we are able to play turn wise. But the value X and are appearing suddenly, which doesn't look very attractive. So let's give a basic animation. Bring out your code editor, go to tick Teco board. Yeah. Wrap the text gid with an animated size duration. Boned duration give milliseconds milliseconds, 200. This is just a fade in effect, you can say. V basic effect. But obviously, we have changed the value so before testing it. Let's also display the turns. That is which player's turn is there to avoid any confusion. In the Tito board, in the game screen in the game screen below the Ticat board. Simply room data provider, that room data then layer name. I just have to write this. That's it. Now, let's test the complete game functionality. If I create a name it then join This is wrong. Here name Mark I join Rahter. See if I click here, then it's Mark Stern. Then again, Raster. Also, very basic fade in animation here. And also, if you want, you can give whatever animation or effects you want. Our main focus is on the functionality. So now, everything till here is working perfectly fine. In the next session, we will work on the functionality to check the winner of the round because obviously, if we complete this game also, Then also, nothing will happen. So see you in the next video. Thank you. 29. Check Winner of the Game: H i. Now the next most important thing we have to check is the winner of the round in the game so that whether it is a draw or a win, players can either play again or exit. And since this functionality is related to game and not sockets, let's create a new file inside resources. Inside resources create a file game methods do dot. Also, the game winning logic will be pretty long as we have to check all the three consecutive grades with the same value, either vertically, horizontally, and diagonal directions. Let's say class gay methods. This class will have only one function wide check winner. We will ask for the bell context with the provider as well as showing some dialog boxes and the socket. Socket client. Remember, this socket is coming from the socket IO client, only the in from the dart. Faster create a room data provider. This will be false. Room data pro ide. And also the string winner that is here, here we will have either X or, which one with symbol one. And later on, with that symbol, we can get the user details. Now, let's check if there is any three consecutive grids, with the same value. Horizontal is checking His. Now, I hope you have understood horizontally. It's like suppose a dummy room. So here horizontally means zero, one, two, like this. These are the three horizontal directions. Now, let's work on the logic. We will do everything with the IL statement. I Rom data provider do display elements at zero is equal to Rom Data provider, display elements at one position, and Rom data provider. The display elements at zero is equal to room data provider, the display elements at the at position. Two, Here, till here, I hope you have understood that this zero is equal to one, and also zero is equal to two. That means obviously one is also equal to two. But we have to make sure and Rom data provider, the display elements at zero, is not equal to empty string. There has to be some value inside it. In that case, winner is equal to room data provider, the display element at zero, that is x or y, x or zero, whatever it is. Similarly, let's copy it Past it. And now we will check if element at three is equal to element at four and element at three is also equal to element at five, and finally, element at three, not equal to t string. So winner is equal to this. That is the second line of horizontal direction. Similarly, copy and paste it. Now the last row six is equal to 76 is equal to eight and six is not equal to t, so display eleate is six, like this. This was the horizontal value. Similarly, What I will do is copy everything, all these things. Pay state. Now, I will be checking for the three consecutive grids with the same value at vertical direction. Here, it will be oa display elements at zero equal to display element. Zero, one, two, three. It will be three, and again, zero is equal to 60 is not equal to 20 t, then make it zero, the winner. Then I will do one one is zero, one, two, 34. One is equal to four, then one is equal to seven. One not equal to empty and make the winner display one. Remember this is horizontally, and we have three horizontal lines. Finally, two is equal to 52 is equal to eight, then the two. And don't stress it. You will get the source code, so at least you can check if there is any error with your code. Now finally, copy everything, paste it again, and this is for that three consecutive grids in the same value diagonally. I will just write diagonal here. And I hope you know the diagonal that is this one. First with it horizontally, then with it vertically, and finally diagonally. And there diagonal can be like this and like this. Yeah. At zero is equal to 40 is equal to eight. This is fine. Then the next one is two equal to zero, two, 34. Two is equal to six, then it should be 22. Now we don't need this one. Now, only I want is condition here. That is SAF. Room data provider dot filed box is equal nine. That is checking all possibilities of winning, and then we will declare it draw. Winner is equal to empty. Obviously, this is empty, and we will display dial box saying draw. We will work on this dialug box in the next video, but I hope you have understood this logic. I know it is pretty big, but still It's very straightforward. It's only the FL statements, nothing else. So save you in the next session. Thank you. 30. Display Winner in DialogBox: Hi. Now, let's work on a dialogue box so that when whatever the result it is, we can show it in the dialogue box. Inside Utils folder, create a new file Utils dot dot. I will separate the dialog box function here. It won't be a class. It will be directly a function. So wide to game dialogue. Bill contexts context string text directly write to dialogue. Now context is there. Then another property I want to add is barrier dismissable to false. Then in the builder, context and I will return and alert dialogue. Title will text with the title with the text value. And we will have actions, the actions. Let's have it text button. For now, just leave it empty and it will be context play again. Like this. Go to the game methods file. Here, here, show a game dialogue box game dialogue box for the draw result. Okay. And now, what if the game is not draw and someone wins? At the below of the check winner function, write the logic to check if winner, that this variable is not empty. Here, Let's write if winner not equal to empty. And then we'll check if room the provider, do player one dot player type is the winner. Now with the symbol, we can know which one is the winner. Also we will have the s. But let's work. If player one wins, then show game dialog box. Text will be room the provider do player name, the dis player one, player name, one the round. And we will emit an event. Obviously, we have to tell the server as well. Socket client that emit the winner the event will be a winner, and the data will be winner socket ID. Roma provider player one socket ID, and also the room ID. We have to send these two things. Room dt provider, Rota ID. Okay. And what if player two wins, then copy everything. Past. Here, it will be player two player name. Winner and here it will be played two. Other things will remain same. This is the logic. If someone wins, then we will first show a dial box and also emit en even to the note server. Now execute the check winner function inside tab listener. Go to socket methods so that after every turn, we will check for the winner or draw. Here. Write check for winner. Write gay methods do check Winner. We'll send the socket client. Okay. I hope you have understood because obviously, in every tap, this is called, and we will check whether the game is over or not. Now let's test it. Lot of things are. Let's say everything is fine, right? Great roll cope Jo If I do here. L et's let's try to win it. I will try to win the X value. And see Rahul Won the round. So that means our game logic is working. And I guess there is some issue with the value. I will check it. I will check this thing in the next video, what happened here, Okay? Thank you. 31. Play Again Functionality: Hi. In the last video, I found a bug in the application. Let's first of all, show you the bug. If I create a new role. Rahul, create it copy. At and write the second cla and join. Then suppose in Rahuls term turn its x and if I click on twice, it becomes zero. Se Here, If I click here, it's X. If I clear, C. So this was some kind of issue if I click multiple times. So User can tap twice and the symbols or the values are misplaced. So for that, I have make a lot of changes or not a small changes. First of all, go to Room data provider class, and here in the line 14, add a new state that is bull absorbing value and leave it to true. And I hope you remember the absorbed pointer. That is if it is true, then you cannot tap on it. If it is false, then you can tape on it. By default, I will make it true, then create a getter function for it. S After that create an update function. This, that is absorbing to true, what it means is, after the user taps on it, I will directly change its value to true so that he won't be able to tap twice. And When the client get an update room data function, that is, suppose if you go to client method, Se update room listener is there, which calls the update room data. After every turn, the room will be updated. And also in the val beginning, also, the room will be updated. That is when the second user joins the room. Here, we will change the absorbing value. That is whoever turns it is that person's absorbing value will be false. And by default, it will be true. So remember, change this line this line. Then this s and this. Also, you will get the code, so you will understand it, but I have mentioned the new code comment as well. After that, I don't think so Here, it was I didn't make any changes in the socket method. No. Directly go to the tacto bode and here. Comment the previous code that is absorbing and write absorbing is equal to room data dot absorbing value. That is by default, it will be true. And also When the user taps on it, we will first check. If it is true. That is he shouldn't be allowed to execute the function, then I will return it from here only. It won't be executed. And if the user taps on it, then directly, I will change update the absorbing to true so that he cannot click twice. And after this, the socket method will be called. That's it. These were the changes. Simply I changed the way how the absorbing value works. That's it. Let's try it out now. If I now create a room, a bad pasted john And now if I click here, see, I have double click, but there is no issue. Now here, zero is there O is there. If I click here multiple times also, then also nothing is happening because the absorbing is true after the user clicks on it. And here, here it is. So that means now that error is fixed. That was a very critical bug. Obviously, the game wouldn't make any sense with that bug. But as we are programmers, we can find bug and solve that. Also, the only next change you have to do is go to game methods, and here in the line 74. Make sure when you check if data provided filled boxes is equal to nine, you add and winner is equal to empty. Because earlier there was another bug that is when there was only it's tern, suppose like this and like this. Okay, I wander around, but the thing was, when only one box was left, and the winner wins, then also it was showing draw, because in the code, Just try to understand this logic. That is the winner wins supposed by diagonally. But all the boxes were filled nine. That is why he again changed the winner to empty and show row. But here we are checking winner is equal to empty. Then on the dialogue box of draw. Or else don't change the winner value. So make sure you update this as well. So that's it. These were all the bucks we need to fix. Now, let's work on what happens when we click on the play again button. That is, let's create a function, which will restart a new game. If we click on the play again. Go to game methods do file here. After this check winner. After this check winner, create a new punch clay board Bill then the provider then we will remove all the values from the display elements. Write n is equal to zero, I less than room data provider, do display elements len I p p simp room data update display elements. Index will be, and choice will be et. And then simply called set fill box stress value to zero, like this and assign this clear word in the UTs function. Go to ts function here. Si write K methods word contexts gator pop. That's right. And here I join join. And if I make it win and click on play again, see. Again, we can play Vicki Sterns there like this. So the play again functionality is working perfectly. In the next video, we'll work on listening to the winner event server. Thank you. 32. Listen to Winner Event: I. In the check winner function, we are emitting an event called winner. As you can see, so now we have to listen to that socket event in the server. Go to index the JS file. Here. Let's create a new socket listener on winner a sync. We are getting the winner socket ID. Rom ID. Let's try catch. It will be simply consol E. Now, let's get the root. Rom ID. Room idea. Then let's see who won, that is players find. We have to find what. Two. Player dot socket ID should be equal to winners socket ID. Get that player. Increase the point. Dot points p equal one. R is equal two S. Now, if game reaches the number of rounds that can be played Then we will check with the points directly, that is player points greater than equal to rounds. Simply write IO two room ID end game with the player data. That's right. I to ID that simply increase the point point increase. That's it. This is the listener in the socket, and we'll just check it again. That players find. It will just return the value in the player. Then player start points wait. I hope you have understood that I am comparing the points with the Maxon, since it will be zero, one, two, like this, only three rounds will be there. That's it. That's it for the winner listener. In the next video, we will work on listening to the end game point increase events in the client. Thank you. 33. Listen to EndGame Event: Hi, welcome back. So our application is about to be completed. Let's listen to point point increase event in the flatter side. Go to socket methods that file here. And here. Let's write a function d point increase listener. Well contacts the sock client dot point increase. Then we get the player Data as you call the room provider. No, right. If play Data socket ID is equal to room data do so ID. Increase player one point. So I will just Rota provider per one and playera. It's simple. I room data provider the update Player two with player data. So I'm just we already have the increase point in the player data variable. So I will just update the player two data with this. Suppose if I go here, we're changing it and notify the listeners, so the screens will be updated as well. Like this. And also, let's listen to the end game event as well. Bellow here, right wide game Bell Cont client on end game re data. Simply where I show game dialog box. The text will we layer data layer name one the game. And after that, you can simply navigate the pop tail. And I'm removing all the screens. That's et's test it out. Let's see what happens whether it's working or not. Okay. S Rahul won the round. I guess there was, we forgot to bind the listeners to the game screen. That is the issue. Go to game screen. In the init state. And also, what is What is this error? Oh, I also did this typing mistake. It should be IO. That was also there. Go to game screen. And here bind it that is socket methods, do point increase listener and socket method and n game. It should be end game listener. It looks good enough. Okay. That's it. As you can see, our project is completed. In the next video, I will simply test the complete application. Thank you. 34. Test the Complete Application: Hi, welcome to the final video of our course. Here we will test the complete working of the application. So let's create a room. Let's create this copy it. Past it here. Join that room. Now let's try it. Let's try. If I click on play again. Then the point is not working. Let's see what happened. I go to the index, the Jas file. And if I refresh it here as well. The point increased in the server. So here till here it's working fine. It was mistake. I can see I do a lot of mit go And if I go to game methods or socket methods and here increase. Okay. This was a bug which I fixed. Now, if I again create a join and see. Level gets the point. And if I make prayer win, then she gets the point. And if again Lah wins, then he won. He wins the game, and we are showing directly. I know it's not a very good experience. So dialer box. So here you can just write the logic if you want. It's up to you. That is okay. After clicking on the button, he should go again to the main screen. Again, a new game should open, whatever you want. But as you can see, the app was working perfectly. All the bugs were fixed. So that's it for this video, or you can say for this course. I hope you have enjoyed and learned a lot. Do check out my other courses as well. Do recommend me some topics also on what concepts I should make videos. That's it. Thank you. Have a nice day and keep practicing.