---
title: Pong Example
slug: pong-example
docTags: 
createdAt: 2024-07-30T11:39:20.337Z
---

In this example you will learn how to use the AirConsole API to communicate between a screen and controllers in a simple Pong-game.

You can play the game here: [https://www.airconsole.com/#https://game.airconsole.com/com.airconsole.testpong.cdn.airconsole.com/2024-02-14-14-52-40/](https://www.airconsole.com/#https://game.airconsole.com/com.airconsole.testpong.cdn.airconsole.com/2024-02-14-14-52-40/) to get a better idea about what we are gonna talk about :)

![](https://api.archbee.com/api/optimize/eODGJqzvP6Walum1Gn5N9/UQ_-qjNU_Gc1nxoiayV_V_image.png)

You can check the game code here: [View code.](https://github.com/AirConsole/games-pong)

To download the game, use the following link: [Download pong.zip](https://github.com/AirConsole/games-pong/archive/master.zip)

### *Basic message exchange between a screen and controllers:*

AirConsole and its API makes it very easy for game developers to build games, which can be controlled by a smartphone - instead of e.g. a keyboard or a mouse.

The whole communication can be pretty much summed up with two methods of the API:<font color="#eb144c">`onMessage()`</font>and<font color="#eb144c">`message()`</font>.

All devices (screen and controllers) share the same API - thus there are (almost) no controller or screen specific methods for the communication.

In the following we will explain you in detail how players can control their paddles in a simple, but fun game like Pong.

![](https://api.archbee.com/api/optimize/eODGJqzvP6Walum1Gn5N9/WtnChVPLUjodP-lYvjRsK_image.png)

### */screen.html*

Start a local webserver of your choice and create a <font color="#eb144c">`/screen.html`</font> in the root directory.

:::BlockQuote
You can check the code of the whole <font color="#eb144c">`screen.html`</font> in [this repo](https://github.com/AirConsole/games-pong/blob/master/screen.html)
:::

Include the AirConsole API file:

|   |     \<script type="text/javascript" src="https\://www\.airconsole.com/api/airconsole-1.7.0.js">\</script> |
| - | --------------------------------------------------------------------------------------------------------- |

Our game will run on a canvas element, have a score and a "wait message". As soon as the document is ready, we call the<font color="#eb144c">`init()`</font>function.

```html
<body onload="init()">
    <div class="game">
      <canvas id="canvas"></canvas>
      <div id="score">0:0</div>
      <div id="wait"></div>
    </div>
  </body>
```

The<font color="#eb144c">`init()`</font>function sets up our canvas, creates player objects and a ball object and most importantly calls the<font color="#eb144c">`setupConsole()`</font>function.

In the<font color="#eb144c">`setupConsole()`</font>we construct the<font color="#eb144c">`AirConsole`</font>object and assign it to the<font color="#eb144c">`airconsole`</font>variable.

```javascript
//* Sets up the communication to game pads.* /
function setupConsole() {
  airconsole = new AirConsole();
  airconsole.onConnect = function (device_id) {
    checkTwoPlayers();
  };
  airconsole.onDisconnect = function (device_id) {
    var player = airconsole.convertDeviceIdToPlayerNumber(device_id);
    if (player != undefined) {
      // Player that was in game left the game.
      // Setting active players to length 0.
      airconsole.setActivePlayers(0);
    }
    checkTwoPlayers();
  };
  airconsole.onMessage = function (device_id, data) {
    var player = airconsole.convertDeviceIdToPlayerNumber(device_id);
    if (player != undefined && data.move !== undefined) {
      paddles[player].move.y = data.move;
    }
  };
}
```

After that, we overwrite the<font color="#eb144c">`onMessage()`</font>,<font color="#eb144c">`onConnect()`</font>and the<font color="#eb144c">`onDisconnect()`</font>methods, so we can use them for our needs of the game.

<font color="#eb144c">`onMessage(device_id, data)`</font>

The<font color="#eb144c">`onMessage(device_id, data)`</font>method listens for all incoming messages. In the screen-context it means that it receives all data which the controllers send. In our pong-game, whenever a player presses the up or down button on its device, the screen receives a messages and that is handled in the<font color="#eb144c">`onMessage(device_id, data)`</font>method. The<font color="#eb144c">`device_id`</font>param is the id of the device which sent the message (E.g.*2*). The<font color="#eb144c">`data`</font>param is an object and holds custom data, like<font color="#eb144c">`{ move: 50 }`</font>.

<font color="#eb144c">`onConnect(device_id)`</font>

The<font color="#eb144c">`onConnect()`</font>method gets called when a device connects.

<font color="#eb144c">`onDisconnect(device_id)`</font>

Whenever a device disconnects<font color="#eb144c">`onDisconnect()`</font>gets called.

<font color="#eb144c">`setActivePlayers(max_players)`</font>

![](https://api.archbee.com/api/optimize/eODGJqzvP6Walum1Gn5N9/uVfEFdzRQHMa-SSDTP8dT_image.png)

The<font color="#eb144c">`setActivePlayers(max_players)`</font>was introduced to avoid confusion with device ids. You can use it as a helper method which tells which devices should get a player number. It basically maps your controller devices to a zero-based player number.

**Set active players**

When a player connects and we have at least two controllers connected, we call<font color="#eb144c">`setActivePlayers(2)`</font>method in the<font color="#eb144c">`checkTwoPlayers()`</font>function to set the first two devices to active players and start the game.

```javascript
// Only update if the game didn't have active players.
if (active_players.length == 0) {
  if (connected_controllers.length >= 2) {
    // Enough controller devices connected to start the game.
    // Setting the first 2 controllers to active players.
    airconsole.setActivePlayers(2);
    resetBall(50, 0);
    score = [0, 0];
    score_el.innerHTML = score.join(":");
    document.getElementById("wait").innerHTML = "";
  } else if (connected_controllers.length == 1) {
    document.getElementById("wait").innerHTML = "Need 1 more player!";
    resetBall(0, 0);
  } else if (connected_controllers.length == 0) {
    document.getElementById("wait").innerHTML = "Need 2 more players!";
    resetBall(0, 0);
  }
}
```

Otherwise we just display that more players are needed to play the game.

**Set no active players**

When an active player disconnects and there are not enough active players left we want again to display "*It's a 2 player game!*" on the controller and on the screen "*Need X more player!*". When the leaving player was active in the game, we set all active players to 0, before calling again the<font color="#eb144c">`checkTwoPlayers()`</font>function.

<font color="#eb144c">`message(device_id, data)`</font>

The message method sends a message to another device. In our pong game, whenever a player wins, we send a message to this device and let the device vibrate (if supported).

```javascript
/**
 * Sends a message to the device that it should vibrate;
 */
function vibrate(player) {
  airconsole.message(
    airconsole.convertPlayerNumberToDeviceId(player),
    { vibrate: 1000 })
}
```

How that works is explained below in the controller.html.

Thats basically all AirConsole relevant code of the<font color="#eb144c">`screen.html`</font>. The rest of the code is only the game itself, which we won't cover here.

### */controller.html*

Whenever someone requests an AirConsole game on a mobile device, the <font color="#eb144c">`/controller.html`</font> will be delivered.

Now create a<font color="#eb144c">`/controller.html`</font>and include the same AirConsole API file as we did in the<font color="#eb144c">`/screen.html`</font>:

```html
<script type="text/javascript" src="https://www.airconsole.com/api/airconsole-1.7.0.js"></script>
```

As in the<font color="#eb144c">`/screen.html`</font>, we also create an<font color="#eb144c">`AirConsole()`</font>object and initialize it with the options<font color="#eb144c">`{"orientation": "portrait"}`</font>.

```javascript
/**
 * Sets up the communication to game pads.
 */
function setupConsole() {
  airconsole = new AirConsole();

  airconsole.onConnect = function (device_id) {
    checkTwoPlayers();
  };

  airconsole.onDisconnect = function (device_id) {
    var player = airconsole.convertDeviceIdToPlayerNumber(device_id);
    if (player != undefined) {
      // Player that was in game left the game.
      // Setting active players to length 0.
      airconsole.setActivePlayers(0);
    }
    checkTwoPlayers();
  };

  airconsole.onMessage = function (device_id, data) {
    var player = airconsole.convertDeviceIdToPlayerNumber(device_id);
    if (player != undefined && data.move !== undefined) {
      paddles[player].move.y = data.move;
    }
  };
}
```

We again overwrite the<font color="#eb144c">`onMessage()`</font>method and also make use of the<font color="#eb144c">`onActivePlayersChange()`</font>method.

<font color="#eb144c">`onMessage(device_id, data)`</font>

This time we listen for all messages, which were sent from the screen. As already mentioned, whenever a player wins, the device of the player should vibrate. The<font color="#eb144c">`onMessage(device_id, data)`</font>method receives now a message from the screen (AirConsole.SCREEN) and with the data<font color="#eb144c">`{ vibrate: 1000 }`</font>.

<font color="#eb144c">`onActivePlayersChange(player_number)`</font>

Whenever the screen calls<font color="#eb144c">`setActivePlayers()`</font>, the<font color="#eb144c">`onActivePlayersChange(player_number)`</font>method will be called on the controllers, which are set to active. Use this method to tell your controller it is an active device in your game. In our Pong game we use the passed<font color="#eb144c">`player_number`</font>to tell if the player is the left or the right paddle. The<font color="#eb144c">`player_number`</font>starts at 0, so that the first player will receive *0&#x20;*&#x61;nd the second *1&#x20;*&#x61;s the<font color="#eb144c">`player_number`</font>param.

**Sending a move event from controller to the screen**

To tell the screen that a player wants to move his paddle up or down we use the<font color="#eb144c">`airconsole.message`</font>method.

```javascript
/**
 * Tells the screen to move the paddle of this player.
 * @param amount
 */
function move(amount) {
  airconsole.message(AirConsole.SCREEN, {move: amount})
}

```

On an<font color="#eb144c">`ontouchstart`</font>event the move function will be called, which sends a message to the screen. On a<font color="#eb144c">`ontouchend`</font>we again call the move function with a value of 0 and again send a message to the screen.

```html
<div class=button ontouchstart="move(-50)" ontouchend="move(0)" onmousedown="move(-50)" onmouseup="move(0)">
  <div class="button_label">UP</div>
</div>
<div style="height: 8%"></div>
<div class=button ontouchstart="move(50)" ontouchend="move(0)" onmousedown="move(50)" onmouseup="move(0)">
  <div class="button_label">DOWN</div>
</div>
```

That's it! That's all you need to let your screen and controllers communicate!

Learn more about [how to test your game](https://developers2.airconsole.com/testing-your-game) locally or on your webhost.
