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.