Pong Example
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/ to get a better idea about what we are gonna talk about :)

You can check the game code here: View code.
To download the game, use the following link: Download pong.zip
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:onMessage()andmessage().
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.

Start a local webserver of your choice and create a /screen.html in the root directory.
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 theinit()function.
<body onload="init()"> | |
---|---|
| <div class="game"> |
| <canvas id="canvas"></canvas> |
| <div id="score">0:0</div> |
| <div id="wait"></div> |
| </div> |
| </body> |
Theinit()function sets up our canvas, creates player objects and a ball object and most importantly calls thesetupConsole()function.
In thesetupConsole()we construct theAirConsoleobject and assign it to theairconsolevariable.
/** | |
---|---|
| * 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 theonMessage(),onConnect()and theonDisconnect()methods, so we can use them for our needs of the game.
onMessage(device_id, data)
TheonMessage(device_id, data)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 theonMessage(device_id, data)method. Thedevice_idparam is the id of the device which sent the message (E.g.2). Thedataparam is an object and holds custom data, like{ move: 50 }.
onConnect(device_id)
TheonConnect()method gets called when a device connects.
onDisconnect(device_id)
Whenever a device disconnectsonDisconnect()gets called.
setActivePlayers(max_players)

ThesetActivePlayers(max_players)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 callsetActivePlayers(2)method in thecheckTwoPlayers()function to set the first two devices to active players and start the game.
// 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 thecheckTwoPlayers()function.
message(device_id, data)
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).
/** | |
---|---|
| * 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 thescreen.html. The rest of the code is only the game itself, which we won't cover here.
Whenever someone requests an AirConsole game on a mobile device, the /controller.html will be delivered.
Now create a/controller.htmland include the same AirConsole API file as we did in the/screen.html:
<script type="text/javascript" | |
---|---|
| src="https://www.airconsole.com/api/airconsole-1.7.0.js"></script> |
As in the/screen.html, we also create anAirConsole()object and initialize it with the options{"orientation": "portrait"}.
var airconsole; | |
---|---|
| /** |
| * Sets up the communication to the screen. |
| */ |
| function init() { |
| airconsole = new AirConsole({"orientation": "portrait"}); |
| |
| /* |
| * Checks if this device is part of the active game. |
| */ |
| airconsole.onActivePlayersChange = function(player) { |
| var div = document.getElementById("player_id"); |
| if (player !== undefined) { |
| div.innerHTML = (["Left Player", "Right Player"][player]); |
| } else { |
| div.innerHTML = "It's a 2 player game!"; |
| } |
| }; |
| |
| /* |
| * Makes the device vibrate if the screen says so. |
We again overwrite theonMessage()method and also make use of theonActivePlayersChange()method.
onMessage(device_id, data)
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. TheonMessage(device_id, data)method receives now a message from the screen (AirConsole.SCREEN) and with the data{ vibrate: 1000 }.
onActivePlayersChange(player_number)
Whenever the screen callssetActivePlayers(), theonActivePlayersChange(player_number)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 passedplayer_numberto tell if the player is the left or the right paddle. Theplayer_numberstarts at 0, so that the first player will receive 0 and the second 1 as theplayer_numberparam.
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 theairconsole.messagemethod.
/** | |
---|---|
| * Tells the screen to move the paddle of this player. |
| * @param amount |
| */ |
| function move(amount) { |
| airconsole.message(AirConsole.SCREEN, {move: amount}) |
| } |
On anontouchstartevent the move function will be called, which sends a message to the screen. On aontouchendwe again call the move function with a value of 0 and again send a message to the screen.
<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 locally or on your webhost.