Using SDL2: Pong 3
Tags: sdl, cpp, pong
Published: 2018-11-24 02:27:53

For this post, we'll get the ball on the screen. First thing I did was to create a ball class called, well, `Ball`. It follows the same structure as the previous classes: an update and draw methods. One method that makes it stand out from the rest is the `init()` method. This initializes the object and places it at the position we choose.

**Why not use the constructor?**

In the `Pong` class, I added yet another object called `m_ball`. Because SDL2 doesn't provide the feature to draw circles, I went with an image and decided to use SDL2_image again.

Using the constructor initializer list is impossible because the renderer doesn't get created until later, after when `m_ball` is already default initialized.

ball.hpp:

```cpp
#pragma once

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include <random>

class Ball
{
public:
    Ball() = default;
    ~Ball();
    void init(SDL_Renderer *renderer, int x, int y);
    void update(double delta_time);
    void draw(SDL_Renderer *renderer);
private:
    int m_velocity;
    double m_x;
    SDL_Texture *m_image;
    SDL_Rect m_position;
};
```

Ball::init():

```cpp
void Ball::init(SDL_Renderer *renderer, int x, int y)
{
    IMG_Init(IMG_INIT_PNG);

    SDL_Surface *image = IMG_Load("ball.png");
    
    m_image = SDL_CreateTextureFromSurface(renderer, image);
    SDL_FreeSurface(image);

    IMG_Quit();

    m_position.x = x;
    m_position.y = y;

    m_x = m_position.x;

    SDL_QueryTexture(m_image, nullptr, nullptr, &m_position.w, &m_position.h);

    std::random_device dev;
    std::mt19937 rand_gen(dev());
    std::uniform_int_distribution<> dist(0, 1);

    if(dist(rand_gen) == 0)
    {
        m_velocity = -3;
    } else {
        m_velocity = 3;
    }
}
```

Quite a bit is happening in this function. First, we initialize SDL2_image's PNG loader, open an image and save it to an `SDL_Surface`. Next, we convert it into an `SDL_Texture` and free the `SDL_Surface`. Lastly, we quit SDL2_image.

We'll introduce a new function called `SDL_QueryTexture()`. It takes a pointer to an `SDL_Texture` for the attributes we want to query. The rest are output parameters for the data we would like. The first one is a pointer to an `Unit32`. We can see an `SDL_Texture`'s format by using this output parameter. For the next one, we'll wave our hands over and concentrate on the last two. The output parameters for the width and height.

To make this game a little more exciting, we'll randomize the direction the ball goes. If it is 0 then it will move to the left. When a value of one, it goes to the right.

We use some shiny C++ 11 features to get uniform distributions. This is something `std::rand()`  cannot give us. I won't go into much detail but the gist of what I'm doing is creating a random device and then a Mersenne Twister engine. Finally, create a range from 0 to 1 using `std::uniform_int_distribution`.

Depending on the value, we set the `m_velocity` variable to the correct value.

Ball::update():

```cpp
void Ball::update(double delta_time)
{
    m_x = m_x + (m_velocity * delta_time);
    m_position.x = m_x;
}
```

Nothing new.

Ball::draw():

```cpp
void Ball::draw(SDL_Renderer *renderer)
{
    SDL_RenderCopy(renderer, m_image, nullptr, &m_position);
}
```

Nothing new here also.

Just like every other class before it, we call the `update()` method in `Pong`'s update method and the `draw()` method in `Pong`'s draw method.

```cpp
void Pong::update(double delta_time)
{
    ...
    m_ball.update(delta_time);
}
```

```cpp
void Pong::draw()
{
    m_ball.draw(m_game_window_renderer);
}
```

Compile and run.

![](https://thepracticaldev.s3.amazonaws.com/i/v882d9o38x47akfyzwaq.png)

## What's next

Currently, the ball only travels in a straight horizontal line. In the next post, this will be fixed.

Github repository: https://github.com/Noah11012/sdl2-tutorial-code