DEV Community

Noah11012
Noah11012

Posted on • Updated on

Using SDL2: Pong

We're going to jump straight in and make a Pong clone in SDL2 and C++. I've already created three files: main.cpp, pong.hpp, and pong.cpp. Main.cpp only has one job: create an instance of a Pong class and call the method game_loop().

main.cpp:

#include "pong.hpp"  

int main()           
{                    
    Pong pong;       
    pong.game_loop();
}                    
Enter fullscreen mode Exit fullscreen mode

The Pong class that resides in pong.cpp handles our window, renderer, window events and eventually more as we progress through this article.

pong.hpp:

#pragma once                                

#include <SDL2/SDL.h>                       

class Pong                                  
{                                           
public:                                     
    Pong();                                 
    ~Pong() = default;                      

    void game_loop();                       
    void update(double delta_time);         
    void draw();                            

private:                                    
    SDL_Window   *m_game_window;            
    SDL_Event     m_game_window_event;      
    SDL_Renderer *m_game_window_renderer;   
};                                          
Enter fullscreen mode Exit fullscreen mode

pong.cpp:

#include "pong.hpp"                                            

Pong::Pong()                                                   
{                                                              
    SDL_CreateWindowAndRenderer(680, 480, SDL_WINDOW_RESIZABLE,
 &m_game_window, &m_game_window_renderer);                     
}                                                              

void Pong::game_loop()                                         
{                                                              
    bool keep_running = true;                                  
    while(keep_running)                                        
    {                                                          
        while(SDL_PollEvent(&m_game_window_event) > 0)         
        {                                                      
            switch(m_game_window_event.type)                   
            {                                                  
                case SDL_QUIT:                                 
                    keep_running = false;                      
            }                                                  
        }                                                      

        update(1.0/60.0);                                      
        draw();                                                
    }                                                          
}                                                              

void Pong::update(double delta_time)                           
{                                                              

}                                             

void Pong::draw()                             
{                                             
    SDL_RenderClear(m_game_window_renderer);  

    SDL_RenderPresent(m_game_window_renderer);
}                                             

Enter fullscreen mode Exit fullscreen mode

In the constructor, we initialize both the window and renderer using SDL_CreateWindowAndRenderer(). It's a shortcut to creating a window and then creating the renderer from the window. We also allow resizing of the window in case the user is not satisfied with the default dimensions. This has an implication that we must talk about. If we allow resizing of the window, this means our objects in the game will change dimension/shape. We need an independent resolution from the window dimensions. With SDL2 being a fairly low level library, this is easy to accomplish. In the constructor, add the function SDL_RenderSetLogicalSize() that takes a pointer to an SDL_Renderer and two arguments for the width and height.

SDL_RenderSetLogicalSize(m_game_window_renderer, 400, 400);
Enter fullscreen mode Exit fullscreen mode

The next order of business is to create the paddles. Like always, we'll create a class to manage the position, updates and drawing to the screen.

paddle.hpp:

#pragma once                             

#include <SDL2/SDL.h>                    
#include "paddle.hpp"                    

class Pong                               
{                                        
public:                                  
    Pong();                              
    ~Pong() = default;                   

    void game_loop();                    
    void update(double delta_time);      
    void draw();                         

private:                                 
    SDL_Window   *m_game_window;         
    SDL_Event     m_game_window_event;   
    SDL_Renderer *m_game_window_renderer;

    Paddle        m_left_paddle;         
    Paddle        m_right_paddle;        
};                                       
Enter fullscreen mode Exit fullscreen mode

paddle.cpp:

#include "paddle.hpp"                            

Paddle::Paddle(int x, int y)                     
{                                                
    m_position.x = x;                            
    m_position.y = y;                            
    m_position.w = 50;                           
    m_position.h = 100;                          
}                                                

void Paddle::handle_input(SDL_Event const &event)
{                                                

}                                                

void Paddle::update(double delta_time)           
{                                                

}                                                

void Paddle::draw()                              
{                                                

}                                                
Enter fullscreen mode Exit fullscreen mode

We also add the Paddle classes to the private section of the Pong class and initialize them in the constructor initialization list:

pong.hpp:

#include "paddle.hpp"

...

Paddle        m_left_paddle; 
Paddle        m_right_paddle;

Enter fullscreen mode Exit fullscreen mode

pong.cpp:

Pong::Pong(): m_left_paddle(0, (400 / 2) - 50), m_right_paddle(400 - 50, (400 / 2) - 50)
{
    ...
}                                                                                
Enter fullscreen mode Exit fullscreen mode

In the game loop of Pong, any events that are not handled by Pong itself should be sent to the other objects in the game like the paddles.

while(SDL_PollEvent(&m_game_window_event) > 0)       
{                                                    
    switch(m_game_window_event.type)                 
    {                                                
        ...                   
    }                                                

    m_left_paddle.handle_input(m_game_window_event); 
    m_right_paddle.handle_input(m_game_window_event);
}                                                    

Enter fullscreen mode Exit fullscreen mode

What's next?

In the next part, we'll get the left and right paddles moving up and down the screen.

Like always, the source code for this series can be found at my Github repository:

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

Discussion (1)

Collapse
n3u2o profile image
N3U2O

Hey, nice tutorial, thanks for sharing it.

The content of the paddle.hpp file here is wrong, I just thought I'd suggest an edit.

Cheers^