Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1109305 of Mobile touch controls

  • Revision slug: Games/Techniques/Control_mechanisms/Mobile_touch
  • Revision title: Mobile touch controls
  • Revision id: 1109305
  • Created:
  • Creator: chrisdavidmills
  • Is current revision? No
  • Comment

Revision Content

{{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}

The main advantage of HTML5 in the gaming world is multiplatform: you can build the game once and then play it on a smartphone, tablet, laptop, PC, TV, or even a fridge if it have a browser. The future of mobile gaming is definitely web, and many developers chose the mobile first approach in their game development process.

In this tutorial we will see how easy it is to implement mobile controls in an HTML5 game, and enjoy playing on a mobile, touch-enabled device.

The game Captain Rogers is built with Phaser and managing the controls is Phaser-based, but it could also be done in pure JavaScript. The good thing about using Phaser is that it offers helper variables and functions for easier and faster development, but it's totally up to you which approach you'll chose.

Pure JavaScript approach

We could implement touch events on our own - setting up event listeners and assigning relevant functions to them would be quite straightforward:

var el = document.getElementsByTagName("canvas")[0];
el.addEventListener("touchstart", handleStart, false);
el.addEventListener("touchmove", handleMove, false);
el.addEventListener("touchend", handleEnd, false);
el.addEventListener("touchleave", handleLeave, false);
el.addEventListener("touchcancel", handleCancel, false);

That way touching game's canvas would emit events and thus we could manipulate the player's ship the way we want. Touchstart is fired when the user puts a finger on the screen, touchmove when he moves the finger on the screen while touching it, touchend when the user stops touching the screen, touchleave when the user moves their finger outside of the area listening for events and touchcancel when a touch is cancelled, for example when user moves finger outside of the screen. More about that can be found in the touch events article.

Touch events in Phaser

We don't have to do that on our own, because Phaser offers managing the touch events for us.

Pointer theory

A pointer represents a single finger on the touch screen. Phaser starts two pointers by default, so two fingers at once can perform an action. Captain Rogers game is a simple one, it can be controlled by two fingers - left one moving the ship and right one shooting. There's no multitouch or gestures, everything is handled by single pointer inputs.

You can add more pointers to the game by using this.game.input.addPointer and have up to ten pointers being managed simultaneously. The most recently used pointer is available in this.game.input.activePointer object - the most recent finger active on the screen.

If you need to access a specific pointer, they are available in this.game.input.pointer1, pointer2 etc. They are assigned dinamically, so if you put three fingers on the screen, then pointer1, pointer2 and pointer3 will be active. Removing second finger won't change the other two, and putting it back again will use the first available one, so pointer2 will be used again.

You can easily get coordinates of the most recently active pointer by using this.game.input.x and this.game.input.y variables.

Input events

Instead of using the pointers directly it is also possible to listen for this.game.input events, like onDown, onUp, onTap and onHold:

this.game.input.onDown.add(itemTouched, this);

function itemTouched(pointer) {
    // do something
}

The itemTouched function will be executed when the onDown event will be dispatched by touching the screen. The pointer variable will contain the information about the pointer that activated the event.

This approach uses the generally available this.game.input object, but you can also detect the actions on any game objects like sprites or buttons by using onInputOver, onInputOut, onInputDown, onInputUp, onDragStart or onDragStop:

this.button.events.onInputOver.add(itemTouched, this);

function itemTouched(button, pointer) {
    // do something
}

That way you'll be able to attach an event to any object in the game, like the player's ship, and react to the actions performed by the user.

The interesting advantage of using Phaser is also that the buttons you create will take any type of input, whether it's a touch on mobile or click on desktop.

Implementation

The easiest way to add an interactive object that will listen for the input is creating a button:

var buttonEnclave = this.add.button(10, 10, 'logo-enclave', this.clickEnclave, this);

This one is created in the MainMenu state - it will be placed ten pixels from the top left edge of the screen, will use the logo-enclave image, and execute clickEnclave function when touched. It will work on mobile and desktop out of the box. There are a few buttons in the main menu, including the one that will actually start the game.

For the gameplay though, instead of creating more buttons and covering the small mobile screen with them, we can think of something a little bit different: have invisible areas which respond to the given action. From the design point of view it will be better to make the area of action bigger without covering half of the screen with button images. For example, tapping on the right side of the screen will fire the weapon:

this.buttonShoot = this.add.button(this.world.width*0.5, 0, 'button-alpha', null, this);
this.buttonShoot.onInputDown.add(this.goShootPressed, this);
this.buttonShoot.onInputUp.add(this.goShootReleased, this);

The code above will create a new button using the transparent image which covers right half of the screen. You can assign functions on input down and input up separately if you'd like to perform more complicated actions, but generally in the game touching the right side of the screen will fire the bullets.

Moving the player could be managed by creating the four directional buttons, but we can take the advantage of the touch screens and drag the player's ship around:

var player = this.game.add.sprite(30, 30, 'ship');
player.inputEnabled = true;
player.input.enableDrag();
player.events.onDragStart.add(onDragStart, this);
player.events.onDragStop.add(onDragStop, this);

function onDragStart(sprite, pointer) {
    // do something when dragging
}

We can drag the ship around and do something in the meantime, and react when the drag is stopped.

Dedicated plugins

You could go even further and use dedicated plugins like Virtual Joystick - this is a paid, official one, but you can find free and open source alternatives. The initialization of Virtual Joystick looks like this:

this.pad = this.game.plugins.add(Phaser.VirtualJoystick);
this.stick = this.pad.addStick(30, 30, 80, 'generic');

In the create function of the Game state we're creating a virtual pad, and then a generic stick that have four directional virtual buttons by default. It is placed 30 pixels from the top and left edges of the screen and is 80 pixels wide.

Then, the stick can be pressed during the gameplay in the update function:

if(this.stick.isDown) {
    // move the player
}

We can adjust the player's velocity based on the current angle of the stick and move him.

Summary

Now when the mobile approach is done, let's see how we can add keyboard and mouse support.

{{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}

Revision Source

<p>{{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}</p>

<p class="summary">The main advantage of HTML5 in the gaming world is multiplatform: you can build the game once and then play it on a smartphone, tablet, laptop, PC, TV, or even a fridge if it have a browser. The future of mobile gaming is definitely web, and many developers chose the mobile first approach in their game development process.</p>

<p>In this tutorial we will see how easy it is to implement mobile controls in an HTML5 game, and enjoy playing on a mobile, touch-enabled device.</p>

<p class="note">The game <a href="https://rogers2.enclavegames.com/demo/">Captain Rogers</a> is built with Phaser and managing the controls is Phaser-based, but it could also be done in pure JavaScript. The good thing about using Phaser is that it offers helper variables and functions for easier and faster development, but it's totally up to you which approach you'll chose.</p>

<h2 id="Pure_JavaScript_approach">Pure JavaScript approach</h2>

<p>We could implement touch events on our own - setting up event listeners and assigning relevant functions to them would be quite straightforward:</p>

<pre>
var el = document.getElementsByTagName("canvas")[0];
el.addEventListener("touchstart", handleStart, false);
el.addEventListener("touchmove", handleMove, false);
el.addEventListener("touchend", handleEnd, false);
el.addEventListener("touchleave", handleLeave, false);
el.addEventListener("touchcancel", handleCancel, false);</pre>

<p>That way touching game's canvas would emit events and thus we could manipulate the player's ship the way we want. Touchstart is fired when the user puts a finger on the screen, touchmove when he moves the finger on the screen while touching it, touchend when the user stops touching the screen, touchleave when the user moves their finger outside of the area listening for events and touchcancel when a touch is cancelled, for example when user moves finger outside of the screen. More about that can be found in the <a href="/en-US/docs/Web/API/Touch_events">touch events</a> article.</p>

<h2 id="Touch_events_in_Phaser">Touch events in Phaser</h2>

<p>We don't have to do that on our own, because Phaser offers <a href="https://phaser.io/docs/2.6.1/Phaser.Touch.html">managing the touch events</a> for us.</p>

<h3 id="Pointer_theory">Pointer theory</h3>

<p>A <a href="https://phaser.io/docs/2.6.1/Phaser.Pointer.html">pointer</a> represents a single finger on the touch screen. Phaser starts two pointers by default, so two fingers at once can perform an action. Captain Rogers game is a simple one, it can be controlled by two fingers - left one moving the ship and right one shooting. There's no multitouch or gestures, everything is handled by single pointer inputs.</p>

<p>You can add more pointers to the game by using <code>this.game.input.addPointer</code> and have up to ten pointers being managed simultaneously. The most recently used pointer is available in <code>this.game.input.activePointer</code> object - the most recent finger active on the screen.</p>

<p>If you need to access a specific pointer, they are available in <code>this.game.input.pointer1</code>, <code>pointer2</code> etc. They are assigned dinamically, so if you put three fingers on the screen, then <code>pointer1</code>, <code>pointer2</code> and <code>pointer3</code> will be active. Removing second finger won't change the other two, and putting it back again will use the first available one, so <code>pointer2</code> will be used again.</p>

<p>You can easily get coordinates of the most recently active pointer by using <code>this.game.input.x</code> and <code>this.game.input.y</code> variables.</p>

<h3 id="Input_events">Input events</h3>

<p>Instead of using the pointers directly it is also possible to listen for <code>this.game.input</code> events, like <code>onDown</code>, <code>onUp</code>, <code>onTap</code> and <code>onHold</code>:</p>

<pre>
this.game.input.onDown.add(itemTouched, this);

function itemTouched(pointer) {
    // do something
}</pre>

<p>The <code>itemTouched</code> function will be executed when the <code>onDown</code> event will be dispatched by touching the screen. The <code>pointer</code> variable will contain the information about the pointer that activated the event.</p>

<p>This approach uses the generally available <code>this.game.input</code> object, but you can also detect the actions on any game objects like sprites or buttons by using <code>onInputOver</code>, <code>onInputOut</code>, <code>onInputDown</code>, <code>onInputUp</code>, <code>onDragStart</code> or <code>onDragStop</code>:</p>

<pre>
this.button.events.onInputOver.add(itemTouched, this);

function itemTouched(button, pointer) {
    // do something
}</pre>

<p>That way you'll be able to attach an event to any object in the game, like the player's ship, and react to the actions performed by the user.</p>

<p>The interesting advantage of using Phaser is also that the buttons you create will take any type of input, whether it's a touch on mobile or click on desktop.</p>

<h3 id="Implementation">Implementation</h3>

<p>The easiest way to add an interactive object that will listen for the input is creating a button:</p>

<pre>
var buttonEnclave = this.add.button(10, 10, 'logo-enclave', this.clickEnclave, this);</pre>

<p>This one is created in the <code>MainMenu</code> state - it will be placed ten pixels from the top left edge of the screen, will use the <code>logo-enclave</code> image, and execute <code>clickEnclave</code> function when touched. It will work on mobile and desktop out of the box. There are a few buttons in the main menu, including the one that will actually start the game.</p>

<p>For the gameplay though, instead of creating more buttons and covering the small mobile screen with them, we can think of something a little bit different: have invisible areas which respond to the given action. From the design point of view it will be better to make the area of action bigger without covering half of the screen with button images. For example, tapping on the right side of the screen will fire the weapon:</p>

<pre>
this.buttonShoot = this.add.button(this.world.width*0.5, 0, 'button-alpha', null, this);
this.buttonShoot.onInputDown.add(this.goShootPressed, this);
this.buttonShoot.onInputUp.add(this.goShootReleased, this);</pre>

<p>The code above will create a new button using the transparent image which covers right half of the screen. You can assign functions on input down and input up separately if you'd like to perform more complicated actions, but generally in the game touching the right side of the screen will fire the bullets.</p>

<p>Moving the player could be managed by creating the four directional buttons, but we can take the advantage of the touch screens and drag the player's ship around:</p>

<pre>
var player = this.game.add.sprite(30, 30, 'ship');
player.inputEnabled = true;
player.input.enableDrag();
player.events.onDragStart.add(onDragStart, this);
player.events.onDragStop.add(onDragStop, this);

function onDragStart(sprite, pointer) {
    // do something when dragging
}</pre>

<p>We can drag the ship around and do something in the meantime, and react when the drag is stopped.</p>

<h3 id="Dedicated_plugins">Dedicated plugins</h3>

<p>You could go even further and use dedicated plugins like <a href="https://phaser.io/shop/plugins/virtualjoystick">Virtual Joystick</a> - this is a paid, official one, but you can find free and <a href="https://github.com/Gamegur-us/phaser-touch-control-plugin">open source</a> alternatives. The initialization of Virtual Joystick looks like this:</p>

<pre>
this.pad = this.game.plugins.add(Phaser.VirtualJoystick);
this.stick = this.pad.addStick(30, 30, 80, 'generic');</pre>

<p>In the create function of the <code>Game</code> state we're creating a virtual pad, and then a generic stick that have four directional virtual buttons by default. It is placed 30 pixels from the top and left edges of the screen and is 80 pixels wide.</p>

<p>Then, the stick can be pressed during the gameplay in the <code>update</code> function:</p>

<pre>
if(this.stick.isDown) {
    // move the player
}</pre>

<p>We can adjust the player's velocity based on the current angle of the stick and move him.</p>

<h2 id="Summary">Summary</h2>

<p>Now when the mobile approach is done, let's see how we can add keyboard and mouse support.</p>

<p>{{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}</p>
Revert to this revision