Tuesday, March 3, 2015

Building Mobile Games Using the MVC Pattern



When we first decide to create any application we have to keep in mind that our app can be ported or migrated to other platforms. Maybe we will never have to do it but keeping this in mind we will create a better app. So we will need a good layer design to get this goal. A good way is to follow the MVC (model view controller) paradigm. In a few words:

  • Model: The logic that remains under any application. Also known as Business Rules.
  • View: The tier that paints to the screen.
  • Controller: The middle layer that connects Model and View and handles user events by calling the model and displaying to the screen to the View layer.

Keeping these layers separated will allow you to switch your UI framework with less changes than expected.
If we think in terms of oop, we can  implement this architecture  by creating interfaces between view and controller layers. This will force you to keep this model and avoid the temptation to mix these layers. If you are able to abstract the view layer, it will be easier to implement an application based on the MVC architecture

For instance, look at our view interface that we are using to develop our remote client in our   multiplayer game: “Snake the net”…

public interface ClientNibbles {
 public void getSet();
 public void go ();
 public void update (Board game);
public Movement getMovementDirection();
 public int getPlayerId();
 public int getIdGame();
 public int getnumPlayerGame();
public void setPlayerId(int id);
 public void setIdGame(int idGame);
 public void setnumPlayerGame(int NumPlayerGame);
}

There is actually two main operation to implement: update method and getMovementDirection .  We send, each tick, to the view layer a board object with the position of each players. The view layer just needs to read this object and paint a representation of it to the screen.  The Controller and model layers just deal with the server which movements to do but, once commited, they just send a “photo” to the view layer in order to paint the screen. In the reverse way, the controller layer will get own movements by calling getMovementDirection (). The rest of the interface defines control method to configure an incoming game. I think that is an exciting and simple approach. Isn’t it?

If we follow this proposal of architecture we will just need to port the upper (view) layer in some scenarios. In detail:

Our game is intended to be, at first, an Android game. Therefore, we only have the option of using Java as a programming language. You could be tempted to go to Android Studio (or ADT) and start right away. Wait a minute… Test and debug a mobile game is always more complex compared to an standalone app. Thus, basing on our MVC model, we will make fisrt  a standalone  application, fix bugs and once we have stabilized we will just write the part of android view. Think what you will get:
·        
  •        Keeping just one source of the code (Controller and logic).
  •       Once developed the project in Android, if we detect incidents related to the core It’s easier to come back to standdalone platform to find out the problem instead of using android. Then once  fixed the error, we would  check that everything is ok at mobile scope.

 In our app, we started by implementing a standalone client that implemented the interface defined at view level. This allow us to test the model layer without using any mobile device or simulator, just simple java client apps. By doing this, we are also creating an pure Java game that can be played by his own.


Once stabilized we just need to implement the defined interface (view layer) at android scope. We created dedicated activities, layouts and event custom views to handle this.  Once done, we are able to test the game using two different types of clients: swing java and android clients.

Tests with different remote clients(Java(Android)
But above all, we have to recall that we are designing a multiplayer game. It will be a game that needs someone to accept or discard the movements done by each movement. The asynchronous approach (peer to peer) won’t work since we need someone to decide if a remote movement is on time or late and if we let the clients decide this acceptance or not, it can produce different games in each client… and this would be a disaster. So, we need a mandatory server to handle this. And a server has clients…

So, actually, we have two components to implement: client and server. We also decided to separate these components through interface contracts. So once implemented the server side and deployed where we decided we wouldn't need to change anything (lifecycle apart). While each part implements his side everything will be OK.


Let's turn back at the client side. There are some theories that tell us that remote players in multiplayers games should be  something like a thin client. This means that each client will wait until the server sends the players movement message to paint into the screen. You can imagine how laggy will be perceived by the user. To improve this scenario, and overcome   the perceived latency we decided that clients are going to predict his own movements. We will implement a mandatory server and a client who makes predictions. (The server consolidates and send back to each client the  consolidated movements for each tick.). By doing this, every client can’t move on his own (or almost).


Andoid client screenshot

So the client won't be a thin client. He may also needs to play. Actually, he needs to have the same logic that the server so we will share  the logic code, or almost, by the client and the server. Again we will share the model code between client and server.

There are just Two differences with the server:
  • The client does not consolidate any movement. He just makes his own prediction and moves his own players. He will move the rest of  players once received the consolidated movements by the server
  • If we are wrong in our prediction we will get back to the last tick  and we will replay our own movement based on the server information.


To deal with these differences you  just need to  create an additional layer in order to handle these differences without affecting the common part.

Thursday, February 19, 2015

First Footage


It’s time to make our dreams come true. We have been writing some tech entries about how to do a multiplayer game. Now, you can see how  we have implemented this ideas . Look at the following video: 4 players/snakes online trying to survive:






You can detect easily some client time tick corrections (just notice that client tick is not always the same). In the other hand, it’s not easy to detect that there is one correction at client side. During the game, one movement arrives late to the server so when the consolidated server movements gets back to the client, he’s forced to correct the initial prediction and moves based on server movements. As a user, you will see how an initial movement is quickly modified(our head changes his position).

The best of all is that everything works in a smooth way.

Thursday, February 12, 2015

Cheating Latency



In our last posts we have been dedicating our efforts to reduce the client perceived latency. Let’s check what   we have  focused:
-          We have configured TCP to flush data as soon as it has been generated.
-          We decided to mix TCP & UDP whenever is possible.
-          We create control layers to sync client and server to get a smooth gameplay.
-          We made our own Object Serialization .
All points above are about  technical issues. Now, let’s turn inside our app and let's check if we can enhance its performance.
Summarizing how the server works  will show us some clues about which point can be improved. Let’s look inside:
-        The server and the remote clients wait, initially,  the same gap of time (tick) for each turn.
-          The server wakes up each time tick and consolidates the players movements sent previously by the remote clients.
-        The server sends back a message containing the consolidated movements and tells every client if they have advanced or delayed related to the objective lag between them.
-          The remote clients make some adjustments on the client side to compensate changing latency related to the server.
-          In order to make this work, clients begin their tick before the server in order to compensate each own latency plus certain buffer.
Now, let’s think what we can do to improve this algorithm:

First Enhancement: Try to send  consolidated movements once all player movements have arrived.
As we have seen, the  server  waits until the end of the tick to send back consolidated movements to the client. That’s how it should be, you may think. Sure? Is it strictly mandatory to wait until the end of the server tick if we already have all movements?
Let’ see... We have nothing to do once all movements are received, at server side, except waiting to the conclusion of the tick. So, if we advance the message containing the consolidated movements,  remote  clients will receive sooner that movements and they will paint non own movements before.
As a result, remote clients will see a more fluid and dynamically game and that’s one of our main goals.
            Risks? If the end client  tick time is so close  to the server end tick , we will be in risk of arriving late for the following movements. That’s where our algorithm, described in our last post, works. The following client tick will be shorter than usual in order to keep the same gap related to the server. If it happens very often  we will only feel a faster game and, in fact, this is what we want. Anyway, we always can wait a minimum of time before sending back consolidated movements. In our case, Snake the Net, we have not implemented this guarantee, except at LAN modes,  because we want a fast game and unfortunately, the latency itself introduces more time that we wanted at minimum.
We implemented this approach with sensible results and I recommend to apply similar strategies wherever  is possible.

Second Enhancements: Extra time for the lazy clients
  Let’s think in the opposite way. What if we have lazy clients? What if we add some extra milliseconds to the server tick and then we tell him to recover that time by reducing his tick client? By doing this, we avoid to correct our clients despite he is a really lazy client. We make him to do a fast tick but, in the other hand, we avoid to correct him. In our case this enhancement  help  us by reducing corrections and improving stability. Of course, you have to control if a lazy client is actually a disconnected client. Again, sense common. If he is late several consecutive times, we will disconnect him and replaced by a bot, that they always arrive at time ;-)