# Pong in Simple DirectMedia Layer 2

(/home/alkaline) #1

(Note: Pong in SDL2 isn’t 15 characters. Damnit.)

So in my gamedev course we’re coding Pong in SDL2. I’m not done it yet but I thought I’d share the code so far:

``````// Name: Alkaline Thunder
// Course: GAME202
// Prof: SGT. James Heller
// Title of program: Pong
// Date: Jan. 10th, 2019

// Error logging - we need iostream.
#include <iostream>
#include <random>
#include <ctime>

// Include the SDL2 library.
#include "SDL.h"

// Also for error logging so we don't need std:: everywhere.
using namespace std;

// This is the size of the game window.
#define WINDOW_WIDTH 1920
#define WINDOW_HEIGHT 1080

// Are we still running the game?
bool running = true;

// The speed and direction of the ball.
int speedX, speedY;
int direction[2] = { -1, 1 };

// An SDL renderer for the game.
SDL_Renderer* renderer;

// Unknown...
SDL_Event event;

// Holds information about the most recently polled SDL event.
int mouseX, mouseY = 0;

// Holds the player and AI score values.
int PlayerScore, AIScore = 0;

// Rectangles for each object on-screen.

// Checks if two rectangles collide/overlap with each other.
bool IntersectsWith(SDL_Rect& A, SDL_Rect& B)
{
// The sides of each rectangle
int LeftA, LeftB;
int RightA, RightB;
int TopA, TopB;
int BottomA, BottomB;

// Calculate the sides of rectangle A
LeftA = A.x;
RightA = A.x + A.w;
TopA = A.y;
BottomA = A.y + A.h;

// Now do it for Rectangle B
LeftB = B.x;
RightB = B.x + B.w;
TopB = B.y;
BottomB = B.y + B.h;

// If any side of Rectangle A are outside of Rectangle B, the rectangles DON'T collide.
if (BottomA < TopB)
return false;

if (TopA > BottomB)
return false;

if (LeftA > RightB)
return false;

if (RightA < LeftB)
return false;

// If we get this far, the rectangles collide.
return true;
}

// Initializes SDL, the game window, and starts up the game.
{
// Seed the random number generator
srand(time(0));

// Attempts to create a window for the game.
SDL_Window* GameWindow = SDL_CreateWindow("Pong", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

// Create the renderer object
renderer = SDL_CreateRenderer(GameWindow, 0, SDL_RENDERER_ACCELERATED);

// If the window is invalid, throw an error.
if (!GameWindow)
{
cerr << "FATAL: Couldn't start up the SDL window.  Stop." << endl;
return;
}

// Initialize the rectangles to their original positions.
// Starts the player paddle in the center of the Y axis.

// Copies the position of the Player Paddle to the AI paddle to save lines of code.

// Sets the x axis of the AI paddle to the far right of the screen.

// Set the ball size.
Ball.w = Ball.h = 20;

// Set the ball to the center of the screen.
Ball.x = (WINDOW_WIDTH - Ball.w) / 2;
Ball.y = (WINDOW_HEIGHT - Ball.h) / 2;

// Initialize the speed values for the ball.
speedX = speedY = -1;

}

// Processes all user input. I think.
void Input()
{
// Poll events from SDL until we run out.
while (SDL_PollEvent(&event))
{
// Handle the user quitting the game
if (event.type == SDL_QUIT)
{
running = false;
}

// Handle mouse movement.
if (event.type == SDL_MOUSEMOTION)
{
// Grab the mouse's current location.
SDL_GetMouseState(&mouseX, &mouseY);
}

// Handle keyboard presses.
if (event.type == SDL_KEYDOWN)
{
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
// Quit the game.
running = false;
break;
}
}

}
}

void Update()
{
// Set the Y coordinate of the player's paddle based on the mouse's Y position.
PlayerPaddle.y = mouseY - (PlayerPaddle.h / 2); // this also makes it so the paddle is center-aligned to the mouse.

// Move the ball.
Ball.x += speedX;
Ball.y += speedY;

// If the ball is outside the left wall, AI gets a point.
if (Ball.x + Ball.w < 0)
{
AIScore++;
cout << "The AI beat you. They now have " << AIScore << " point(s)." << endl;
}

// If the ball is outside the right wall, then the player gets a point.
if (Ball.x - Ball.w > WINDOW_WIDTH)
{
PlayerScore++;
cout << "You beat the AI. You now have " << PlayerScore << " point(s)." << endl;
}

// If the ball is outside of the left or right of the screen we reset it to the centre.
if (Ball.x + Ball.w < 0 || (Ball.x - Ball.w) > WINDOW_WIDTH)
{
Ball.x = (WINDOW_WIDTH - Ball.w) / 2;
Ball.y = (WINDOW_HEIGHT - Ball.h) / 2;

// Initialize the speed with random numbers.
speedX = (rand() % 2 + 1) * direction[rand() % 2];
speedY = (rand() % 2 + 1) * direction[rand() % 2];
}

if (Ball.y < 0 || (Ball.y + Ball.h) > WINDOW_HEIGHT)
{
speedY = -speedY;
}

// Generate a random byte.
int randByte = rand() % 255;

// If this byte is divisible by 15, we fail to update the AI.
// This results in the AI having an "error," which makes
// it more human.
// if (randByte % 15 == 0)
// {
// Get the distance between the ball and the AI paddle.
int ballCenterY = Ball.y + (Ball.h / 2);

if (aiCenterY > 0 && aiCenterY < WINDOW_HEIGHT)
{
int ballCenterX = Ball.x + (Ball.w / 2);
if (ballCenterX > (WINDOW_WIDTH / 2))
{
int distance = ballCenterY - aiCenterY;

// Normalize the value.
if (distance < 0)
distance = -1;
else if (distance > 0)
distance = 1;

// Multiply the distance by the ball speed. This is the velocity the AI will travel in.
int aiVelocity = distance * abs(speedY);

// Increment the AI Y coordinate by the velocity.
}
}
//}

// Collision check for the player.
{
// X speed goes positive.
speedX = abs(speedX);

// Ball x coordinate goes to the right of the player paddle.
// This fixes the possibility of the ball glitching inside
// the paddle and never being able to escape.
}

// Do the same for the AI.
{
// X speed goes negative.
speedX = -abs(speedX);

// Ball x coordinate goes to the left of the AI paddle.
// This fixes the possibility of the ball glitching inside
// the paddle and never being able to escape.
}

// Slow the game down to 60 ticks per second.
SDL_Delay(4);
}

// Draws the game to the screen based on the current state.
void DrawScreen()
{
// Clear the screen so we can draw on it.
SDL_RenderClear(renderer);

// Render the pong background.
SDL_Rect background{ 0,0,WINDOW_WIDTH,WINDOW_HEIGHT };
SDL_SetRenderDrawColor(renderer, 0x22, 0x22, 0x22, 0xFF);
SDL_RenderFillRect(renderer, &background);

// Set the color to white.
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);

// Draw a line down the center of the screen.
int lineWidth = 4;
SDL_Rect CenterLine = { (WINDOW_WIDTH - lineWidth) / 2, 0, lineWidth, WINDOW_HEIGHT };
SDL_RenderFillRect(renderer, &CenterLine);

// Render the ball.
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
SDL_RenderFillRect(renderer, &Ball);

// Present the backbuffer to the screen.
SDL_RenderPresent(renderer);
}

// Shuts down the game and SDL.
void Quit()
{
SDL_Quit();
}

// Starts up the game loop.
int main(int argc, char* argv[])
{
// Start up SDL.

// Enter the game loop. It ends when running = false.
while (running)
{
// Process player input.
Input();

// Update game state.
Update();

// Render the game world.
DrawScreen();
}

// Tear down SDL.
Quit();

// Tear down C++.
return 0;
}
``````