Pong: Creating Our First Game Objects and Player Characters
Prerequisites
- Configured and created a Phaser game instance.
Overview
In this section, we will cover how to preload assets, create game objects, assign them sprites, set their locations, and get them moving.
Preloading Assets
Now that we have our game instance, it's time to add some game assets to give our players something to look at and control.
Information
The word "assets" has many definitions in the real world. In the context of game development, assets mean any digital content used by the video game to communicate information to the user about the state of the game. This can include audio, visual elements and animations.
Making Our Ball
1. Inside the preload function defined inside of src/game.js add two function calls to this game instance's load.image() method with the following name and path parameter:
| game.js | |
|---|---|
Information
This function tells the game instance to pre-load the images we want to use in the game itself. If you had other assets you wanted to load in such as music or animations, you would define them here as well using their respective load methods.
2. Directly above the create() function, define the following variables and one keys object to use inside of our create() and update() functions. These variables are used throughout our examples:
| game.js | |
|---|---|
Info
You might be wondering why we declare keys as an object and cursors as an empty variable. This is because of how Phaser recognizes keys—it treats all your arrow keys as one pre-defined object called cursors, but other keys have to have their purpose defined individually. You'll notice as you continue through these instructions, we use slightly different language when creating our inputs. Make sure to pay attention to the differences as they do not work interchangeably.
3. Inside the create() function, add your first game object: the ball. By calling this game instance's add.sprite method, it adds a sprite (our preloaded image asset) to the ball, and places it in the center of our board. Find the center by dividing this game instance's width and height properties by two and setting those as the X and Y coordinates for the ball:
| game.js | |
|---|---|
4. Moving to our update() function in the same file, set the initial velocity for our ball to add some behavior to our game object and get it moving:
| game.js | |
|---|---|
5. To ensure the balls location only updates when the game is started, add an if statement that contains all the code inside of our update() function. Inside this if statement, reference our isGameStarted variable:
| game.js | |
|---|---|
Warning
At this point your ball will have stopped moving. Don't worry! This is intended behavior at the moment as we have not set our isGameStarted variable to true. This means that every time the game calls the update() function, it sees the isGameStarted variable is falsey and skips moving the ball.
6. To ensure the ball starts moving when the game is started, add an if statement that sets isGameStarted to true when the game calls the update() function for the first time:
| game.js | |
|---|---|
7. Currently, our ball simply continues in one direction until it dissapears off the edge of the screen. Call the setCollideWorldBounds method on the ball to let the game know this element should detect colliding with the edge of our screen:
| game.js | |
|---|---|
8. Now that the ball is colliding, give it some bounce. Call setBounce on the ball variable to let the game know that when it does collide with something—it should bounce off instead of sticking to it:
| game.js | |
|---|---|
Adding Player Characters: A Tale of Two Paddles
- Call the
thisgame instance'sphysics.add.spritemethod inside of thecreate()function. When declaring our players, it's important to remember that we don't want our paddles to be pressed up against the edge of the screen. To do this, offset the paddlesxandyparameters as well:
Danger
Notice how in this step, the name of the sprite is not the same as the name of the variable. If your sprites are not rendering, it might be because you used the wrong value for the key of our sprite. While it can be helpful to have your assets share a name with your variables, it can cause confusion in larger projects where you might have to reuse the asset elsewhere.
Click To See An Example
2. Now add collision to the paddles. When adding collision, you have to use separate methods for adding collision between game objects and adding collision between a game object and the world. this.physics.add.collider takes two game objects as inputs and creates collision between those two objects. gameObject.setCollideWorldBounds adds collision between a game object and your screen:
3. Next, we need to ensure that when the ball makes contact with our paddle, the paddle does not move—they are immovable. Call the setImmovable method on both player objects inside the create() function:
Input and Control
1. Inside our create() function, call this game instance's input.keyboard.addKey and this.input.keyboard.createCursorKeys to add these keys to our game instance. This lets the game know to watch these keys for events:
2. Inside our update() function, we are going to tell the game what to do when these cursors or keys are pressed and what to do when they are not. We can do so using if statements wrapped around some behavior for our paddles. In this case, we will make it so that triggering these events causes our paddles to gain or lose velocity. Add the if statements:
| game.js | |
|---|---|
Information
You might be wondering what the code means as the wording is odd, cursor.down.isDown? What this actually means is quite simple: isDown in this context means when the key is pressed down.
Information
You might be wondering why we use negative paddle speeds when moving the paddles up. This is because Phaser perceives all positive velocity Y values to be moving from up to down, so if we want to move down to up, we have to use a negative value. If you wanted to make a game where a character moves left and right, you would have to use the same paradigm for the X axis.
3. Make sure that when a key is not being pressed, the paddles stop. Call the player1 and player2 setVelocityY methods in the update() function and assign a velocity of 0 to the paddles:
4. Inside our update() function, clamp the balls velocity. Do this by referring to our paddlespeed inside of an if condition, and changing the balls behaviour if it gets too fast or slow. By setting both these traits, we lock the ball into moving at one speed:
Experiment
Try playing with the speed of the ball by increasing or decreasing its maximum and minimum velocity. Notice how when the max velocity is higher, it can put the players in unwinnable situations where the paddle moves to slowly to meet the ball. How about when it moves slowly? The game gets easier. By changing these values, we can increase and decrease the difficulty of our game!
Success
If you have followed along with the tutorial so far, you should currently have a version of Pong that has two controllable paddles using the S and W keys for one player and the Up and Down arrows for the other.
Code
| game.js | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
Conclusion
By the end of this section, you will have learned the following:
- How to create game objects
- How to give game objects collision properties
- How to create input to control game objects
Well done! Now you can move onto the next step: