Jump to content
  • Advertisement
Sign in to follow this  
W84M3

Code Review - Pong

This topic is 1051 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I don't know if this is allowed, but since i read in this archive that it was recommended so we beginners can improve here is my code for the game Pong:

I've watched some video tutorials about how to make pong.

I've used C++ with SDL2.

#include "SDL.h"
#include "SDL_ttf.h"
#include <iostream>
#include <stdlib.h>
#include <ctime>
#include <string>

using namespace std;

// Default positions for the Rects
const int BALL_X = 390;
const int BALL_Y = 290;

const int Player_X = 20;
const int Player_Y = 250;

const int AI_X = 770;
const int AI_Y = 250;

int score_Player = 0;
int score_AI = 0;

bool running;

//SDL STUFF
SDL_Window *window = NULL;
SDL_Renderer *renderer= NULL;
SDL_Event event;

SDL_Rect rect_Player;
SDL_Rect rect_AI;
SDL_Rect rect_Ball;

//SDL_TTF STUFF
SDL_Color White = { 255, 255, 255 , 0};
TTF_Font* Sans;

// Ball Velecities
int xVel;
int yVel;

//Get random number between high and low
int GetRandomNumber(int high, int low)
{
return rand() % high + low;
}

//Reset the ball and the players to the default position and gives teh inicial boost to the ball
void ResetGame()
{
rect_Player.x = Player_X;
rect_Player.y = Player_Y;

rect_AI.x = AI_X;
rect_AI.y = AI_Y;

rect_Ball.x = BALL_X;
rect_Ball.y = BALL_Y;
xVel = GetRandomNumber(2, -2);
yVel = GetRandomNumber(2, -2);
//Horizontal speed is always 2 ou -2
if (xVel >= 2 || xVel >=0)
{
xVel = 2;
}
if (xVel < 0)
{
xVel = -2;
}
}

//Test if a point (a,b) is inside rect
bool PointInRect(int a, int b, SDL_Rect rect)
{
if (a > rect.x && b > rect.y && a < rect.x + rect.w && b < rect.y + rect.h)
{
return true;
}
return false;
}

//Test colision between rect1 and rect2
bool TestColision(SDL_Rect rect1, SDL_Rect rect2)
{
if (PointInRect(rect1.x, rect1.y, rect2) || PointInRect(rect1.x + rect1.w, rect1.y, rect2) || PointInRect(rect1.x, rect1.y + rect1.h, rect2) || PointInRect(rect1.x + rect1.w, rect1.y + rect1.h, rect2))
{
return true;
}
return false;
}

//Starts the window, the renderer and sets the position of the PLayer, Ball and AI and loads the font for the score
void LoadGame()
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return;
}

if (TTF_Init()!= 0){
std::cout << "SDL_Init Error: " << TTF_GetError << std::endl;
return;
}

window = SDL_CreateWindow("Pong!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);
if (window == nullptr){
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return;
}

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED );
if (renderer == nullptr){
SDL_DestroyWindow(window);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return;
}

SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);

SDL_RenderClear(renderer);

SDL_RenderPresent(renderer);

rect_Player.h = 100;
rect_Player.w = 10;

rect_AI.h = 100;
rect_AI.w = 10;

rect_Ball.h = 20;
rect_Ball.w = 20;
rect_Ball.x = BALL_X;
rect_Ball.y = BALL_Y;

srand((int)time(0));

Sans = TTF_OpenFont("Sans.ttf", 19);
ResetGame();
}

//Keeps tabs on score x=1 - AI Scored! x=2 - Player Scored!
void Score(int x)
{
if (x == 1)
{
score_Player += 1;
}
if (x == 2)
{
score_AI += 1;
}
}

//Game logic - Movement of the ball and the players...colision tests and score update
void GameLogic()
{
//Delay so the game doesnt run too fast on my PC
SDL_Delay(10);

//Event Manager
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_KEYDOWN:
/* Player Movement */
switch (event.key.keysym.sym)
{
case SDLK_w:
rect_Player.y -= 10;
break;
case SDLK_s:
rect_Player.y += 10;
break;
default:
break;
}
break;
case SDL_QUIT:
running = false;
break;
}

//Ball Movement
rect_Ball.x += xVel;
rect_Ball.y += yVel;

//AI Movement
//AI starts moving only when ball gets to his half of the map
if (rect_Ball.x > 400)
{
if (rect_AI.y + 0.5*rect_AI.h > rect_Ball.y + 0.5*rect_Ball.h)
{
rect_AI.y -= 3;
}

if (rect_AI.y + 0.5*rect_AI.h < rect_Ball.y + 0.5*rect_Ball.h)
{
rect_AI.y += 3;
}
}

//Player Top and Bottom limits
if (rect_Player.y < 1)
{
rect_Player.y = 1;
}

if (rect_Player.y + rect_Player.h > 599)
{
rect_Player.y = 599 - rect_Player.h;
}

//Ball Top and Bottom limits
if (rect_Ball.y < 1)
{
yVel = -yVel;
}

if (rect_Ball.y + rect_Ball.h > 599)
{
yVel = -yVel;
}

//Ball Left and Right limits
//When the ball touches the limits someone scored!
//1 - The player
//2 - The AI
if (rect_Ball.x + rect_Ball.w > 801)
{
ResetGame();
Score(1);
}

if (rect_Ball.x < -1)
{
ResetGame();
Score(2);
}

//AI Top and Bottom limits

if (rect_AI.y < 1)
{
rect_AI.y = 1;
}

if (rect_AI.y + rect_AI.h > 599)
{
rect_AI.y = 599 - rect_AI.h;
}

// Test colision Ball-Player
if (TestColision(rect_Ball, rect_Player))
{
xVel = -xVel;
}

// Test colision Ball-AI
if (TestColision(rect_Ball, rect_AI))
{
xVel = -xVel;
}
}

//Renders the Rects into the window
void DrawScreen()
{
//Renders the Ball the Player and the AI
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

SDL_RenderClear(renderer);

SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

SDL_RenderFillRect(renderer, &rect_Player);

SDL_RenderPresent(renderer);

SDL_RenderFillRect(renderer, &rect_AI);

SDL_RenderPresent(renderer);

SDL_RenderFillRect(renderer, &rect_Ball);

SDL_RenderPresent(renderer);

//PLAYER_SCORE

string PScore = "Player: " + to_string(score_Player);

SDL_Surface* scorePlayerMessage = TTF_RenderText_Solid(Sans, PScore.c_str() , White); 

SDL_Texture* playerMessage = SDL_CreateTextureFromSurface(renderer, scorePlayerMessage);

int Pw = scorePlayerMessage->w;
int Ph = scorePlayerMessage->h;

SDL_FreeSurface(scorePlayerMessage);

SDL_Rect rect_PlayerScore = { 145, 10, Pw, Ph };

SDL_RenderCopy(renderer, playerMessage, NULL, &rect_PlayerScore);
SDL_RenderPresent(renderer);

SDL_DestroyTexture(playerMessage);

//AI_SCORE

std::string AScore = "AI: " + std::to_string(score_AI);

SDL_Surface* scoreAIMessage = TTF_RenderText_Solid(Sans, AScore.c_str(), White);

SDL_Texture* AIMessage = SDL_CreateTextureFromSurface(renderer, scoreAIMessage);

int Aw = scoreAIMessage->w;
int Ah = scoreAIMessage->h;

SDL_FreeSurface(scoreAIMessage);

SDL_Rect rect_AIScore = { 390+145, 10, Aw, Ah };

SDL_RenderCopy(renderer, AIMessage, NULL, &rect_AIScore);
SDL_RenderPresent(renderer);

SDL_DestroyTexture(AIMessage); 
}

//Update method... too fast
void Update()
{
while (running) //game loop
{
GameLogic(); //update stuff;
DrawScreen(); //render your stuff
}
}

//Quits the game
void Quit()
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
}

//Main
int main(int argc, char* args[])
{

LoadGame();
running = true;
Update();
Quit();

return 0;
}

Its a bit rough around the edges. I made this in less than 24 hours with lots of google. There is stuff here i don't understand 100% mainly some SDL stuff on the renderer (DrawScreen() method).

 

Some questions i have:

  1. How can improve the update method? Because now it is updating way to fast even with a SDL_Delay(10); the rendering is flickering a bit.
  2. I didn't fully understand the renderer code. It was somewhat of try and error where i ended up placing SDL_RenderPresent(renderer); after each thing i wanted to render. (feels stupid and unnecessary, maybe i'm the one who is stupid)
  3. What is the idea behind implementing sound? (i didn't feel like googling this one)
  4. How can i improve upon my code?
  5. What is a good way to make the AI to lose? AT this moment is quit impossible for him to lose... I've made him move only when the ball gets into his side of the map, and even slowed him down quite a bit (relative to the player speed) but he looks almost like he teleports to the ball location,

Tomorrow i'll start with my worm game, this time without (hopefully) any video tutorial.

Edited by W84M3

Share this post


Link to post
Share on other sites
Advertisement
2. Definitely don't do that. Only Present once per update/frame. That is why you get flickering; you're copying incomplete images to the screen while drawing out the scene.

Share this post


Link to post
Share on other sites


1. Make a sound file.
 
2. Ask SDL to load the sound file into a sound object.
 
3. Tell SDL to play the sound object when you want the sound to start playing.
 
Repeat steps 1-2 for each unique sound in your game (ball hits paddle, ball hits wall, player wins, player loses, etc.). Repeat step 3 every time you want a sound to play.
 
You're going to have to feel like Googling it if you want more information. SDL's sound capabilities are very low-level and not the best if you're just looking for fast and easy. You might need to use an add-on library like SDL_mixer to do more complex sound.

 

its not that i didn't feel like googling... it was more of a tired thing... i was a bit tired yesterday and i wanted like a explanation first before i started messing with sound :D

 

About the other responses i really appreciate them...

Share this post


Link to post
Share on other sites

Many thanks rip-off!

That's exactly what i wanted to hear. i'll read and study your notes tomorrow and i'll come back if i have any doubts about anything.

Just wanted to say that the collision typo has occurred because i'm not an English native speaker .

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!