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:
handle_input()
Any events not handled by the main window will be addressed in Paddle
if the class so does desires.
update()
Updates the state of our paddles including the position, and when we get to it, collision.
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;
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};
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;
}
}
}
}
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;
}
}
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);
}
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)