{{PreviousMenuNext("Games/Techniques/Control_mechanisms/Mobile_touch", "Games/Techniques/Control_mechanisms/Desktop_with_gamepad", "Games/Techniques/Control_mechanisms")}}
Now when we have our mobile controls in place and the game playable on touch-enabled devices, it would be good to add mouse and keyboard support, so the game can be playable also on desktop. That way we can broaden the list of supported platforms the game can be played on.
It's also easier to test the controls-independent features like gameplay on desktop if you develop it there, so you don't have to push the files to a mobile device everytime you make a change in the source code.
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
Let's try to implement the pure JavaScript controls in the game first and see how it will work. First, let's set up the event listener to listen for the pressed keys:
document.addEventListener('keydown', keyDownHandler, false);
Whenever any key is down, we're executing the keyDownHandler
function. Inside of it we can get the code if the key that was pressed and compare it with whatever we currently need. There are no helpers so you have to remember what the given codes are. For example 37
is the left arrow:
function keyDownHandler(event) { if(event.keyCode === '37') { // move left } // else if ... }
If the code of the key that was just pressed is 37
, then we can perform the action assigned to it - move the ship left. If there will be more keys to check we can do it in a switch statement:
document.onkeydown = function(event) { var code = event.keyCode; switch(code) { case 37: { // move left break; } case 38: { // move up break; } case 39: { // move right break; } case 40: { // move down break; } } };
We can write our own KeyCode
object containing the key codes, for example:
var KeyboardHelper = { left: 37, up: 38, right: 39, down: 40 };
That way instead of using the codes to compare the input we could do something like this:
if(event.keyCode === KeyboardHelper.left) { // move left }
And it will work. We can assign any actions in the given cases and situations, with or without Phaser.
Phaser approach
As I mentioned before you can write everything on your own, but you can also take the advantage of built-in Phaser functions that will make your life easier and development a lot faster. All the edge cases, differences between browser implementations of various features are covered by the framework, so you can focus on the actual task you want to do.
Mouse
The mouse interactions in the game are focused on clicking the buttons. In Phaser the buttons you create will take any type of input, whether it's a touch on mobile or click on desktop. That way, if you already implemented the buttons the mobile controls section way it will work out of the box on the desktop too.
var buttonEnclave = this.add.button(10, 10, 'logo-enclave', this.clickEnclave, this);
The button will be placed ten pixels from the top left edge of the screen, will use the logo-enclave
image, and will execute clickEnclave
function when clicked. We can assign actions directly to the buttons:
this.buttonShoot = this.add.button(this.world.width*0.5, 0, 'button-alpha', null, this); this.buttonShoot.onInputDown.add(this.shootingPressed, this); this.buttonShoot.onInputUp.add(this.shootingReleased, this);
The button used for shooting works perfectly fine for both mobile and desktop approach.
If you want to use the mouse's cursor position on the screen you can do so with this.game.input.mousePointer
. Let's assume you'd like to shoot a bullet when the right half of the screen is clicked with a mouse - it would be something like this:
if(this.game.input.mousePointer.isDown) { if(this.game.input.mousePointer.x > this.world.width*0.5) { // shoot } }
If you'd like to differentiate the mouse buttons being pressed, there are three defaults you can pick from:
this.game.input.mousePointer.leftButton.isDown; this.game.input.mousePointer.moddleButton.isDown; this.game.input.mousePointer.rightButton.isDown;
Keep in mind that instead of mousePointer
, it's better to use activePointer
for platform independent input if you want to keep the support for mobile interactions.
Keyboard
The whole game can be controlled with just the keyboard and nothing else. The built in this.game.input.keyboard
object manages the input from the keyboard and have a few helpful methods like addKey
or isDown
. There's also the Phaser.KeyCode object containing all the available keyboard keys:
---IMG-KEYS---
In the main menu of the game we can add an extra way to begin playing. The Start button can be clicked to do so, but we can use the Enter
key to do the same:
var keyEnter = this.game.input.keyboard.addKey(Phaser.KeyCode.ENTER); var keyEnter.onDown.add(this.clickStart, this);
You can use addKey
to add any key Phaser.KeyCode
object can offer. The onDown
function is executed whenever the Enter
key is pressed - it will launch the clickStart
method which starts a new game.
It's only an extra way to do it, but it's an option to play the game on desktop without using a mouse, so you don't have to take your hands off the keyboard.
Controlling the game
We can start supporting the keyboard input in games built with Phaser by creating the basic cursor keys in the create
function:
this.cursors = this.input.keyboard.createCursorKeys();
It creates four directional arrow keys for us:
this.cursors.left; this.cursors.right; this.cursors.up; this.cursors.down;
You can also define the keys on your own and offer an alternative, WASD
control mechanism:
this.keyLeft = this.input.keyboard.addKey(Phaser.KeyCode.A); this.keyRight = this.input.keyboard.addKey(Phaser.KeyCode.D); this.keyUp = this.input.keyboard.addKey(Phaser.KeyCode.W); this.keyDown = this.input.keyboard.addKey(Phaser.KeyCode.S);
Now we have both cursor and WASD
keys depending on the player preferences:
if(this.cursors.left.isDown || this.keyLeft.isDown) { // move left } else if(this.cursors.right.isDown || this.keyRight.isDown) { // move right } if(this.cursors.up.isDown || this.keyUp.isDown) { // move up } else if(this.cursors.down.isDown || this.keyDown.isDown) { // move down }
In the update
function we can now move the player's ship in any direction using one of the two movement keys setup.
To accomodate that we can also offer the usual and the alternative firing controls. For cursor keys the natural shooting button would be on the other side of the keyboard, so the player can use the other hand - for example the X
key, for WASD
keys it can be the Space
:
this.keyFire1 = this.input.keyboard.addKey(Phaser.KeyCode.X); this.keyFire2 = this.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
Then, in the update function we can check if any of those two is pressed:
if(this.keyFire1.isDown || this.keyFire2.isDown) { // fire the weapon }
If yes, then it's time to shoot some bullets! We can even define a secret cheat button:
this.keyCheat = this.input.keyboard.addKey(Phaser.KeyCode.C);
And then in the update function whenever it is pressed:
if(this.keyCheat.isDown) { this.player.health = this.player.maxHealth; }
We can set the health of the player to maximum. Remember: it's a secret, so don't tell anyone!
How to play
We've implemented the controls, and now it's recommended to inform the player about his options to control the game - he wouldn't know about them otherwise. When showing how to play screen where the various ways to control the ship in the game are shown, instead of showing them all we can detect whether the game is launched on desktop or mobile:
if(this.game.device.desktop) { moveText = 'Arrow keys or WASD to move'; shootText = 'X or Space to shoot'; } else { moveText = 'Tap and hold to move'; shootText = 'Tap to shoot'; }
If the game is running on desktop the cursor and WASD
keys message will be shown - if not, then the message we have for mobile will be.
---IMG_HOW_TO_PLAY_SCREEN_DESKTOP---
To skip how to play without setting up a new key for it, we can listen for any key and move on:
this.input.keyboard.onDownCallback = function() { if(this.stateStatus == 'intro') { this.hideIntro(); } };
It hides the intro and starts the actual game.
Pause and game over screens
To make the game fully playable with keyboard it should be possible to go back to the main menu from pause and game over screens, continue playing or restarting the game. It can be done exactly the same as before - by capturing key codes and performing actions. For example, by pressing Phaser.KeyCode.Backspace
or Phaser.KeyCode.Delete
you can hook up the action related to the Back
button in the game.
Summary
Now when the mouse and keyboard controls are in place on top of mobile controls it's time to spice things up and add Gamepad API support which will make the game even more enjoyable.