- Overview
- Transcript
4.3 New Game Method
Now that we have a form, we’ll need a Meteor method to create the game in our database. This is where we start to use the Chess.js library that provides the game logic for our application.
Related Links
1.Getting Started3 lessons, 11:39
1.1Introduction00:39
1.2Application Demo05:23
1.3Application Setup05:37
2.First Steps4 lessons, 19:19
2.1Organizing Your Code05:44
2.2Set Up a Router07:24
2.3Add User Accounts03:39
2.4Collections02:32
3.The User List Page3 lessons, 23:41
3.1List Users12:38
3.2Making Friends04:57
3.3Write a First Meteor Method06:06
4.The Game List Page4 lessons, 39:05
4.1Waiting for Data08:15
4.2New Game Form08:35
4.3New Game Method09:42
4.4List the Games12:33
5.The Game Page10 lessons, 1:28:25
5.1Get the Game Data04:53
5.2Display the Game: Prep Work11:40
5.3Display the Game12:00
5.4Style the Chess Board02:50
5.5Making Moves: The Event Handler16:54
5.6Making Moves: The Meteor Method10:00
5.7Listing the Moves06:48
5.8Chat Between Users11:56
5.9Reviewing the Game09:29
5.10Deploy the Application01:55
6.Conclusion1 lesson, 00:44
6.1Conclusion00:44
4.3 New Game Method
Now that we've created our form and our user can actually select these values from the drop down, we want to create a new game record in our database when they click the Create Game button. So back here in our games.js file, let's add some code to the bottom here. Let's do Template.games.events and let's wire up a new event handler, and this is going to be 'submit form'. So when that form is submitted, what do we want to do? Well, first step, we want to prevent the default action. So we'll say evt.preventDefault. And that will prevent the page from doing its normal refresh. Then, let's call a Meteor method, and we're going to write that method next. So we'll say Meteor.call and we're gonna call createGame. And there are two things that we need to pass this method. We need to pass it the color that the user chose, and the opponent that they chose to play against. So, we can say, evt.target, which is the form, .color, to get the color field, .value, and then, evt.target.otherPlayer.value. All right, there we go, so yes, otherPlayer and color. All right, so now, let's go ahead and open up our methods file and underneath setFriend here, let's add a new method that we're going to call createGame. Now this function, of course, will take the color and the opponentId. Okay, so the first step is to figure out what the opponent's color will be. So let's say otherColor is a simple name for it. We'll say otherColor = if color is equal to white then the other color will be black, otherwise color must be black so the other player will be white. Then, let's create our game object. And our initial game object will have a couple of fields. One of the fields that we want to add here is the list of moves that have been made in the game. So we'll just store this as an empty string for now because no moves have been made. We're gonna be storing these moves in Portable Game Notation, which is quite common in chess. It's a way of using the algebraic notation of chess to record every move throughout a game. Now beside the moves, we also want to store the current position of every piece on the board. And for this, we're going to use the Forsyth-Edwards Notation. And this is a standard notation for describing a particular board position of a chess game. It's gonna look something like this. As you can see right here, we have the starting position for a standard chess game. Now right now, you don't have to worry too much about what this means. We're going to look at this in more detail later on when we start actually displaying the chessboard. But the good news is, we don't actually have to write this out ourselves because there is a handy library called chess.js. And as you can see, this is a JavaScript chess library for chess move generation and validation, piece placement and movement, and check, checkmate and draw detection. And we're gonna be using this library to manage the actual rules of chess. So deciding whether a piece can move or not, whether we're asking it to move to a valid place when a king is in check, when the game has been checkmated or when it's been drawn. All of that will be figured out by this library for us. Now thankfully, someone else has already turned this library into a Meteor package. So if we come to our terminal here and we can do meteor add and the package is makalu:chess-js. Now that that has installed, we have access to a chess object from within our code. So for the board here, let's create a new Chess object, and then we'll call the fen function. Of course, this stands for Forsyth-Edwards Notation. And this will return the current position of the board in that notation. And of course, for a brand new chess game, we are in the initial state. And, of course, we also need to record the users and their colors. So, we'll say game[color] is going to be this .userId and game[otherColor] is going to be opponentId. Now, of course, when we're initially creating the game, we don't know if this game is actually going to happen or not. So we're going to say game.needsConfirmation and that is going to need to be confirmed by the opponent that the logged in user has selected. So we'll set needsConfirmation to be the opponentId as well. Finally, let's go ahead and do Games.insert and we will insert our game object. Now we could just end there but, instead, we also need to create a conversation to go along with this game. So we will pass a callback function to insert. Now this callback function takes two things, an error and the id of the game object that was just created. So we'll just say if there is an error, then let's go ahead and throw that error. Otherwise, let's say Conversations.insert. And let's create our new conversation, so we'll link it to the game by saying game is the id. And then let's add the users that are playing the game. This will be an array, and we will have this .userId. And actually from within here, this is not going to be the right value. So let's go ahead and bind this function to the right value of this. Okay, so this.userId and also the opponentId that was passed in. And then, we also want to have our array of messages. And let's create an initial message here. And this message is going to have the name of system because it is the system who made this message and not either one of the users. And the text will be Game started and let's add a new date and we'll say .toString. There we go. So this way we have our new game being created. And then we have our new conversation created right along with it, if we know that the game has been successfully created, excellent. All right, so that is all we need to do to create a new game. Now we can't actually see our new game yet because we don't have the games being listed anywhere. However, we can see the effect of this in a couple of places. So right now we're signed in as the user Paul, and this user has two friends Andrew and Cameron. Now if he decides to start a new game with Andrew and I click Create Game. Okay, notice that we have an error here. Let's see, execution in template helper, reference, game is not defined, and it looks like this is within our loop. Okay, so let's come back to our games.js and the problem, of course, is inside of this loop, we never had this problem before because we never had any game records to loop over. The problem here is that in the callback, I used games and I also used games down here on line 12, but then game on line 13. So, let's change that all to game. All right, so if we come back to the browser, and let's try and have Paul create a new game with Andrew again. I'll click Create Game, and let's see, this drop down now, it should only have Cameron but both Andrew and Cameron are showing up. So let's see if we can figure out what the problem is here. If we go to a new Terminal tab and I say meteor mongo, we can log into our database and we can say db.games.find. And let's see. Okay, so we do have a game showing up here. Notice that we have an empty moves string. We have our board with the appropriate syntax. We have white set to one userId. And black set to another userId and it needs confirmation by that other user. Okay, so this game here should mean that Andrew is no longer showing up in the opponent's list here. So let's see what we can do to fix that. Over here in our helpers, let's go ahead in console.log our list of friends at the beginning here. And let's also log it at the end. So we'll log it as soon as we get it and then also after we remove all of the friends that need to be removed. And if we let the page refresh here, you can see that in both cases it's the same and Meteor runs this template twice for some reason. But that's okay, we can still see that in both cases the array does not change. And one of those needs to be removed, in fact, it's this first one here, the one that begins 8PR. And if we go back to our meteor mongo output, you can see here that the black player here is 8PR. And so Andrew, who is 8PR, should not be showing up in this list. So let's go ahead and do console.log. And let's log the color and also the index just to make sure both of those values are being figured out correctly, they should be black and 0. Okay, and when our page refreshes, it seems that we're never actually running anything inside that function, which means we're not finding any games where the result is equal to null. Now, this should work even if result does not exist. And we could actually use games from within here to give this a test. So if I say games.find, and then I have to say .fetch here so it returns the array. It looks like no games are actually being returned. So that's a bit of an issue. If we come back to where we're publishing our games from the server. It seems that, let's see. So our syntax looks like it's correct here. This userid, that should be a capital I. So let's see if that fixes the issue. If we come back here. It looks like that might be the issue. If I refresh the page now, it looks like we only have Cameron. And we're successfully removing Andrew from the array. Okay, that's better. Okay, so let me go ahead and remove these console.log lines. And now, if we let our page refresh one more time we can see that we only have Cameron left in our array here. And if we create a new game with Cameron, notice that this changes to our message, Before starting a game you need to make some friends. Or, maybe you're already playing with all your friends. Excellent, so now we are successfully creating new game objects. The next step, of course, is to list these game objects below here, and so we're gonna do that in the next lesson.