FAQ: Learn Phaser: Basics - Keyboard Events

This community-built FAQ covers the “Keyboard Events” exercise from the lesson “Learn Phaser: Basics”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Phaser

FAQs on the exercise Keyboard Events

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

I was able to move Codey aound as directed. Fun! So I would like to know “how would you make Codey accelerate speed after moving in the same direction for a few frames?”
Thanks -

2 Likes

Look into transition and easing, for some insight into this. We can choose the curve that describes our transition speed at various times for 0 to t.

Define a direction variable and increase speed if the direction is identical on update and reset speed if not.

I wrote the code as it was instructed but when I ran the code Codey was not showing can anyone please help me?
Thanks

Hi,

I’m new to coding.
Has anyone worked out how to accelerate after moving a few frames?
I have been looking around and there seems to be many ways to accomplish, but I can’t quite work out how to implement.
Any insight would be great!

Thanks

2 Likes

so am when you turn a number to negative it goes the other the way insted of being slow i was just messing around and i found out

As for the challenge part, there can be many ways to implement the acceleration. We can make the feature as simple or as complex as we want. Here is one rudimentary implementation of the feature.

Firstly, I chose to interpret the instruction “…make Codey accelerate speed after moving in the same direction for a few frames…” as meaning that we are holding down a cursor key for a period of time. If we are just tapping the key, then there is no acceleration and we just move with the base speed of 5 units. If we hold down a cursor key, then the longer we hold the key, Codey picks up more acceleration depending on how long the key has been kept pressed. Of course, that is not the only way the instructions can be interpreted. I am just making an interpretation that keeps thing fairly simple.

Looking at the documentation for Phaser.Input.Keyboard, I think the repeats property can help in a simple implementation of the task.

repeats :number

If a key is held down this holds down the number of times the key has 'repeated'.

What I did:
In create(), I added a statement just to be on the safe side: gameState.acceleration = 0;
In update(), I made modifications like:

if (gameState.cursors.right.isDown) {
    gameState.acceleration = gameState.cursors.right.repeats * 0.3;
    gameState.codey.x += (5 + gameState.acceleration);
  }

I made similar edits for the other three cursor keys in update().
That’s it.

repeats is an integer. The longer we hold down the key, the more the repeats. i just chose 0.3 arbitrarily as the acceleration increase for every repeat. So, if we hold down the right key for a duration equal to 2 repeats, the acceleration of 0.6 will be added to the base speed of 5 units. If we keep holding the key, the acceleration will keep on increasing and Codey will move faster and faster.

Instead of just a statement to decide the acceleration, we could define a function and send the repeats to the function. In the function, we could customize how the acceleration happens. We could also put a speed limit. I just used a single statement to keep things simple.

In the documentation, there is also the getDuration() method. The method worked in the Phaser Sandbox, but didn’t work in the Codecademy environment, so I chose the repeats approach instead.

If you want to see Codey speed up in the Codecademy browser, you can fiddle with the acceleration of 0.3. Also, keep pressing a key till Codey goes outside the screen. Then, bring Codey back by moving in the opposite direction and you will see Codey speed across the screen depending on how long you have been holding down the key.

6 Likes

getDuration() seems to be the best method here. It is not working in the actual Codecademy environment because it is using the 3.16 version and getDuration() has been added only on 3.17, but you can just update the version in index.html (I did use the 3.52 version) and it will work

1 Like

Initially, I was going to ask if there is a way of moving Codey diagonally because in my first attempt at a solution I used a series of if…else conditionals to implement movement on key presses.
However, after some experimentation I figured it out.
So… for anyone who made the same mistake that I did, this is what happened.

SOLUTION 1:
if(gameState.cursors.right.isDown){
gameState.codey.x += 5;
}
else if(gameState.cursors.left.isDown){
gameState.codey.x -= 5;
}
else if(gameState.cursors.up.isDown){
gameState.codey.y -= 5;
}
else if(gameState.cursors.down.isDown){
gameState.codey.y += 5;
}

This solution let me move Codey up, down, left and right. But, it didn’t let me move him diagonally.
This is because if…else statements are exclusive. If a condition in one of the statements is met, all the rest are skipped.
So… when I pressed ‘right’, my conditional that looked for ‘right’ press was executed and I would move right etc.
But… when I pressed right AND up, because my conditional that looks for the ‘up’ key press was after the conditional that looks for ‘right’, the code from the ‘up’ conditional would be skipped and not execute.
So… what I had coded was a set of priority instructions for Codey. He preferred right, then left, then up, and then down. If I held down right and then left, I would keep on going right. If I held down down and then up, I would start going down then as soon as the up key was pressed I would shoot up etc.

But I didn’t realise this at the time.
So my initial solution was this monstrosity:

//increases x coordinate if only right button is pressed
if(gameState.cursors.right.isDown && !(gameState.cursors.up.isDown || gameState.cursors.down.isDown || gameState.cursors.left.isDown)){
gameState.codey.x += 5;
//decreases x coordinate if only left button is pressed
} else if (gameState.cursors.left.isDown && !(gameState.cursors.up.isDown || gameState.cursors.down.isDown || gameState.cursors.right.isDown)){
gameState.codey.x -= 5;
//decreases y coordinate if only up button is pressed
} else if (gameState.cursors.up.isDown && !(gameState.cursors.right.isDown || gameState.cursors.left.isDown || gameState.cursors.down.isDown)){
gameState.codey.y -= 5;
//increases y coordinate if only down button is pressed
} else if (gameState.cursors.down.isDown && !(gameState.cursors.right.isDown || gameState.cursors.left.isDown || gameState.cursors.up.isDown)){
gameState.codey.y += 5;
}

I made conditionals that excluded multiple key presses.
I then added the following:

//increases x and decreases y coordinates when right and up are pressed together
} else if (gameState.cursors.right.isDown && gameState.cursors.up.isDown){
gameState.codey.x += 5;
gameState.codey.y -= 5;
//increases x and y coordinates when right and down are pressed together
} else if (gameState.cursors.right.isDown && gameState.cursors.down.isDown){
gameState.codey.x += 5;
gameState.codey.y += 5;
//decreases x and y coordinates when left and up are pressed together
} else if (gameState.cursors.left.isDown && gameState.cursors.up.isDown){
gameState.codey.x -= 5;
gameState.codey.y -= 5;
//decreases x and increases y coordinates when left and down are pressed together
} else if (gameState.cursors.left.isDown && gameState.cursors.down.isDown){
gameState.codey.x -= 5;
gameState.codey.y += 5;
}

I made conditional statements for each possible combination of two keys that would make Codey move diagonally.

This made diagonal movement possible but was very lengthy.

After reflecting a bit more on the code, and googling a hunch about the difference between if…else and if…if, I realised that I could do exactly the same thing with much simpler code:

if(gameState.cursors.right.isDown){
gameState.codey.x += 5;
}
if(gameState.cursors.left.isDown){
gameState.codey.x -= 5;
}
if(gameState.cursors.up.isDown){
gameState.codey.y -= 5;
}
if(gameState.cursors.down.isDown){
gameState.codey.y += 5;
}

In this code, every if statement is checked, even if one is executed. By getting rid of the else, I was getting rid of the implied ‘break’ from the if… else sequence after a successful execution.
So for this if… if solution, if I click right and down, the conditionals for both right and down are executed, allowing for diagonal movement.

The only question I really have remaining, which I would really appreciate an answer on if anyone reads this far lol, is this:
Why, if I press THREE keys (such as up, down and right), do I only get the execution of the first two keys I press?
For example, if I press up > left > right, then if all the code is executed I would expect to first go up, then go diagonally up and left, and then to cease movement on the x coordinate as right and left cancel out but still continue up on the y coordinate. However, regardless of the order in which I press three keys down, Codey, bless him, can only process two key presses and seems to completely ignore three or four. This also happened when I then tried to implement this with my if…else version.
Is this a limit to phaser’s ability to execute multiple changes to a game object each update? Or am I not seeing something in my code?
Thanks if you read this far and I hope it was helpful!!! :smiley:

I made Codey bounce!!!
In my shenanigans of using a million if...else statements I made this:

   //bounces up and down if both up and down are pressed
   else if (gameState.cursors.up.isDown && gameState.cursors.down.isDown){
    switch(gameState.codey.bounce) {
      case 3:
        gameState.codey.bounce = -3;
        break;
      case -3:
        gameState.codey.bounce = 3;
        break;
      default:
        gameState.codey.bounce = -3;
        break;
    }
    gameState.codey.y += gameState.codey.bounce;
    //bounces right and left if both up and down are pressed
  } else if (gameState.cursors.right.isDown && gameState.cursors.left.isDown){
    switch(gameState.codey.bounce) {
      case 3:
        gameState.codey.bounce = -3;
        break;
      case -3:
        gameState.codey.bounce = 3;
        break;
      default:
        gameState.codey.bounce = -3;
        break;
    }
    gameState.codey.x += gameState.codey.bounce;
}

I made conditional statements for if the up and down keys were pressed, and for if the right and left keys were pressed. When this happened, I created a new attribute for Codey called bounce (which gave how big the bounce would be) and then using a case-switch alternated between its value being negative and positive every time the update() scene was rerun. This results in him going up and then down by the value of bounce every cycle. Because why not,
3 Likes

Are you seeing this only in Phaser? Maybe try experimenting with a non-Phaser game to confirm that you are only seeing this in Phaser environments. I tried holding three cursor keys simultaneously and it seemed to work for me.

Perhaps these may be offer an explanation.

1 Like

That’s a great explanation, seems to be a hardware limitation on my end! Thanks for that.

I tried this out and this does work, but how does this code know to move Codey?

In step 1, we created a cursor keys object and assigned it to our gameState object giving this object a property name of cursors in our gameState object:
gameState.cursors = this.input.keyboard.createCursorKeys();
createCursorKeys creates an object with properties which contain objects containing information for the four direction keys, the space bar and the shift key.

These keys have properties/members and methods associated with them (you can read about them here). One of the members associated with a key is called isDown. This returns true/false depending on whether the key is being held down. In our update() function, we created an event listener to check whether a specific key is being pressed. If it is being pressed, we increase/decrease the x or y coordinates of Codey depending on which direction key has been pressed. We did all of this in steps 1-3.

I just added a new property to the gameState object called acceleration (I chose this name for the property, it is not a property already existing in the library). Then I used the repeats member/property of the Key class to set the acceleration.

Here’s my code, in case anyone needs some suggestions:

//initialise a property speed inside gameState with the initial speed value for each direction
//
const gameState = {
  speed: {
    speedLeft: 1,
    speedRight: 1,
    speedUp: 1,
    speedDown: 1,
  }
};

function update() {
  if (gameState.cursors.right.isDown) {
    //reset speed rates for other directions
    gameState.speed.speedLeft = 1;
    gameState.speed.speedUp = 1;
    gameState.speed.speedDown = 1;
    //if the player is outside the boundaries make it start from the opposite side
    gameState.codey.x<410? gameState.codey.x+=1*gameState.speed.speedRight : gameState.codey.x=-10;
    //increment speed by a factor of 1% per update
    gameState.speed.speedRight *= 1.01;
  };
  if (gameState.cursors.left.isDown) {
    gameState.speed.speedRight = 1;
    gameState.speed.speedUp = 1;
    gameState.speed.speedDown = 1;
    gameState.codey.x>-10? gameState.codey.x-=1*gameState.speed.speedLeft : gameState.codey.x=410; 
    gameState.speed.speedLeft *= 1.01;
  };
  if (gameState.cursors.up.isDown) {
    gameState.speed.speedLeft = 1;
    gameState.speed.speedRight = 1;
    gameState.speed.speedDown = 1;
    gameState.codey.y>-10? gameState.codey.y-=1*gameState.speed.speedUp : gameState.codey.y=510;
    gameState.speed.speedUp *= 1.01;
  };
  if (gameState.cursors.down.isDown) {
    gameState.speed.speedLeft = 1;
    gameState.speed.speedRight = 1;
    gameState.speed.speedUp = 1;
    gameState.codey.y<510? gameState.codey.y+=1*gameState.speed.speedDown : gameState.codey.y=-10; 
    gameState.speed.speedDown *= 1.01;
  }
};

Cheers :slight_smile:

1 Like

I’m working on Keyboard Events chapter for the “Learn Phaser: Basics” track.
When I add gameState.cursors = this.input.keyboard.createCursorKeys() to the create function,
then add the cursor controls to the update() function, my sprite does not move when I hover, or click my mouse down.
However, the arrow keys do work to make my sprite move.

Here is the solution that was given by Codecademy, and that was what I used, and my mouse clicks still do not work.

So, my question is, is the mouse-click coding meant to work with a track-pad mouse, or are they only meant to work with an external mouse? I have the track-pad mouse on my laptop computer. I do not have way to plug in an external mouse. So, currently, I am able to use the arrows, to make the Codey sprite move, but the mouse clicks do nothing for me.

This is an example of the code that I am talking about…
if (gameState.cursors.down.isDown) {
gameState.codey.y += 5;

… and below is the actual code ( which is the Codecademy solution )

const gameState = {}

function preload() {
this.load.image(‘codey’, ‘https://content.codecademy.com/courses/learn-phaser/codey.png’);
}

function create() {
gameState.codey = this.add.sprite(150, 200, ‘codey’);
gameState.cursors = this.input.keyboard.createCursorKeys();
}

function update() {
if (gameState.cursors.right.isDown) {
gameState.codey.x += 5;
}

if (gameState.cursors.left.isDown) {
gameState.codey.x -= 5;
}

if (gameState.cursors.down.isDown) {
gameState.codey.y += 5;
}

if (gameState.cursors.up.isDown) {
gameState.codey.y -= 5;
}
}

const config = {
type: Phaser.AUTO,
width: 400,
height: 500,
backgroundColor: “#5f2a55”,
scene: {
preload,
create,
update
}
}

const game = new Phaser.Game(config)

As the name suggests input.keyboard.createCursorKeys has to do with the keyboard (createCursorKeys - Phaser 3 API Documentation (beta)) and affects the hotkeys for Up, Down, Left, Right, Space Bar and shift. It doesn’t affect the mouse.

You may want to browse the documentation (Phaser.Input - Phaser 3 API Documentation (beta)) or the examples (Phaser 3.60 Examples)

Thank you so much. :slight_smile: