 Good afternoon everyone, joining from India and from across the world. Today we have May. May is a software engineer, info developer and a public speaker. She likes talking in tech conferences and taking part in hackathons. May stages yours, all the best. Yay! I'm so happy to be here. Yeah, so hi everyone. First of all, I want to thank you all for joining, taking the time to be here with me today. I'm truly honored and excited to do this talk. And yeah, let's begin. I'll share my screen. Oh, there you go. Can you see my Star Wars screen? Okay. All right. I think we can start. So yeah, like I said, hello everyone. My name is May Baceron. I'm a software engineer. I'm an info developer at Porter. I write in Groovy, Python, Clojure, Node.js, and several other languages on a daily basis. I am a mentor and a public speaker. And yes, I was born Star Wars fan. You can see that in the presentation. You can see that in my background. You know, I don't think you can miss that. So I already did quite a few Clojure talks in my life. And most of the talks that I did were about some game development or maybe just functional programming in general. Or, you know, there were many different talks that I did. And about Clojure. And I think that the main thing was that I showed is just a single-player game. And then somebody that I talked with just approached me. And he said, well, Clojure is nice. But if you ever decide to write a multiplayer online game, well, you can't do that in Clojure. And you know what happens when you tell a developer that they can't do something. I'm in. So, yeah, I decided I am going to write multiplayer online game in Clojure. And I'm going to do that in under 100 lines of code, or at least the backend will be under 100 lines of code. And that's the game that we're going to check out today. So the backend of the game is written in Clojure, as I mentioned. And the front end is written in React.js. And it was written by my friend, thank you for that. So now let's check out the game itself. So what you can see over here is the way the game starts. You can see that we have two windows opened. And you can see that the way that you know that you are the player is if you're a monkey with a little crown on your head, then this is how you know that you are the self. I see that a few more people joined. So just for the sake of those who just recently joined, I'm going to tell you that the game that you see right now, the backend is written in Clojure and the front end is written in React.js. It's just monkeys scattered around the screen. And what these monkeys are trying to do is now we have just one screen and not a split screen. So it will be easier for everyone to see, but you can see the other players over here. So every monkey has their, you know, his own exception above his head, exception type. So for instance, the one that you see right now has a divide by your zero exception. And you can only collect exceptions that match the one that you have on your head. The idea was, you know, enclosure exceptions are kind of annoying. And it's hard to understand what's going on with them. So I was like, oh, what if every person can collect their own, you know, exceptions? I don't know. I thought it was funny at the time. I hope you guys are laughing and girls are laughing somewhere. And if not, you know, I'm laughing for you. Okay. So that's the game. I want you to notice that we have a player that goes around the screen, each person over here, like I said, wants to collect exceptions, but please remember that you can totally do that with any other things. It doesn't have to be exceptions. You can define your own player that will be maybe, I don't know, collect bananas or apples. That's the idea of this game that it's quite simple, but still has enough complications in order for us to be able to talk about the challenges and choices that I had to make when I worked on this game. So let me talk about all of these challenges and choices in, you know, two steps. The first thing that I'm going to talk about is only the challenges. I want to describe what were the challenges for me when I decided to develop a multiplayer online game. And then I will tell you about the choices that I made in order to handle these challenges. Now, when I will go through these challenges, I want you to try to think with yourself, how would you do that? And then later at the Q and A session, I would be so happy if some of you will, you know, step up and participate and tell me, how would you do things if you do it the same like I did? If you've already developed a multiplayer online game, share those thoughts with me and let's do it together. So the first challenge is to define the game flow. What does it mean? You know, in general, you want to define the game that you're going to develop. So you want to define the amount of players. You want to define the movement. Can you move in 2D in two directions, just left and right, or maybe, you know, up and down only, or can you move in four directions? Like just like you saw that our monkeys can go. Also, you want to decide about the boundaries. Can you leave the window just like in Snake, where if the snakes leave the window, then he can come back from the other side, you know, or you can't live the window. This is how I did it with the monkeys game. Monkey, when he reached the end of the window, he can't leave it. And then another thing that you want to remember is you want to handle collisions. How do you do that? If you want to be able to collide with other players, if you want that, if you had a collision with an item, do you want to collect it? Do you want to ignore it? And of course you want to decide if there are winner, winner situation or losing situation. That's it. So the next thing that we want to do is to choose the game architecture. There are several popular ways to define the game architecture. And you've got to think about both the internal architecture and also about the communication between server and, you know, between clients and server. And there is no one right way to do that. Remember that even the biggest gaming companies are still facing this matter today, the communication part and try to make it, you know, the fastest, the best, the easiest. So, you know, then what we need to do is to define not just the communication between the client server, but we also want to define the protocol. Now, what does it mean to define the protocol? We want to define what will be sent in the messages between the client and the server. Do you plan to send only, you know, just specific limited information from the server to the client? What about, you know, all of the images and graphical things where do you hold these? So this is also some of the things that you'll have to consider when I say protocol, you know. How do you, how do a client recognize self? You know, if we have so many players, how does the client recognize if a player is self rather than just other players, stuff like that will be a part of the decisions that you'll have to make. I think one of the last things is managing the game state and what is a game state anyway? Let me talk about that for a minute. So a game state is the mode of the game entities at a given time. For example, the location of the players, the number of players, the number of items to collect, etc. So that's what it means to have to handle the game state. You want to decide who determines the game state. Probably the smartest would be to have the server do that in order to maintain consistency because if, you know, if you have one player deciding on the game state, then, you know, it might cause a few consistency problems if you do that in a different way. But there are architectures that have been doing that over the years. So I can't say that it's completely wrong, right? Okay. Part of, you know, part of the things that you'll have to handle will be adding a new player, handling player movement. What happens when the player has left the game and then handling the player entities, which means what happens to all the things that are scattered around the screen, which is not the player. So we talked about the challenges, and now I'm going to talk about the choices that I made. The first thing that I mentioned was the game flow. So, you know, if I make it into a simpler mode, then you can see that this is actually the game flow that we have. So we have several different players, and each player can move in four directions, and they can all collect items that match their something. So over here, I showed it with simply every player can collect an item that match the color of, you know, their little head. Notice that I defined that there will be no obstacles. It means that the player can move freely, not like in Pac-Man. In Pac-Man, there are not obstacles, but there is like a maze. So that was also something that I decided to do, not to have a maze, not to have obstacles, but it doesn't mean that I won't add it in the next, you know, version of this game. By the way, I don't think I mentioned it, but this is why this talk is called Attack of the Clones 2. That's because this talk is a part of a series of a talk that I do. Every time that I do this talk, it's where when I develop the game a bit further and I show it, so, you know, try to check it out or, you know, find the next talk that I do. If you're interested in seeing the next version of this monkey game. Okay, that was a side note. I'm going back to talk about the main thing. I was talking about the game flow. Let's move forward. So now that we were done with the game flow, I'll tell you about the architecture that I chose. So I chose the client server architecture, which means that there is one server who determines what, you know, the game state, and he sends it to all of the connected clients. This also means that if one player, yeah, notice how it's ugly, ugly arrows. I know, I chose to leave those arrows because I thought, oh, well, they'll know that I am incapable of drawing. So it's okay, right? So what we see over here with my ugly arrows in the screen is how it goes with the architecture that I chose, like what's happening there. We need that if player one made a move, you know, it will be sent to the server. It does not determine the new coordinates of the player. What will be sent to the server is only the fact that the player moved somewhere. And how, you know, maybe if you moved a little bit, if you moved further, but that's what's going to be sent to the server. And so the client will inform the server about that move. Then the server will calculate the new coordination of the player and he will send these coordinates to all of the connected player. Now, you can see that right in the drawing that he sends to player two and to player three. Hey, player one made a moved left. Hey, player three, player one moved left. Actually, an arrow that I now see that I forgot to add is how the server also sends these coordinates to player one itself. So that's missing in the drawing, but I just told you about that. Okay. Now we will talk about defining the communication and protocols between the client and server. So messages protocol. This, what you see over here is actually the first message on the left that is sent from the client to the server on, you know, on the moment of the connection. So what will be sent is just this tiny JSON. And you can see that it's already actually written in a map style and closure, but it's just a JSON that's coming from the client side. And this JSON will only have height and width of the window. And we want to send that to the server. So then the server will be able to determine where he will locate, you know, the first, you know, the player position and all of the things that he has to send back to the client that are based on the side, the size of the window. So now we have on the second message. This is the message that the server will send to the client back once he knows that a client has connected. So let's go over this map. I want you to get familiar with it because we're going to use it throughout the session. We have the first key says self question mark true. Now I want you to notice that it also says player question mark true. And then we have the ID key. So all of these three keys, they say this. First of all, this map describes a player. Second of all, second of all, this player is also self, you know, this is the one that this is the one monkey that needs to have the crown on the head. Okay. And we also sent an ID. Now you can see that it's just a randomly generated you ID. And because we wanted it to be unique. And this is how I determine which player is which, and I make sure that everyone is not someone else. And then the rest of the keys that we have over here X, Y, that's location score, you know, that's how much, how many exceptions you've collected. We also have show true, which determines if this player is connected or not. And then we have exception type. This is what will determine what's written above the player's head. We have collision false. And this is where I decided to determine what happens when somebody collide with the window. If it says collision true, this is how, you know, I handle the collisions part. You'll see that in a little bit and window height and window width. This is these values always change in case the client change them because we always want them to batch what we have in the client side. Okay. Now we, we just saw, okay, I'll go back just for a minute. We just saw these messages. This is how this is how it starts. Okay. The communication between the client and the server. Now throughout the game, what's going on here is that the client only sends use what you see over there client to service sense X plus 10 plus then it means, you know, the movement that was there. And then the server will send. I'm sorry. Okay. So, and then the server will send a message with the updated game state. And you can see over here the player map that we already discussed. And also another map is exception question mark true. These are the exceptions that are scattered around the screen. Okay. Now the way that I did the communication was using Web sockets. I'm not going to talk too much about Web sockets, but this is how it's usually done. The first thing will be an HTTP request from the client to the server. And then it will be an upgrade by the server to a bi-directional open communication, open and persistent until one of the sides closes the channel. That's pretty much it. There is a lot more to say about Web sockets, which I'm not going to do today, but I'm going to talk about the other things that I used the HTTP kit library and closure. Now let's see how to use that library. What you can see over here and now listen, even if you've never written in closure, I just want you to focus on the names of the functions that you see over here. Defend means defining a function. And you can see that we have Defend Web socket handler. And this means that this is where we're handling the web sockets. And this is where we're handling the web sockets. After the connection is open between the client and the server. We have Def Web socket routes. Remember how I told you that Web sockets start with an HTTP request. It happens right there. You see get and then the backslash. That's it. And then we have in the main, it says run server and Web socket routes. It's called the Web socket routes that I defined up here. Now I want to go back to the Web socket handler function that you see over here. What we get is a request. And you can see that it says on close channel, which is saying what happens when the connection is closed? Well, if the connection is closed, what you want to do is call the remove player function. And on receive, this is what will actually happen as long as the connection is open, we want to call the process message function. Now here's the process message function. This function has two modes, either adding a new player. Or updating the player state. These are the two modes, right? Because if a player has just was just added, then I want to do some things. And then it's a whole different thing if I want to update. And you can see that what they are both getting over here is the height and width of the window. And also the specific connection. And this is how I can tell which connection I am currently working on in terms of processing the data that I got. Now I'll briefly talk about how I handled the active connections. You can see that I have an atom, which is with a list in it. And it's our, you know, in closure, it's not really a list. I can call it just collection. So I have a player's collection. And what it means is all what I will have there is all of the active players are going to be added to this collection. Each player is represented as a map. And we already saw the map of a player. You can see that again over here. This is actually where I created new player. You can see that. Do you remember that I said that we have player a question mark? True. This is how we know that this map represents a player and not something else. So we will have many maps like that, that each map describes a different player. How do we know that this map describes a different player? That's because we have the ID key just like we have over here. Okay, let's move forward. Now what we want to do is when the server got a message, I talked about how the thing that the server wants to do is to either add a new player or update an existing player. Another thing is the player, then the server wants to update the other connections about what just happened, right? So we have two functions for that. Just check it out. We have the send message function. Send message function gets two things as an input. We get con, which is a short for connection, and we have message. So it means that this function gets the connection that we want to send the message to and the message to be sent. You can see that I use the send function over here. This is actually a function that is from the HTTP kit library. So send this message to this connection. That's it. Look how short and cute this is. I mean, it's insane. I don't know. I love it. Then we call this function, the send message function. We call it from broadcast message. We call it the send message function. We call it the send message function. What broadcast message function is doing, it receives a message, and then you can see that I call DUSEC. What DUSEC is doing, it actually goes through all of the players list or collection, and it sends the same message to all of the connections. And then that's it. All right. Let's move forward. Now we need to manage the game state. Okay. When I talked about managing the game state, I told you that we want to handle adding a new player, player movement. What happens when the player has left the game? And let's see that. So how do we add a new player? Adding a new player means that first of all, we want to send a message to the player himself, the one that actually created this message happening. You see that I did the self true over here. So that's what we have on the first line in this function. Then we have two calls to DUSEC. Why do I do that? So the first one is because I want to send all of the existing players to DUSEC. I want to send all of the existing players to the new player. Let's say I just joined the game and there are already five or maybe three players over there that I need to iterate over all of these players and send all of them to me, the new one. And then I want to go ahead and send to all of them the new player. I want to update all other players that a new player joined. And then that's it. I want to update the players list. That's the last thing that I do with adding the new connection in. All right. Now we will talk about the player movement. All right. What do we have over here? Now, every time that I call the update player state function, I have been sending the connection and also the new X and new Y into this function. Now the updating of the new values is being done in a different function. It's just a very small function that calculates the previous X plus 10 equals the new X. So I didn't put that in here. And so we get those new values. And then we have the move player. We have the move player function. And then we do the collect because what happens in the collect function is I check whether I need to collect some of those exceptions that were scattered around the screen. And last, I am going to send, I'm going to broadcast the message to all of the connected players. That's it. Okay. Let's move forward now. Player movement. You saw how I called the collect function before. Now I don't think that I want to go into this function. I just wanted to show you that what we're doing over here is we got to make sure that if an item was collected, then I want to remove it from the items map. I want to update the player new score in the player's map. And I need to return the updated player to the player himself. Okay. Now what happens if a player left the game? We just need to remove him from the list of all players. And that's pretty much it, you know, we've been going through all of those things and we are done. So what you see over here is we have the original drawing that I used for the game. You can see it's not as nice as what I had at the end, right? So I want to do a quick summary of what we talked about today before I finish and then we can do the Q&A session. All right. So we talked about the different choices and challenges that you have to make when you develop a multiplayer online game. I told you that there is more than one way to do things. And for me, I went with the simplest way that I found at that moment, because it was important for me to be able to finish that game because sometimes it's super hard to finish side projects. So I start simple and then I upgrade it. And I hope that next time you'll join me when I'll do the next talk and that's it. Let me know if you have any questions. Thank you. I see that there are some questions in the chat and stuff like that. I hope you enjoyed, you know, I can't see any of the participants, but I do hope you enjoyed this talk. So thank you so much. There are quite a few questions. Do you want to attempt these questions now? Or I can basically selectively turn on the participants so that I can turn on the mics of the participants so that they can ask you the questions. Everything works. Whatever works for you. Okay. I could see there is a question from Aditya. Aditya, I'm just like turning the mic on. You can ask the question. Okay. Yeah, it wasn't. Hi, me. Thanks for the talk. It was just a small question. I was curious about the hello. Oh, sorry. I was on mute. I didn't, I didn't hear you. Can you? Am I audible now? Yeah. Yeah, you are. I was just curious about the identification scheme because the ID didn't appear to be a UUID. So I was wondering if like the, the, like when a player registers the server sort of create some ID and gives to the player, like how does that sort of work? Because one other scheme could be like the player might, you know, come up with the UUID of its own and say, okay, this is I and please register me in the game or something like that. I mean, I can't. Okay. So first of all, I, I can't say that the way I handle the identification of each player is, you know, the best in terms of not cheating proof. Okay. I didn't. If somebody wants to cheat on that to monkey's game. Well, it's not there. I would love to hear other people's thoughts on that to be honest, because the way I did it was, you know, it's just the most naive way I defined an ID. And then I, I, you know, based on hoping that the players are honest, obviously, we don't actually want that. But it's, it's a whole different thing to make sure that you have good, you know, ways to prevent cheating. That's, that's a whole different subject. I would love to do a talk about that one day if I'll find good ways to do that. If you have ideas, I'd love to hear yours. I just, I can't hear you. I'm sorry. Well, that one, the thought that I just had was maybe copycats are a feature of the game that it's part of the gameplay. Like you could get a clone or you could get a monkey's copycating you and you can't stop it. Now what do you do? It's actually very funny thing to do. Very small life. Thank you for that. Okay. Yeah. Thank you. Yeah. But seriously, that, I mean that could have sort of like a national equilibrium kind of dynamic to it because you don't know the incentives of all the players and there could be like, like copying can have a cost and copying can have penalties. I don't know. I mean, it could be very interesting gameplay. Exactly. Exactly. You can say there are a few ways to handle that. Not only, I don't think honestly that, you know, just stopping the cheating is the best way. I always think that if you find like, you know, good ways, artistic kind of ways to annoy, but not too much the cheaters, then this could be more fun and helpful. But what do I know? Thank you. Thank you. Thanks. Thanks. Yeah. Any more questions, people? I do want to ask the audience a questions, my question myself, if I may. Has anybody here ever developed their own game or a multiplayer game? I'd love to hear about that too. If you don't have a question, then I'd love to hear about that. Yeah. You folks can raise their hands and then you are more than welcome to share your experience. You can see the raise hand button on the zoom. I do. Oh, no, I'm just asking the audience. They can see. Okay. Okay. By the way, while we're at it, I want to reshare the screen again just to show everyone. I'm not sure if they were able to see it. I want everyone to see my, my Twitter or my email or my LinkedIn. This is where I post a lot about the talks that I do. So if you're interested in hearing in when I come out with the next talk about, you know, the next step of the game or the next part of development or how I evolve it, then this is where you can do that. And I'll also love to hear, you know, your thoughts. If you don't have the time to do that over here, then you can also send to me either here in the chat or to any of those places. Just wanted to say that because I wasn't sure that I did. I always love to chat about. Games and closer and literally anything that is related to functional programming. Yeah. So I'm just saying. What are the more questions. So Sunday's question was, what are the prerequisites to start game game development? Okay. So I think. I hope I got the, the question correctly and that you mean what are the prerequisites in terms of your knowledge? And if that's what you're aiming for, then I think what you should do is just start by reading a little bit about game development from other people. I would go and check out literally other people's code before I would write a single line of code by myself. I think that's always a good place to start to see other people's work. I think that's we, that's what we do as developers anyway in our everyday life. We see other people's work. We use that in order to create new things and to learn from them. And that's how I would start. That's actually how I started honestly. Before I went to writing my own things. I went and I checked out tutorials. I went and I checked out just a code in GitHub. If you want, you can go ahead and check out my GitHub and find this game and start from there. I think that's the best way. Yeah. That's it. Yeah. Thank you. Thank you. So I do not see any more questions.