DEV Community

Noah11012
Noah11012

Posted on • Updated on

Using SDL2: Pong 2

Continuing from where we left off, the Paddle class was created to handle several aspects of a paddle. Currently, three methods were made to manage a specific matter regarding your paddles:

  1. handle_input()

Any events not handled by the main window will be addressed in Paddle if the class so does desires.

  1. update()

Updates the state of our paddles including the position, and when we get to it, collision.

  1. draw()

Draws a representation of a paddle namely with a rectangle.

The Paddle class also contains a state for the position and is made up these private method variables:

double m_y;
Type      m_type;
Direction m_direction;
SDL_Rect  m_position;
Enter fullscreen mode Exit fullscreen mode

If you have followed this series from at least the post Using SDL2: Moving an image you will know we encountered a problem with how C++ does arithmetic operations with different types. E.g. adding a double to an int will have the int operand promoted to a double. The gist of the problem is that the frame rate is capped at 60 fps by passing in 1.0/60.0 to update() in the main update loop of Pong. This number is approximately equal to 0.0167 which you will notice is a floating point number. Trying to store a floating point number in a variable that is only intended to hold integer values will truncate the fractional part of the floating point number. To rectify this problem, we have an additional variable to first hold the result of the new position then store it in the correct SDL_Rect member variable. That way the fractional part is preserved in the double variable.

Still with me?

Good.

Additional attributes to the Paddle class is the m_direction and m_type. The first one is an enum class used to hold the current direction to paddle is heading. The second distinguishes itself from the other paddle. We will need this to keep track of what paddle we are handling events for.

enum class Type {LEFT, RIGHT};
enum class Direction {NONE, UP, DOWN};
Enter fullscreen mode Exit fullscreen mode

The logic we use to move the paddles is the following:

void Paddle::handle_input(SDL_Event const &event)
{
    switch(event.type)
    {
        case SDL_KEYDOWN:
            Uint8 const *keys = SDL_GetKeyboardState(nullptr);

            if(m_type == Type::LEFT)
            {
                if(keys[SDL_SCANCODE_W])
                {
                    m_direction = Direction::UP;
                }
                else if(keys[SDL_SCANCODE_S])
                {
                    m_direction = Direction::DOWN;
                }
            } else if(m_type == Type::RIGHT)
            {
                if(keys[SDL_SCANCODE_UP])
                {
                    m_direction = Direction::UP;
                }
                else if(keys[SDL_SCANCODE_DOWN])
                {
                    m_direction = Direction::DOWN;
                }
            }
    }
}
Enter fullscreen mode Exit fullscreen mode

For the update function:

void Paddle::update(double delta_time)
{
    if(m_direction == Direction::UP)
    {
        m_y = m_y - 5.0 * delta_time;
        m_position.y = m_y;
    }
    else if(m_direction == Direction::DOWN)
    {
        m_y = m_y + 5.0 * delta_time;
        m_position.y = m_y;
    }
}
Enter fullscreen mode Exit fullscreen mode

And finally, the draw function:

void Paddle::draw(SDL_Renderer *renderer)
{
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &m_position);
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
Enter fullscreen mode Exit fullscreen mode

SDL2 allows drawing primitives like rectangles. We use a filled rectangle in this situation, however, if your need is an outline of a rectangle, use SDL_RenderDrawRect().

Compile and run.

What's next

In the next post we will get the ball on screen and maybe get collision detection working.

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

Top comments (0)