When I first created the local game I made all players that were not controlled by people just go back and forth just to add something dynamic to the game. However these were not especially fun to play against. The game is still designed to be a multiplayer game for four people, but since I want anyone to be able to just click play and get started immediately I still need the other players to move which is where the AI comes in.
I started working on the AI yesterday and made it move in the direction the ball(s) were relative to the paddle. This was easily done by just taking the dot product between the paddle’s forward vector and the vector between the paddle and the balls position + a vector in the direction of the balls velocity, making it look like its predicting the path of the ball. This way the paddle moves left or right to always be able to deflect the ball. And this is exactly what it did as long as there was only one ball. With two balls it did miss the ball sometimes since it prioritized the ball closest to the paddle and could only move with the same speed as the player.
However it is not very fun to play against an unbeatable opponent, so what I have done today is tried to make the AI more dumb, while still appearing intelligent. The way I did this was by only tracking balls that were moving in the direction of the paddle and are within a certain distance from the paddle since this is how many real players think (and moving towards the middle when the balls are moving away). The result is fairly good and is not impossible to score against, albeit quite difficult. Since I am making a multiplayer game I have decided to keep the AI in this relatively good state and not spend more time on perfecting something not central to the game but instead move on to the powerup(s) and other things concerning the logic of the game.
I decided to change the plan a little bit by starting the gui work this week instead of next mostly since I discovered that it was not easy to leave and start a new game. So in order to debug easier I created a simple gui which I then just continued to work on. Right now I have a main menu where the player input their name which makes the play button appear. There is also an options and a help button but these are not implemented yet. At the bottom I put a link to the blog. I have also made an in-game menu from which the player can leave the game and return to the main menu. The options and help buttons will also be implemented in this menu. And after some work it is now possible to join a game, play a bit and then leave, without reloading the page or anything crashing. This process is perfectly in line with the goal of being able to start a match immediately and play for the duration you want, instead of waiting to find other players.
I think I will finish the menus tomorrow or Friday morning and will then start work on smarter AI’s.
So far this week I have not made huge strides in the development. Most of the time has been spent implementing interpolation for the balls and paddles so their positions don’t have to sent each and every frame. Right now I send ball position every ~50ms and paddle position every 80ms. The reason I don’t send the paddle positions as often as the ball position is because the client predicts its own movement which is correct in almost every case (the exception is when the paddle stops ). So the players position is extremely close to that on the server and must therefore not be synced as often. Regarding the other players they don’t directly interact with the player and so they don’t have to be that precise. The ball however has currently no extrapolation so the ball on the client is rendered in the place it was ~50ms ago. I think this is sufficiently precise 80ms however is not.
I also added a precision control for the player using shift. This enables more control of the bounce direction by making the movement speed slower..
Since the game looks almost the exact same i have not included any screenshots this time.
After the first milestone I started implementing the network using socket.io. The plan was to just copy most of the client side code and remove the unnecessary parts like graphics and input but this did not turn out as I was hoping.
I quickly realized that I used stuff like Three.js vectors and 3d matrices for the paddle movement. So most of yesterday I spent on changing all that to use the PhysicsJS vectors instead and to use 2d transformations which is faster and which I then moved back to the client.
I created two networkmanagers for both the client and the server: LobbyManager and NetworkSession. Even though the game will not feature a traditional lobby, but instead just place you in the first game available and fill the non-player spots with AI opponents, I still need something that manages all the games, how many spots are available in each game and what players are in what game. This is the responsibility of the LobbyManager on the server side. On the client it just creates a socket and connects to the server. Then when it receives an id for which game it was assigned to it starts the GameManager.
The NetworkSession classes are in charge (to some extent) of the communication between the server and the client in-game. They have functions for sending data to all players in a game or just a specific socket. In other network games I have worked on I usually have a networkmanager which is in charge of sending and receiving all network traffic in which other parts of the game adds data to a queue which will be sent. However socket.io is more event-based: you register for a callback on a certain message and execution of that function is then left to the framework and will be done asynchronously. This has led me to do some stuff that at first look quite bad but as the game takes shape seems like a good solution. For example on client disconnect I have registered two callbacks: one in LobbyManager which removes the socket from all lists and one in Player which resets the player to an AI entity. Another example is player movement for which I register and send only in Player. I have not implemented enough code yet to decide if this will work though.
The stable site will probably stay the same for a few days until I have gotten something working without crashing or freezing.
I have spent most of today testing out the Web audio API to play a simple sound effect. I thought this was an important test since I have read about many other web game developers having problems with playing sound.
The test site loads a short audio clip using an XMLHttpRequest and can play it in a loop or just a one shot. I had some problems getting it to work for both Chrome and Firefox which turned out to be a problem with the sound output on my computer. Chrome chose one automatically whilst Firefox used the one set in the sound settings
Anyway I think it ought to work in both browsers now which is very good news since I can now begin with the development of the game.