UDP is great for action based games in which the message exchange frequency is expected to be high and the inherent unreliability of protocol is acceptable. With UDP, the OS doesn’t have the overhead of marshaling, buffering, tracking and acknowledging messages due to which UDP messages arrive at the destination application with a shorter delay as compared to TCP messages.
Action based realtime multiplayer games require a very high message transfer rate. In this kind of games, player has to update it’s position, score, credit at a very high frequency.
In case of packet loss, the following updates will compensate the loss of previous packet.
We’ve developed a simple game which illustrates these concepts.
GamePlay:
This is an accelerometer based game which has three screens:
- Main Activity: User gives its name and connects with AppWarp cloud server
- RoomListActivity: This screen gives user an option to create a new room or to join from a list of existing rooms. If the user selects to create a new room, then it moves to the game-screen and waits for another user to join the same game room as this is a 2 player game. The list of all rooms having one user in them is also displayed and the user can select one of those to start right away.
- GamePlay Activity: The user has to move his monster (red) using the device accelerometer and has to collect the coin from middle of the screen. It also must protect itself from the laser wire (collision with laser wire will reset your position). You can also view your opponent’s activity movement on screen in real-time.
To win the match, you have to get the coin before your opponent.
Handling Accelerometer : The accelerometer is a hardware sensor used to detect a shake motion.You can access these sensors and acquire raw sensor data by using the Android sensor framework.
SensorManager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
Here, this specifies class implement SensorEventListener.
@Override
public void onSensorChanged(SensorEvent event) {
if(isGameRunning){
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
float x = -event.values[0];
float y = event.values[1];
updateMove(Utils.userName, x*10, y*10);
}
}
}
Code Highlights:
- Initialize AppWarp to use UDP: Once you connect with AppWarp then you have to call
theClient.initUDP();
This API checks if device has a full duplex UDP connection or not with the AppWarp server. Incoming UDP Traffic may be blocked if the client is behind certain types of NATs(Network address translation). It determines the connectivity by performing a 3-way handshake with the server over UDP and provides the result in ConnectionListener.onInitUDPDone. In case of lack of connectivity, the server will fall back to sending updates over TCP for the client. Sending can continue over UDP irrespective.
ResultCode:
1. WarpResponseResultCode.SUCCESS : If the client has full duplex UDP connectivity.
2. WarpResponseResultCode.BAD_REQUEST : If the client is unable to receive UDP traffic from the server.
initUDP also sends keep alive messages periodically to maintain its UDP port mapping through the NAT because some NATs will expire the mapping after some.
- Send Data using UDP
private void sendGameResult(String result){
String message = ‘_’+Util.userName +’#'+ result;
theClient.sendUDPUpdatePeers(message.getBytes());
}
private void sendUpdateEvent(float xCord, float yCord){
try{
String message = Util.userName +’#'+ xCord + “@” + yCord;
theClient.sendUDPUpdatePeers(message.getBytes());
}catch(Exception e){
Log.d(“Exception: sendUpdateEvent”, e.getMessage());
}
}
- Handle received byte array update to move the remote player
public void onUpdatePeersReceived(UpdateEvent event) {
if(event.isUDP()){
String message = new String(event.getUpdate());
if(message.startsWith(“_”)){
String sender = message.substring(1, message.indexOf(‘#’)).trim();
String data = message.substring(message.indexOf(‘#’)+1, message.length());
if(sender.equals(Util.userName)==false){
gameScreen.updateResult(data);
}
}else{
String sender = message.substring(0, message.indexOf(‘#’)).trim();
if(sender.equals(Util.userName)==false){
String xCordStr = message.substring(message.indexOf(‘#’)+1, message.indexOf(‘@’));
String yCordStr = message.substring(message.indexOf(‘@’)+1, message.length());
try{
float xCord = Float.parseFloat(xCordStr);
float yCord = Float.parseFloat(yCordStr);
gameScreen.updateMove(sender, xCord, yCord);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
Source Code can be downloaded or viewed from our git repo. If you have any questions or need any further assistance, please feel free to write us at support@shephertz.com
Leave A Reply