Bouncing ball

By Aurélien Rodot, 6 months ago

This time, it is going to be a lot more dynamic. We are approaching a full game!

Bouncing all over the place

Length 20 minutes

Level Complete beginner

Prerequisites

In the previous workshop, you made a tally counter. You learned to use variables of type `int`. We also looked at if statements and conditions to interact with the player. Finaly, we used a function to draw rectangles to the screen.

So in summary, you made a rectangle move by pressing buttons. So we are not far from having a Pong paddle ;)But a Pong game without a ball is not very fun. This is why we will now code a bouncing ball.

Moving Forward

For our bouncing ball, we would need a new variable called `positionX`, which, like you guessed, stores the X (or horizontal) position of our ball. While we are at it, let's add another variable called `speedX` which keeps track of the speed of our ball along the X axis.

Now, look at this code: it makes the ball move forward on it's own!

```#include

int positionX = 32;
int speedX = 1;

void setup() {
gb.begin();

}

void loop() {
while (!gb.update());
gb.display.clear();

positionX = positionX + speedX;

gb.display.print("positionX: ");
gb.display.print(positionX);
gb.display.print("\nspeedX: ");
gb.display.print(speedX);

gb.display.fillRect(positionX, 32, 4, 4);
}```

When you were taught coordinates, you probably saw something like this where the center is where X and Y are equal to zero, and that X and Y get bigger when you go to the up and to the right. But for screens, this isn't the case.

Coordinates on the Gamebuino META's screen, just like all other screens, have their origin in the upper left corner. Not only that, but the Y values get bigger when you move downwards (the X values grow when moving to the right, just like a regular graph).

This means that the opposite corner (bottom right) is at (`gb.display.width() - 1`, `gb.display.height() - 1`).

Now why did we subtract 1 to get the opposite corner? Well it has to do with the fact that the first pixel has a value of 0 on both axes. Let me put it this way: if you had a screen with only four pixels, and the the first pixel's coordinate was 0, what would be the coordinate of the forth (last) pixel?

Here you can easily see that the forth pixel has a coordinate of 3, not 4. Well the same thing happens with you console's screen! The rightmost pixel has an x coordinate equal to `gb.display.width() - 1`. And the same thing goes for the lowest pixel.

Note: the screen's size is 80 pixels wide by 64 pixels tall. You can check the width by doing `gb.display.print(gb.display.width());` in your code. Or by counting ;). Also note that even if you know this, you should not use `80` instead of `gb.display.width()`, because it is less implicit and is a sort of light obfuscation.

While we are on the topic of screen and positioning, let's take a closer look at how the `gb.display.drawRect()` function works. First, here is its structure:

`gb.display.drawRect(int x, int y, int width, int height);`

Just like the screen, the `X` and `y` passed as parameters are the position of the top left corner of our rectangle. So, knowing this, the bottom right corner of the rectangle has a position of (`x + width - 1`, `y + height - 1`).

Now that this is clear, try to draw the ball higher up the screen. How about drawing the ball so that it is right above the bottom of the screen.

Keeping The Ball In View

Let's launch our little game and see what happens...Hey! the ball just flies off the screen! Well actually that's expected, as we did not use conditions to stop it. So it just keeps going, even off screen. In that case, how could we keep the ball inside of our screen? Well, let's take a look at this algorithm.

```If the ball reaches the right edge
Then go left

If the ball reaches the left edge
Then go right```

So there are a couple of things we must look at:

• How do we make it so that the ball goes towards the left?
• How do we detect the edge of the screen?

Now, before I give you the solution, try to figure it out. Here are a few hints:

Think about what `speedX` does. Play around with its value.

Coordinates on the screen range from `0` to `gb.display.width()`. A value of `0` coresponds to the leftmost pixel, and `gb.display.width()` is the rightmost pixel.

If you are still stuck, here's what we did:

```#include

int positionX = 32;
int speedX = 1;

void setup() {
gb.begin();

}

void loop() {
while (!gb.update());
gb.display.clear();

positionX = positionX + speedX;

// If the ball reaches the left side of the screen
if(positionX < 0){
// Go right
speedX = 1;
}

// If the ball reaches the right side of the screen
if(positionX > gb.display.width()){
// Go left
speedX = -1;
}

gb.display.print("positionX: ");
gb.display.print(positionX);
gb.display.print("\nspeedX: ");
gb.display.print(speedX);

gb.display.fillRect(positionX, 32, 4, 4);
}```

If the ball only moves left and right, this is not going to be a very exiting Pong match :P Why not create `positionY` et `speedY` so that the ball can now move across the screen. But just like the left-right movement, you will need to detect the edge (with `gb.display.height()`) and keep the ball inside the screen. Go ahead and give it a go!

Make us proud on social networks with #gamebuino #bouncingball , we go through them all the time;)

Solution Example

If you are running out of ideas, or need a little guidance, take a look at what we wrote :)

```#include

int positionX = 32;
int speedX = 2;
int positionY = 32;
int speedY = 1;
int ballSize = 8;

void setup() {
gb.begin();

}

void loop() {
while (!gb.update());
gb.display.clear();

// Update horizontal position
positionX = positionX + speedX;

// If the ball reaches the left side of the screen
if(positionX < 0){
// Go right
speedX = 1;
}

// If the ball reaches the right side of the screen
if(positionX > gb.display.width() - ballSize){
// Go left
speedX = -1;
}

// Update vertical position
positionY = positionY + speedY;

// If the ball reaches the top side of the screen
if(positionY < 0){
// Go down
speedY = 1;
}

// If the ball reaches the bottom side of the screen
if(positionY > gb.display.height() - ballSize){
// Go up
speedY = -1;
}

gb.display.setColor(BROWN);
gb.display.print("positionX: ");
gb.display.print(positionX);
gb.display.print("\nspeedX: ");
gb.display.print(speedX);

gb.display.print("\npositionY: ");
gb.display.print(positionY);
gb.display.print("\nspeedY: ");
gb.display.print(speedY);

gb.display.setColor(WHITE);
gb.display.fillRect(positionX, positionY, ballSize, ballSize);
}

```

By Aurélien Rodot, modified by Julien Giovinazzo

Any questions / comments / suggestions, be sure to drop a comment down below!

NEW 3 weeks ago

Juice_Lizard

Merci, c'est corrigé !

NEW 3 weeks ago

Il y a une petite erreur dans les commentaires: c'est écrit deux fois "si la balle atteint le bord gauche" (le second concerne le bord droit donc).

Aurélien Rodot

3 weeks ago

Merci, c'est corrigé !

NEW 3 months ago

@Adamko: You're right, but it would have been nice if you had concurrently given a solution. So, I do.

Fail: The ball is moving out of screen, when it reaches the right side of the the screen.

Solution: We have to subtract the size of the ball. (like in case of bottom touch)

Bugfix:

Change

```// If the ball reaches the right side of the screen
if(positionX > gb.display.width()){```

into

```// If the ball reaches the right side of the screen
if(positionX > gb.display.width() - ballSize){```

and everything works fine.

Greetz & have fun everybody

qpd00z