C++ Breakout game using SDL
up vote
1
down vote
favorite
I did a big mistake to create procedural C++ breakout game on start and now im having trouble converting it into OOP.
As far as I can see I need classes: Loptica (eng. Ball), Splav (eng. Paddle), Blok (eng. Block), Logika (eng. Logic), Kolizija (eng, Collision), Level (eng. Level)
Definition:
#include "SDL.h"
#include "SDL_image.h"
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include <utility>
#include <string>
#include <vector>
#include <algorithm>
#undef main
using namespace std;
SDL_Window *ekran;
SDL_Renderer * renderer = NULL;
SDL_Texture * pozadina = NULL; //background
SDL_Texture * splav = NULL; //paddle
SDL_Texture * loptica = NULL; //ball
SDL_Texture * block01 = NULL; //1st row of blocks
SDL_Texture * block02 = NULL; //2nd row of blocks
SDL_Texture * block03 = NULL; //3rd row of blocks
SDL_Texture * blockNeprobojni = NULL; //impenetrable block
SDL_Rect rectPozadina; //background rect
SDL_Rect rectSplav; //paddle rect
SDL_Rect rectLoptica; //ball rect
SDL_Rect rectBlock01; //block01 rect
SDL_Rect rectBlock02; //block02 rect
SDL_Rect rectBlock03; //block03 rect
SDL_Rect rectBlockNeprobojni; //impenetrable rect
SDL_Event problem;
const int sirinaEkrana = 1280, visinaEkrana = 720;
//sirinaEkrana= screenWidth, visinaEkrana=screenHeight
int brojZivota = 3; //number of lives
int brojBlokova = 36; //total amount of blocks on screen
vector< pair<pair<int, int>, int > > koordinateBlokovaVektor; //array for storing coordinates and impact count on every block
bool igra = true; //bool value for while loop in int main()
int gornjiOdstoj = 20; //space between top wall and 1st row of blocks
int razmakRedova = 5; //space between blocks in a row
int razmakStupaca = 5; //space between blocks in column
int sirinaBloka = 102; //width of the block
int visinaBloka = 20; //height of the block
//sirinaSplavi = paddleWidth, visinaSplavi=paddleHeight
const int sirinaSplavi = 200, visinaSplavi = 10;
//splavPocetniX=starting point X of paddle, splavPocetniY=starting point Y of paddle
const int splavPocetniX = sirinaEkrana / 2 - 100;
const int splavPocetniY = visinaEkrana - visinaSplavi;
//sirinaLoptice= ballWidth, visinaLoptice=ballHeight
const int sirinaLoptice = 20, visinaLoptice = 20;
//lopticaPocetniX = starting point X of the ball, lopticaPocetniY = starting point Y of the ball,
const int lopticaPocetniX = sirinaEkrana / 2;
const int lopticaPocetniY = visinaEkrana / 2;
//lopticaTrenutniX =current X point of the ball, lopticaTrenutniY =current Y point of the ball
int lopticaTrenutniX = 0, lopticaTrenutniY = 0;
//level
int level = 1;
int brojRedovaBlokova = 3; //number of block rows
int brojBlokovaRed = 12; //number of blocks in a row
Main function:
int main(int argc, char*args) {
loadGame();
while (igra)
{
SDL_PollEvent(&problem);
if (problem.type == SDL_QUIT)
igra = false;
Logika();
Crtaj();
}
Quit();
return 0;
}
Quit function:
void Quit() {
SDL_Quit();
}
Loading a game:
void loadGame() {
SDL_Init(SDL_INIT_EVERYTHING);
ekran = SDL_CreateWindow("Breakout", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sirinaEkrana, visinaEkrana, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(ekran, -1, 0);
pozadina = IMG_LoadTexture(renderer, "Slike/pozadina1.png");
loptica = IMG_LoadTexture(renderer,"loptica.bmp");
splav = IMG_LoadTexture(renderer, "splav.bmp");
block01 = IMG_LoadTexture(renderer, "block01.bmp");
block02 = IMG_LoadTexture(renderer, "block02.bmp");
block03 = IMG_LoadTexture(renderer, "block03.bmp");
blockNeprobojni = IMG_LoadTexture(renderer, "blockNeprobojni.bmp");
rectLoptica.x = lopticaPocetniX; rectLoptica.y =lopticaPocetniY; rectLoptica.w = sirinaLoptice; rectLoptica.h = visinaLoptice;
rectSplav.x = splavPocetniX; rectSplav.y = splavPocetniY; rectSplav.w = sirinaSplavi; rectSplav.h = visinaSplavi;
rectPozadina.x = 0; rectPozadina.y = 0; rectPozadina.w = sirinaEkrana; rectPozadina.h = visinaEkrana;
Crtaj();
srand(time(NULL));
randomPocetniSmjer();
}
Game logic:
void Logika() {
#pragma region Paddle movement
const Uint8 *tipka = SDL_GetKeyboardState(NULL);
if (tipka[SDL_SCANCODE_A] && rectSplav.x > 0)
rectSplav.x--;
if (tipka[SDL_SCANCODE_D] && rectSplav.x < 1080) //1280-200(paddle width)
rectSplav.x++;
#pragma endregion
#pragma region Ball movement
rectLoptica.x += lopticaTrenutniX;
rectLoptica.y += lopticaTrenutniY;
#pragma endregion
//UPPER WALL
if (rectLoptica.y < visinaLoptice) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//DOWN WALL, RESET
if (rectLoptica.y > visinaEkrana) {
Sleep(2000);
randomPocetniSmjer();
brojZivota--;
if (brojZivota == 0) {
igra = false;
}
}
//LEFT WALL
if (rectLoptica.x < sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//RIGHT WALL
if (rectLoptica.x > sirinaEkrana - sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//checking collision of paddle and ball
if (provjeraKolizijeSplavi(rectSplav, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//checking collision of ball and block
int velicinaPolja = koordinateBlokovaVektor.size();
for(int i=0;i<velicinaPolja;i++) {
if (provjeraKolizijeBloka(koordinateBlokovaVektor[i].first.first, koordinateBlokovaVektor[i].first.second,koordinateBlokovaVektor[i].second, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
koordinateBlokovaVektor[i].first.first = -1;
koordinateBlokovaVektor[i].first.second = -1;
koordinateBlokovaVektor[i].second--;
break;
}
}
Sleep(2);
}
Drawing function (doesnt work as it should with deleting blocks):
void Crtaj() {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, pozadina, NULL, &rectPozadina);
SDL_RenderCopy(renderer, splav, NULL, &rectSplav);
SDL_RenderCopy(renderer, loptica, NULL, &rectLoptica);
SDL_SetRenderTarget(renderer, pozadina);
SDL_SetRenderTarget(renderer, loptica);
SDL_SetRenderTarget(renderer, splav);
int prviRedBrojac = 0, drugiRedBrojac = 11, treciRedBrojac = 23;
#pragma region LVL 1
for (int j = 0; j < brojBlokovaRed; j++) {
int block1X = j*sirinaBloka + j*razmakRedova, block1Y = gornjiOdstoj;
int block2X = j*sirinaBloka + j*razmakRedova, block2Y = gornjiOdstoj + visinaBloka + razmakStupaca;
int block3X = j*sirinaBloka + j*razmakRedova, block3Y = gornjiOdstoj + 2 * visinaBloka + 2 * razmakStupaca;
spremiKoordinate(block1X, block1Y,1);
if (koordinateBlokovaVektor[j].first.first != -1 && koordinateBlokovaVektor[j].first.second != -1 && koordinateBlokovaVektor[j].second != 0) {
rectBlock01 = initRectBlock(block1X, block1Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock01);
SDL_SetRenderTarget(renderer, block01);
prviRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
if ((j + 1) % 3 == 0) { //if its a impenetrable block
spremiKoordinate(block2X, block2Y,-1); //store -1 if its imprenetrable
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, blockNeprobojni, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, blockNeprobojni);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
else {
spremiKoordinate(block2X, block2Y,2);
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block02, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, block02);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
spremiKoordinate(block3X, block3Y, 1);
if (koordinateBlokovaVektor[j+2].first.first != -1 && koordinateBlokovaVektor[j+2].first.second != -1 && koordinateBlokovaVektor[j+2].second != 0) {
rectBlock03 = initRectBlock(block3X, block3Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock03);
SDL_SetRenderTarget(renderer, block01);
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
#pragma endregion
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderPresent(renderer);
}
Storing coordinates in array:
void spremiKoordinate(int x, int y,int brojUdaraca) {
if (koordinateBlokovaVektor.size() < 36 ) {
koordinateBlokovaVektor.push_back(make_pair(make_pair(x,y), brojUdaraca));
sort(koordinateBlokovaVektor.begin(), koordinateBlokovaVektor.end());
}
}
Initialize SDL_Rect:
SDL_Rect initRectBlock(int x, int y, int sirina, int visina) {
SDL_Rect blok;
blok.x = x;
blok.y = y;
blok.w = sirina;
blok.h = visina;
return blok;
}
Define starting direction of the ball:
void randomPocetniSmjer() {
//reset ball
rectLoptica.x = lopticaPocetniX;
rectLoptica.y = lopticaPocetniY;
//reset paddle
rectSplav.x = splavPocetniX;
rectSplav.y = splavPocetniY;
int smjerKretanja = (rand() % 2 + 1);
int kutGibanjaX1 = -1;
int kutGibanjaY1 = 1;
switch (smjerKretanja)
{
case 1:
lopticaTrenutniX = -kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
case 2:
lopticaTrenutniX = kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
default:
break;
}
}
Next in code is collision:
bool tocnaUnutarSplavi(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaSplavi >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + visinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool tocnaUnutarBloka(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaBloka >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + sirinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool provjeraKolizijeSplavi(SDL_Rect splav, SDL_Rect r2) {
//when ball hits paddle for direction DOWNLEFT
if (tocnaUnutarSplavi(splav.x, splav.y, r2) == true) {
cout << "KOLIZIJA: Splav[" << rectSplav.x << "," << rectSplav.y << "]" << endl;
return true;
}
//when ball hits paddle for direction DOWNRIGHT
else if (tocnaUnutarSplavi(splav.x, splav.y + splav.h, r2) == true) {
return true;
}
else
return false;
}
bool provjeraKolizijeBloka(int x, int y, int brojUdaraca, SDL_Rect r2) {
//when ball hits block from direction UPLEFT
if (tocnaUnutarBloka(x, y, r2) == true) {
return true;
}
//when ball hits block from direction UPRIGHT
else if (tocnaUnutarBloka(x, y + visinaBloka, r2) == true) {
return true;
}
else
return false;
}
If someone could give me some direction to start with because im just confused how to even convert it into OOP .
c++ object-oriented game collision sdl
bumped to the homepage by Community♦ 11 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
up vote
1
down vote
favorite
I did a big mistake to create procedural C++ breakout game on start and now im having trouble converting it into OOP.
As far as I can see I need classes: Loptica (eng. Ball), Splav (eng. Paddle), Blok (eng. Block), Logika (eng. Logic), Kolizija (eng, Collision), Level (eng. Level)
Definition:
#include "SDL.h"
#include "SDL_image.h"
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include <utility>
#include <string>
#include <vector>
#include <algorithm>
#undef main
using namespace std;
SDL_Window *ekran;
SDL_Renderer * renderer = NULL;
SDL_Texture * pozadina = NULL; //background
SDL_Texture * splav = NULL; //paddle
SDL_Texture * loptica = NULL; //ball
SDL_Texture * block01 = NULL; //1st row of blocks
SDL_Texture * block02 = NULL; //2nd row of blocks
SDL_Texture * block03 = NULL; //3rd row of blocks
SDL_Texture * blockNeprobojni = NULL; //impenetrable block
SDL_Rect rectPozadina; //background rect
SDL_Rect rectSplav; //paddle rect
SDL_Rect rectLoptica; //ball rect
SDL_Rect rectBlock01; //block01 rect
SDL_Rect rectBlock02; //block02 rect
SDL_Rect rectBlock03; //block03 rect
SDL_Rect rectBlockNeprobojni; //impenetrable rect
SDL_Event problem;
const int sirinaEkrana = 1280, visinaEkrana = 720;
//sirinaEkrana= screenWidth, visinaEkrana=screenHeight
int brojZivota = 3; //number of lives
int brojBlokova = 36; //total amount of blocks on screen
vector< pair<pair<int, int>, int > > koordinateBlokovaVektor; //array for storing coordinates and impact count on every block
bool igra = true; //bool value for while loop in int main()
int gornjiOdstoj = 20; //space between top wall and 1st row of blocks
int razmakRedova = 5; //space between blocks in a row
int razmakStupaca = 5; //space between blocks in column
int sirinaBloka = 102; //width of the block
int visinaBloka = 20; //height of the block
//sirinaSplavi = paddleWidth, visinaSplavi=paddleHeight
const int sirinaSplavi = 200, visinaSplavi = 10;
//splavPocetniX=starting point X of paddle, splavPocetniY=starting point Y of paddle
const int splavPocetniX = sirinaEkrana / 2 - 100;
const int splavPocetniY = visinaEkrana - visinaSplavi;
//sirinaLoptice= ballWidth, visinaLoptice=ballHeight
const int sirinaLoptice = 20, visinaLoptice = 20;
//lopticaPocetniX = starting point X of the ball, lopticaPocetniY = starting point Y of the ball,
const int lopticaPocetniX = sirinaEkrana / 2;
const int lopticaPocetniY = visinaEkrana / 2;
//lopticaTrenutniX =current X point of the ball, lopticaTrenutniY =current Y point of the ball
int lopticaTrenutniX = 0, lopticaTrenutniY = 0;
//level
int level = 1;
int brojRedovaBlokova = 3; //number of block rows
int brojBlokovaRed = 12; //number of blocks in a row
Main function:
int main(int argc, char*args) {
loadGame();
while (igra)
{
SDL_PollEvent(&problem);
if (problem.type == SDL_QUIT)
igra = false;
Logika();
Crtaj();
}
Quit();
return 0;
}
Quit function:
void Quit() {
SDL_Quit();
}
Loading a game:
void loadGame() {
SDL_Init(SDL_INIT_EVERYTHING);
ekran = SDL_CreateWindow("Breakout", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sirinaEkrana, visinaEkrana, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(ekran, -1, 0);
pozadina = IMG_LoadTexture(renderer, "Slike/pozadina1.png");
loptica = IMG_LoadTexture(renderer,"loptica.bmp");
splav = IMG_LoadTexture(renderer, "splav.bmp");
block01 = IMG_LoadTexture(renderer, "block01.bmp");
block02 = IMG_LoadTexture(renderer, "block02.bmp");
block03 = IMG_LoadTexture(renderer, "block03.bmp");
blockNeprobojni = IMG_LoadTexture(renderer, "blockNeprobojni.bmp");
rectLoptica.x = lopticaPocetniX; rectLoptica.y =lopticaPocetniY; rectLoptica.w = sirinaLoptice; rectLoptica.h = visinaLoptice;
rectSplav.x = splavPocetniX; rectSplav.y = splavPocetniY; rectSplav.w = sirinaSplavi; rectSplav.h = visinaSplavi;
rectPozadina.x = 0; rectPozadina.y = 0; rectPozadina.w = sirinaEkrana; rectPozadina.h = visinaEkrana;
Crtaj();
srand(time(NULL));
randomPocetniSmjer();
}
Game logic:
void Logika() {
#pragma region Paddle movement
const Uint8 *tipka = SDL_GetKeyboardState(NULL);
if (tipka[SDL_SCANCODE_A] && rectSplav.x > 0)
rectSplav.x--;
if (tipka[SDL_SCANCODE_D] && rectSplav.x < 1080) //1280-200(paddle width)
rectSplav.x++;
#pragma endregion
#pragma region Ball movement
rectLoptica.x += lopticaTrenutniX;
rectLoptica.y += lopticaTrenutniY;
#pragma endregion
//UPPER WALL
if (rectLoptica.y < visinaLoptice) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//DOWN WALL, RESET
if (rectLoptica.y > visinaEkrana) {
Sleep(2000);
randomPocetniSmjer();
brojZivota--;
if (brojZivota == 0) {
igra = false;
}
}
//LEFT WALL
if (rectLoptica.x < sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//RIGHT WALL
if (rectLoptica.x > sirinaEkrana - sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//checking collision of paddle and ball
if (provjeraKolizijeSplavi(rectSplav, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//checking collision of ball and block
int velicinaPolja = koordinateBlokovaVektor.size();
for(int i=0;i<velicinaPolja;i++) {
if (provjeraKolizijeBloka(koordinateBlokovaVektor[i].first.first, koordinateBlokovaVektor[i].first.second,koordinateBlokovaVektor[i].second, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
koordinateBlokovaVektor[i].first.first = -1;
koordinateBlokovaVektor[i].first.second = -1;
koordinateBlokovaVektor[i].second--;
break;
}
}
Sleep(2);
}
Drawing function (doesnt work as it should with deleting blocks):
void Crtaj() {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, pozadina, NULL, &rectPozadina);
SDL_RenderCopy(renderer, splav, NULL, &rectSplav);
SDL_RenderCopy(renderer, loptica, NULL, &rectLoptica);
SDL_SetRenderTarget(renderer, pozadina);
SDL_SetRenderTarget(renderer, loptica);
SDL_SetRenderTarget(renderer, splav);
int prviRedBrojac = 0, drugiRedBrojac = 11, treciRedBrojac = 23;
#pragma region LVL 1
for (int j = 0; j < brojBlokovaRed; j++) {
int block1X = j*sirinaBloka + j*razmakRedova, block1Y = gornjiOdstoj;
int block2X = j*sirinaBloka + j*razmakRedova, block2Y = gornjiOdstoj + visinaBloka + razmakStupaca;
int block3X = j*sirinaBloka + j*razmakRedova, block3Y = gornjiOdstoj + 2 * visinaBloka + 2 * razmakStupaca;
spremiKoordinate(block1X, block1Y,1);
if (koordinateBlokovaVektor[j].first.first != -1 && koordinateBlokovaVektor[j].first.second != -1 && koordinateBlokovaVektor[j].second != 0) {
rectBlock01 = initRectBlock(block1X, block1Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock01);
SDL_SetRenderTarget(renderer, block01);
prviRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
if ((j + 1) % 3 == 0) { //if its a impenetrable block
spremiKoordinate(block2X, block2Y,-1); //store -1 if its imprenetrable
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, blockNeprobojni, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, blockNeprobojni);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
else {
spremiKoordinate(block2X, block2Y,2);
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block02, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, block02);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
spremiKoordinate(block3X, block3Y, 1);
if (koordinateBlokovaVektor[j+2].first.first != -1 && koordinateBlokovaVektor[j+2].first.second != -1 && koordinateBlokovaVektor[j+2].second != 0) {
rectBlock03 = initRectBlock(block3X, block3Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock03);
SDL_SetRenderTarget(renderer, block01);
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
#pragma endregion
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderPresent(renderer);
}
Storing coordinates in array:
void spremiKoordinate(int x, int y,int brojUdaraca) {
if (koordinateBlokovaVektor.size() < 36 ) {
koordinateBlokovaVektor.push_back(make_pair(make_pair(x,y), brojUdaraca));
sort(koordinateBlokovaVektor.begin(), koordinateBlokovaVektor.end());
}
}
Initialize SDL_Rect:
SDL_Rect initRectBlock(int x, int y, int sirina, int visina) {
SDL_Rect blok;
blok.x = x;
blok.y = y;
blok.w = sirina;
blok.h = visina;
return blok;
}
Define starting direction of the ball:
void randomPocetniSmjer() {
//reset ball
rectLoptica.x = lopticaPocetniX;
rectLoptica.y = lopticaPocetniY;
//reset paddle
rectSplav.x = splavPocetniX;
rectSplav.y = splavPocetniY;
int smjerKretanja = (rand() % 2 + 1);
int kutGibanjaX1 = -1;
int kutGibanjaY1 = 1;
switch (smjerKretanja)
{
case 1:
lopticaTrenutniX = -kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
case 2:
lopticaTrenutniX = kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
default:
break;
}
}
Next in code is collision:
bool tocnaUnutarSplavi(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaSplavi >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + visinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool tocnaUnutarBloka(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaBloka >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + sirinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool provjeraKolizijeSplavi(SDL_Rect splav, SDL_Rect r2) {
//when ball hits paddle for direction DOWNLEFT
if (tocnaUnutarSplavi(splav.x, splav.y, r2) == true) {
cout << "KOLIZIJA: Splav[" << rectSplav.x << "," << rectSplav.y << "]" << endl;
return true;
}
//when ball hits paddle for direction DOWNRIGHT
else if (tocnaUnutarSplavi(splav.x, splav.y + splav.h, r2) == true) {
return true;
}
else
return false;
}
bool provjeraKolizijeBloka(int x, int y, int brojUdaraca, SDL_Rect r2) {
//when ball hits block from direction UPLEFT
if (tocnaUnutarBloka(x, y, r2) == true) {
return true;
}
//when ball hits block from direction UPRIGHT
else if (tocnaUnutarBloka(x, y + visinaBloka, r2) == true) {
return true;
}
else
return false;
}
If someone could give me some direction to start with because im just confused how to even convert it into OOP .
c++ object-oriented game collision sdl
bumped to the homepage by Community♦ 11 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
I don't know if it suits your needs but I made this breakout clone using SDL in the past It's from my noob days into programming, so it's mostly shitty, so take it as it is. Maybe it will guide you in the direction you seek.
– RandomOne
Oct 10 at 19:39
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I did a big mistake to create procedural C++ breakout game on start and now im having trouble converting it into OOP.
As far as I can see I need classes: Loptica (eng. Ball), Splav (eng. Paddle), Blok (eng. Block), Logika (eng. Logic), Kolizija (eng, Collision), Level (eng. Level)
Definition:
#include "SDL.h"
#include "SDL_image.h"
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include <utility>
#include <string>
#include <vector>
#include <algorithm>
#undef main
using namespace std;
SDL_Window *ekran;
SDL_Renderer * renderer = NULL;
SDL_Texture * pozadina = NULL; //background
SDL_Texture * splav = NULL; //paddle
SDL_Texture * loptica = NULL; //ball
SDL_Texture * block01 = NULL; //1st row of blocks
SDL_Texture * block02 = NULL; //2nd row of blocks
SDL_Texture * block03 = NULL; //3rd row of blocks
SDL_Texture * blockNeprobojni = NULL; //impenetrable block
SDL_Rect rectPozadina; //background rect
SDL_Rect rectSplav; //paddle rect
SDL_Rect rectLoptica; //ball rect
SDL_Rect rectBlock01; //block01 rect
SDL_Rect rectBlock02; //block02 rect
SDL_Rect rectBlock03; //block03 rect
SDL_Rect rectBlockNeprobojni; //impenetrable rect
SDL_Event problem;
const int sirinaEkrana = 1280, visinaEkrana = 720;
//sirinaEkrana= screenWidth, visinaEkrana=screenHeight
int brojZivota = 3; //number of lives
int brojBlokova = 36; //total amount of blocks on screen
vector< pair<pair<int, int>, int > > koordinateBlokovaVektor; //array for storing coordinates and impact count on every block
bool igra = true; //bool value for while loop in int main()
int gornjiOdstoj = 20; //space between top wall and 1st row of blocks
int razmakRedova = 5; //space between blocks in a row
int razmakStupaca = 5; //space between blocks in column
int sirinaBloka = 102; //width of the block
int visinaBloka = 20; //height of the block
//sirinaSplavi = paddleWidth, visinaSplavi=paddleHeight
const int sirinaSplavi = 200, visinaSplavi = 10;
//splavPocetniX=starting point X of paddle, splavPocetniY=starting point Y of paddle
const int splavPocetniX = sirinaEkrana / 2 - 100;
const int splavPocetniY = visinaEkrana - visinaSplavi;
//sirinaLoptice= ballWidth, visinaLoptice=ballHeight
const int sirinaLoptice = 20, visinaLoptice = 20;
//lopticaPocetniX = starting point X of the ball, lopticaPocetniY = starting point Y of the ball,
const int lopticaPocetniX = sirinaEkrana / 2;
const int lopticaPocetniY = visinaEkrana / 2;
//lopticaTrenutniX =current X point of the ball, lopticaTrenutniY =current Y point of the ball
int lopticaTrenutniX = 0, lopticaTrenutniY = 0;
//level
int level = 1;
int brojRedovaBlokova = 3; //number of block rows
int brojBlokovaRed = 12; //number of blocks in a row
Main function:
int main(int argc, char*args) {
loadGame();
while (igra)
{
SDL_PollEvent(&problem);
if (problem.type == SDL_QUIT)
igra = false;
Logika();
Crtaj();
}
Quit();
return 0;
}
Quit function:
void Quit() {
SDL_Quit();
}
Loading a game:
void loadGame() {
SDL_Init(SDL_INIT_EVERYTHING);
ekran = SDL_CreateWindow("Breakout", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sirinaEkrana, visinaEkrana, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(ekran, -1, 0);
pozadina = IMG_LoadTexture(renderer, "Slike/pozadina1.png");
loptica = IMG_LoadTexture(renderer,"loptica.bmp");
splav = IMG_LoadTexture(renderer, "splav.bmp");
block01 = IMG_LoadTexture(renderer, "block01.bmp");
block02 = IMG_LoadTexture(renderer, "block02.bmp");
block03 = IMG_LoadTexture(renderer, "block03.bmp");
blockNeprobojni = IMG_LoadTexture(renderer, "blockNeprobojni.bmp");
rectLoptica.x = lopticaPocetniX; rectLoptica.y =lopticaPocetniY; rectLoptica.w = sirinaLoptice; rectLoptica.h = visinaLoptice;
rectSplav.x = splavPocetniX; rectSplav.y = splavPocetniY; rectSplav.w = sirinaSplavi; rectSplav.h = visinaSplavi;
rectPozadina.x = 0; rectPozadina.y = 0; rectPozadina.w = sirinaEkrana; rectPozadina.h = visinaEkrana;
Crtaj();
srand(time(NULL));
randomPocetniSmjer();
}
Game logic:
void Logika() {
#pragma region Paddle movement
const Uint8 *tipka = SDL_GetKeyboardState(NULL);
if (tipka[SDL_SCANCODE_A] && rectSplav.x > 0)
rectSplav.x--;
if (tipka[SDL_SCANCODE_D] && rectSplav.x < 1080) //1280-200(paddle width)
rectSplav.x++;
#pragma endregion
#pragma region Ball movement
rectLoptica.x += lopticaTrenutniX;
rectLoptica.y += lopticaTrenutniY;
#pragma endregion
//UPPER WALL
if (rectLoptica.y < visinaLoptice) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//DOWN WALL, RESET
if (rectLoptica.y > visinaEkrana) {
Sleep(2000);
randomPocetniSmjer();
brojZivota--;
if (brojZivota == 0) {
igra = false;
}
}
//LEFT WALL
if (rectLoptica.x < sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//RIGHT WALL
if (rectLoptica.x > sirinaEkrana - sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//checking collision of paddle and ball
if (provjeraKolizijeSplavi(rectSplav, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//checking collision of ball and block
int velicinaPolja = koordinateBlokovaVektor.size();
for(int i=0;i<velicinaPolja;i++) {
if (provjeraKolizijeBloka(koordinateBlokovaVektor[i].first.first, koordinateBlokovaVektor[i].first.second,koordinateBlokovaVektor[i].second, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
koordinateBlokovaVektor[i].first.first = -1;
koordinateBlokovaVektor[i].first.second = -1;
koordinateBlokovaVektor[i].second--;
break;
}
}
Sleep(2);
}
Drawing function (doesnt work as it should with deleting blocks):
void Crtaj() {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, pozadina, NULL, &rectPozadina);
SDL_RenderCopy(renderer, splav, NULL, &rectSplav);
SDL_RenderCopy(renderer, loptica, NULL, &rectLoptica);
SDL_SetRenderTarget(renderer, pozadina);
SDL_SetRenderTarget(renderer, loptica);
SDL_SetRenderTarget(renderer, splav);
int prviRedBrojac = 0, drugiRedBrojac = 11, treciRedBrojac = 23;
#pragma region LVL 1
for (int j = 0; j < brojBlokovaRed; j++) {
int block1X = j*sirinaBloka + j*razmakRedova, block1Y = gornjiOdstoj;
int block2X = j*sirinaBloka + j*razmakRedova, block2Y = gornjiOdstoj + visinaBloka + razmakStupaca;
int block3X = j*sirinaBloka + j*razmakRedova, block3Y = gornjiOdstoj + 2 * visinaBloka + 2 * razmakStupaca;
spremiKoordinate(block1X, block1Y,1);
if (koordinateBlokovaVektor[j].first.first != -1 && koordinateBlokovaVektor[j].first.second != -1 && koordinateBlokovaVektor[j].second != 0) {
rectBlock01 = initRectBlock(block1X, block1Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock01);
SDL_SetRenderTarget(renderer, block01);
prviRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
if ((j + 1) % 3 == 0) { //if its a impenetrable block
spremiKoordinate(block2X, block2Y,-1); //store -1 if its imprenetrable
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, blockNeprobojni, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, blockNeprobojni);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
else {
spremiKoordinate(block2X, block2Y,2);
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block02, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, block02);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
spremiKoordinate(block3X, block3Y, 1);
if (koordinateBlokovaVektor[j+2].first.first != -1 && koordinateBlokovaVektor[j+2].first.second != -1 && koordinateBlokovaVektor[j+2].second != 0) {
rectBlock03 = initRectBlock(block3X, block3Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock03);
SDL_SetRenderTarget(renderer, block01);
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
#pragma endregion
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderPresent(renderer);
}
Storing coordinates in array:
void spremiKoordinate(int x, int y,int brojUdaraca) {
if (koordinateBlokovaVektor.size() < 36 ) {
koordinateBlokovaVektor.push_back(make_pair(make_pair(x,y), brojUdaraca));
sort(koordinateBlokovaVektor.begin(), koordinateBlokovaVektor.end());
}
}
Initialize SDL_Rect:
SDL_Rect initRectBlock(int x, int y, int sirina, int visina) {
SDL_Rect blok;
blok.x = x;
blok.y = y;
blok.w = sirina;
blok.h = visina;
return blok;
}
Define starting direction of the ball:
void randomPocetniSmjer() {
//reset ball
rectLoptica.x = lopticaPocetniX;
rectLoptica.y = lopticaPocetniY;
//reset paddle
rectSplav.x = splavPocetniX;
rectSplav.y = splavPocetniY;
int smjerKretanja = (rand() % 2 + 1);
int kutGibanjaX1 = -1;
int kutGibanjaY1 = 1;
switch (smjerKretanja)
{
case 1:
lopticaTrenutniX = -kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
case 2:
lopticaTrenutniX = kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
default:
break;
}
}
Next in code is collision:
bool tocnaUnutarSplavi(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaSplavi >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + visinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool tocnaUnutarBloka(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaBloka >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + sirinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool provjeraKolizijeSplavi(SDL_Rect splav, SDL_Rect r2) {
//when ball hits paddle for direction DOWNLEFT
if (tocnaUnutarSplavi(splav.x, splav.y, r2) == true) {
cout << "KOLIZIJA: Splav[" << rectSplav.x << "," << rectSplav.y << "]" << endl;
return true;
}
//when ball hits paddle for direction DOWNRIGHT
else if (tocnaUnutarSplavi(splav.x, splav.y + splav.h, r2) == true) {
return true;
}
else
return false;
}
bool provjeraKolizijeBloka(int x, int y, int brojUdaraca, SDL_Rect r2) {
//when ball hits block from direction UPLEFT
if (tocnaUnutarBloka(x, y, r2) == true) {
return true;
}
//when ball hits block from direction UPRIGHT
else if (tocnaUnutarBloka(x, y + visinaBloka, r2) == true) {
return true;
}
else
return false;
}
If someone could give me some direction to start with because im just confused how to even convert it into OOP .
c++ object-oriented game collision sdl
I did a big mistake to create procedural C++ breakout game on start and now im having trouble converting it into OOP.
As far as I can see I need classes: Loptica (eng. Ball), Splav (eng. Paddle), Blok (eng. Block), Logika (eng. Logic), Kolizija (eng, Collision), Level (eng. Level)
Definition:
#include "SDL.h"
#include "SDL_image.h"
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include <utility>
#include <string>
#include <vector>
#include <algorithm>
#undef main
using namespace std;
SDL_Window *ekran;
SDL_Renderer * renderer = NULL;
SDL_Texture * pozadina = NULL; //background
SDL_Texture * splav = NULL; //paddle
SDL_Texture * loptica = NULL; //ball
SDL_Texture * block01 = NULL; //1st row of blocks
SDL_Texture * block02 = NULL; //2nd row of blocks
SDL_Texture * block03 = NULL; //3rd row of blocks
SDL_Texture * blockNeprobojni = NULL; //impenetrable block
SDL_Rect rectPozadina; //background rect
SDL_Rect rectSplav; //paddle rect
SDL_Rect rectLoptica; //ball rect
SDL_Rect rectBlock01; //block01 rect
SDL_Rect rectBlock02; //block02 rect
SDL_Rect rectBlock03; //block03 rect
SDL_Rect rectBlockNeprobojni; //impenetrable rect
SDL_Event problem;
const int sirinaEkrana = 1280, visinaEkrana = 720;
//sirinaEkrana= screenWidth, visinaEkrana=screenHeight
int brojZivota = 3; //number of lives
int brojBlokova = 36; //total amount of blocks on screen
vector< pair<pair<int, int>, int > > koordinateBlokovaVektor; //array for storing coordinates and impact count on every block
bool igra = true; //bool value for while loop in int main()
int gornjiOdstoj = 20; //space between top wall and 1st row of blocks
int razmakRedova = 5; //space between blocks in a row
int razmakStupaca = 5; //space between blocks in column
int sirinaBloka = 102; //width of the block
int visinaBloka = 20; //height of the block
//sirinaSplavi = paddleWidth, visinaSplavi=paddleHeight
const int sirinaSplavi = 200, visinaSplavi = 10;
//splavPocetniX=starting point X of paddle, splavPocetniY=starting point Y of paddle
const int splavPocetniX = sirinaEkrana / 2 - 100;
const int splavPocetniY = visinaEkrana - visinaSplavi;
//sirinaLoptice= ballWidth, visinaLoptice=ballHeight
const int sirinaLoptice = 20, visinaLoptice = 20;
//lopticaPocetniX = starting point X of the ball, lopticaPocetniY = starting point Y of the ball,
const int lopticaPocetniX = sirinaEkrana / 2;
const int lopticaPocetniY = visinaEkrana / 2;
//lopticaTrenutniX =current X point of the ball, lopticaTrenutniY =current Y point of the ball
int lopticaTrenutniX = 0, lopticaTrenutniY = 0;
//level
int level = 1;
int brojRedovaBlokova = 3; //number of block rows
int brojBlokovaRed = 12; //number of blocks in a row
Main function:
int main(int argc, char*args) {
loadGame();
while (igra)
{
SDL_PollEvent(&problem);
if (problem.type == SDL_QUIT)
igra = false;
Logika();
Crtaj();
}
Quit();
return 0;
}
Quit function:
void Quit() {
SDL_Quit();
}
Loading a game:
void loadGame() {
SDL_Init(SDL_INIT_EVERYTHING);
ekran = SDL_CreateWindow("Breakout", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sirinaEkrana, visinaEkrana, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(ekran, -1, 0);
pozadina = IMG_LoadTexture(renderer, "Slike/pozadina1.png");
loptica = IMG_LoadTexture(renderer,"loptica.bmp");
splav = IMG_LoadTexture(renderer, "splav.bmp");
block01 = IMG_LoadTexture(renderer, "block01.bmp");
block02 = IMG_LoadTexture(renderer, "block02.bmp");
block03 = IMG_LoadTexture(renderer, "block03.bmp");
blockNeprobojni = IMG_LoadTexture(renderer, "blockNeprobojni.bmp");
rectLoptica.x = lopticaPocetniX; rectLoptica.y =lopticaPocetniY; rectLoptica.w = sirinaLoptice; rectLoptica.h = visinaLoptice;
rectSplav.x = splavPocetniX; rectSplav.y = splavPocetniY; rectSplav.w = sirinaSplavi; rectSplav.h = visinaSplavi;
rectPozadina.x = 0; rectPozadina.y = 0; rectPozadina.w = sirinaEkrana; rectPozadina.h = visinaEkrana;
Crtaj();
srand(time(NULL));
randomPocetniSmjer();
}
Game logic:
void Logika() {
#pragma region Paddle movement
const Uint8 *tipka = SDL_GetKeyboardState(NULL);
if (tipka[SDL_SCANCODE_A] && rectSplav.x > 0)
rectSplav.x--;
if (tipka[SDL_SCANCODE_D] && rectSplav.x < 1080) //1280-200(paddle width)
rectSplav.x++;
#pragma endregion
#pragma region Ball movement
rectLoptica.x += lopticaTrenutniX;
rectLoptica.y += lopticaTrenutniY;
#pragma endregion
//UPPER WALL
if (rectLoptica.y < visinaLoptice) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//DOWN WALL, RESET
if (rectLoptica.y > visinaEkrana) {
Sleep(2000);
randomPocetniSmjer();
brojZivota--;
if (brojZivota == 0) {
igra = false;
}
}
//LEFT WALL
if (rectLoptica.x < sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//RIGHT WALL
if (rectLoptica.x > sirinaEkrana - sirinaLoptice) {
lopticaTrenutniX = -lopticaTrenutniX;
}
//checking collision of paddle and ball
if (provjeraKolizijeSplavi(rectSplav, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
}
//checking collision of ball and block
int velicinaPolja = koordinateBlokovaVektor.size();
for(int i=0;i<velicinaPolja;i++) {
if (provjeraKolizijeBloka(koordinateBlokovaVektor[i].first.first, koordinateBlokovaVektor[i].first.second,koordinateBlokovaVektor[i].second, rectLoptica) == true) {
lopticaTrenutniY = -lopticaTrenutniY;
koordinateBlokovaVektor[i].first.first = -1;
koordinateBlokovaVektor[i].first.second = -1;
koordinateBlokovaVektor[i].second--;
break;
}
}
Sleep(2);
}
Drawing function (doesnt work as it should with deleting blocks):
void Crtaj() {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, pozadina, NULL, &rectPozadina);
SDL_RenderCopy(renderer, splav, NULL, &rectSplav);
SDL_RenderCopy(renderer, loptica, NULL, &rectLoptica);
SDL_SetRenderTarget(renderer, pozadina);
SDL_SetRenderTarget(renderer, loptica);
SDL_SetRenderTarget(renderer, splav);
int prviRedBrojac = 0, drugiRedBrojac = 11, treciRedBrojac = 23;
#pragma region LVL 1
for (int j = 0; j < brojBlokovaRed; j++) {
int block1X = j*sirinaBloka + j*razmakRedova, block1Y = gornjiOdstoj;
int block2X = j*sirinaBloka + j*razmakRedova, block2Y = gornjiOdstoj + visinaBloka + razmakStupaca;
int block3X = j*sirinaBloka + j*razmakRedova, block3Y = gornjiOdstoj + 2 * visinaBloka + 2 * razmakStupaca;
spremiKoordinate(block1X, block1Y,1);
if (koordinateBlokovaVektor[j].first.first != -1 && koordinateBlokovaVektor[j].first.second != -1 && koordinateBlokovaVektor[j].second != 0) {
rectBlock01 = initRectBlock(block1X, block1Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock01);
SDL_SetRenderTarget(renderer, block01);
prviRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
if ((j + 1) % 3 == 0) { //if its a impenetrable block
spremiKoordinate(block2X, block2Y,-1); //store -1 if its imprenetrable
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, blockNeprobojni, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, blockNeprobojni);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
else {
spremiKoordinate(block2X, block2Y,2);
if (koordinateBlokovaVektor[j+1].first.first != -1 && koordinateBlokovaVektor[j+1].first.second != -1 && koordinateBlokovaVektor[j+1].second != 0) {
rectBlock02 = initRectBlock(block2X, block2Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block02, NULL, &rectBlock02);
SDL_SetRenderTarget(renderer, block02);
drugiRedBrojac++;
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
spremiKoordinate(block3X, block3Y, 1);
if (koordinateBlokovaVektor[j+2].first.first != -1 && koordinateBlokovaVektor[j+2].first.second != -1 && koordinateBlokovaVektor[j+2].second != 0) {
rectBlock03 = initRectBlock(block3X, block3Y, sirinaBloka, visinaBloka);
SDL_RenderCopy(renderer, block01, NULL, &rectBlock03);
SDL_SetRenderTarget(renderer, block01);
}
else {
SDL_SetRenderTarget(renderer, NULL);
}
}
#pragma endregion
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderPresent(renderer);
}
Storing coordinates in array:
void spremiKoordinate(int x, int y,int brojUdaraca) {
if (koordinateBlokovaVektor.size() < 36 ) {
koordinateBlokovaVektor.push_back(make_pair(make_pair(x,y), brojUdaraca));
sort(koordinateBlokovaVektor.begin(), koordinateBlokovaVektor.end());
}
}
Initialize SDL_Rect:
SDL_Rect initRectBlock(int x, int y, int sirina, int visina) {
SDL_Rect blok;
blok.x = x;
blok.y = y;
blok.w = sirina;
blok.h = visina;
return blok;
}
Define starting direction of the ball:
void randomPocetniSmjer() {
//reset ball
rectLoptica.x = lopticaPocetniX;
rectLoptica.y = lopticaPocetniY;
//reset paddle
rectSplav.x = splavPocetniX;
rectSplav.y = splavPocetniY;
int smjerKretanja = (rand() % 2 + 1);
int kutGibanjaX1 = -1;
int kutGibanjaY1 = 1;
switch (smjerKretanja)
{
case 1:
lopticaTrenutniX = -kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
case 2:
lopticaTrenutniX = kutGibanjaX1;
lopticaTrenutniY = -kutGibanjaY1;
break;
default:
break;
}
}
Next in code is collision:
bool tocnaUnutarSplavi(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaSplavi >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + visinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool tocnaUnutarBloka(int objektX, int objektY, SDL_Rect loptica) {
if ((objektX + sirinaBloka >= loptica.x && objektY >= loptica.y) && (objektX <= loptica.x + sirinaLoptice && objektY <= loptica.y + visinaLoptice)) {
return true;
}
else
return false;
}
bool provjeraKolizijeSplavi(SDL_Rect splav, SDL_Rect r2) {
//when ball hits paddle for direction DOWNLEFT
if (tocnaUnutarSplavi(splav.x, splav.y, r2) == true) {
cout << "KOLIZIJA: Splav[" << rectSplav.x << "," << rectSplav.y << "]" << endl;
return true;
}
//when ball hits paddle for direction DOWNRIGHT
else if (tocnaUnutarSplavi(splav.x, splav.y + splav.h, r2) == true) {
return true;
}
else
return false;
}
bool provjeraKolizijeBloka(int x, int y, int brojUdaraca, SDL_Rect r2) {
//when ball hits block from direction UPLEFT
if (tocnaUnutarBloka(x, y, r2) == true) {
return true;
}
//when ball hits block from direction UPRIGHT
else if (tocnaUnutarBloka(x, y + visinaBloka, r2) == true) {
return true;
}
else
return false;
}
If someone could give me some direction to start with because im just confused how to even convert it into OOP .
c++ object-oriented game collision sdl
c++ object-oriented game collision sdl
asked Oct 10 at 19:20
Marko Petričević
165
165
bumped to the homepage by Community♦ 11 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 11 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
I don't know if it suits your needs but I made this breakout clone using SDL in the past It's from my noob days into programming, so it's mostly shitty, so take it as it is. Maybe it will guide you in the direction you seek.
– RandomOne
Oct 10 at 19:39
add a comment |
I don't know if it suits your needs but I made this breakout clone using SDL in the past It's from my noob days into programming, so it's mostly shitty, so take it as it is. Maybe it will guide you in the direction you seek.
– RandomOne
Oct 10 at 19:39
I don't know if it suits your needs but I made this breakout clone using SDL in the past It's from my noob days into programming, so it's mostly shitty, so take it as it is. Maybe it will guide you in the direction you seek.
– RandomOne
Oct 10 at 19:39
I don't know if it suits your needs but I made this breakout clone using SDL in the past It's from my noob days into programming, so it's mostly shitty, so take it as it is. Maybe it will guide you in the direction you seek.
– RandomOne
Oct 10 at 19:39
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
This is really not that bad. Despite the variable names not being in English, I'm able to get the gist of it. Here are some useful things that I think would improve the situation.
Avoid Globals
Your first header is mainly a list of global variables. Globals are difficult to work with because they can be changed by any code anywhere in your app. So when a problem occurs with a global, good luck tracking down where it occurs since it could be anywhere. If you put your global data into classes, you'll have minimized the number of places where it could be going wrong.
Let's start with the textures you use. Textures make up a large part of most video games. It would probably make sense to have an object which handles textures. It could load them from disk, give them to code to use, cache recently used textures, etc. I would probably make either a TextureFactory
class, or a TextureCache
class to handle these sorts of tasks. It might not be necessary here since you only have about 5-10 textures, but any more than that and you'll probably want something to organize them.
Use struct
or class
to Combine Data
Notice how after the texture declarations, you have corresponding declarations of rectangles. This is a clue that you should be creating either a struct
or class
that holds both the texture and its rectangle.
Next you declare a bunch of variables for things like the number of lives, current level, the number of blocks on screen, spacing of various elements. These fall into 2 broad categories - game state, and rendering constants. I would make 2 classes for these: GameState
which holds things like the number of lives left and the current level, and GameRenderer
which holds data related to rendering. I notice there's an SDL_Renderer
, so you should probably also put that into your GameRenderer
class.
You make a lot of use of std::pair
for storing coordinates and impact counts. std::pair
is a difficult class to deal with because it's so non-specific. Its data members, first
and second
are meaningless. You should make a Point
or Vector
class
to hold coordinates. You should then make a Block
struct
or class
to hold a Point
or Vector
and an impact count. Then your koordinateBlockovaVektor
vector would be declared as just:
std::vector<Block> koordinateBlokovaVektor;
Naming
I don't speak your language, but I assume Logika
is Logic
and Crtaj
is Draw
? If so, I would recommend using more descriptive names, like UpdateGameState()
and RenderGame()
(or whatever that would be in your native tongue).
I would also avoid putting the type name into the variable's name. So a std::vector
doesn't need to have Vektor
in it's name. If you had a class
or struct
for your textures, you could simply call the rectangle the bounds
or frame
or something along those lines. Something like this:
struct GameTexture {
SDL_Texture* image;
SDL_Rect bounds;
};
Then to access one, you could do:
GameTexture pozadina;
// ... fill it out ...
SDL_RenderCopy(renderer, pozadina.image, NULL, &pozadina.bounds);
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
It depends on how you use them. If aBlock
draws itself, then I'd put it inBlock
, but if aRenderer
draws aBlock
, I'd put it intoRenderer
.
– user1118321
Oct 11 at 16:12
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
This is really not that bad. Despite the variable names not being in English, I'm able to get the gist of it. Here are some useful things that I think would improve the situation.
Avoid Globals
Your first header is mainly a list of global variables. Globals are difficult to work with because they can be changed by any code anywhere in your app. So when a problem occurs with a global, good luck tracking down where it occurs since it could be anywhere. If you put your global data into classes, you'll have minimized the number of places where it could be going wrong.
Let's start with the textures you use. Textures make up a large part of most video games. It would probably make sense to have an object which handles textures. It could load them from disk, give them to code to use, cache recently used textures, etc. I would probably make either a TextureFactory
class, or a TextureCache
class to handle these sorts of tasks. It might not be necessary here since you only have about 5-10 textures, but any more than that and you'll probably want something to organize them.
Use struct
or class
to Combine Data
Notice how after the texture declarations, you have corresponding declarations of rectangles. This is a clue that you should be creating either a struct
or class
that holds both the texture and its rectangle.
Next you declare a bunch of variables for things like the number of lives, current level, the number of blocks on screen, spacing of various elements. These fall into 2 broad categories - game state, and rendering constants. I would make 2 classes for these: GameState
which holds things like the number of lives left and the current level, and GameRenderer
which holds data related to rendering. I notice there's an SDL_Renderer
, so you should probably also put that into your GameRenderer
class.
You make a lot of use of std::pair
for storing coordinates and impact counts. std::pair
is a difficult class to deal with because it's so non-specific. Its data members, first
and second
are meaningless. You should make a Point
or Vector
class
to hold coordinates. You should then make a Block
struct
or class
to hold a Point
or Vector
and an impact count. Then your koordinateBlockovaVektor
vector would be declared as just:
std::vector<Block> koordinateBlokovaVektor;
Naming
I don't speak your language, but I assume Logika
is Logic
and Crtaj
is Draw
? If so, I would recommend using more descriptive names, like UpdateGameState()
and RenderGame()
(or whatever that would be in your native tongue).
I would also avoid putting the type name into the variable's name. So a std::vector
doesn't need to have Vektor
in it's name. If you had a class
or struct
for your textures, you could simply call the rectangle the bounds
or frame
or something along those lines. Something like this:
struct GameTexture {
SDL_Texture* image;
SDL_Rect bounds;
};
Then to access one, you could do:
GameTexture pozadina;
// ... fill it out ...
SDL_RenderCopy(renderer, pozadina.image, NULL, &pozadina.bounds);
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
It depends on how you use them. If aBlock
draws itself, then I'd put it inBlock
, but if aRenderer
draws aBlock
, I'd put it intoRenderer
.
– user1118321
Oct 11 at 16:12
add a comment |
up vote
0
down vote
This is really not that bad. Despite the variable names not being in English, I'm able to get the gist of it. Here are some useful things that I think would improve the situation.
Avoid Globals
Your first header is mainly a list of global variables. Globals are difficult to work with because they can be changed by any code anywhere in your app. So when a problem occurs with a global, good luck tracking down where it occurs since it could be anywhere. If you put your global data into classes, you'll have minimized the number of places where it could be going wrong.
Let's start with the textures you use. Textures make up a large part of most video games. It would probably make sense to have an object which handles textures. It could load them from disk, give them to code to use, cache recently used textures, etc. I would probably make either a TextureFactory
class, or a TextureCache
class to handle these sorts of tasks. It might not be necessary here since you only have about 5-10 textures, but any more than that and you'll probably want something to organize them.
Use struct
or class
to Combine Data
Notice how after the texture declarations, you have corresponding declarations of rectangles. This is a clue that you should be creating either a struct
or class
that holds both the texture and its rectangle.
Next you declare a bunch of variables for things like the number of lives, current level, the number of blocks on screen, spacing of various elements. These fall into 2 broad categories - game state, and rendering constants. I would make 2 classes for these: GameState
which holds things like the number of lives left and the current level, and GameRenderer
which holds data related to rendering. I notice there's an SDL_Renderer
, so you should probably also put that into your GameRenderer
class.
You make a lot of use of std::pair
for storing coordinates and impact counts. std::pair
is a difficult class to deal with because it's so non-specific. Its data members, first
and second
are meaningless. You should make a Point
or Vector
class
to hold coordinates. You should then make a Block
struct
or class
to hold a Point
or Vector
and an impact count. Then your koordinateBlockovaVektor
vector would be declared as just:
std::vector<Block> koordinateBlokovaVektor;
Naming
I don't speak your language, but I assume Logika
is Logic
and Crtaj
is Draw
? If so, I would recommend using more descriptive names, like UpdateGameState()
and RenderGame()
(or whatever that would be in your native tongue).
I would also avoid putting the type name into the variable's name. So a std::vector
doesn't need to have Vektor
in it's name. If you had a class
or struct
for your textures, you could simply call the rectangle the bounds
or frame
or something along those lines. Something like this:
struct GameTexture {
SDL_Texture* image;
SDL_Rect bounds;
};
Then to access one, you could do:
GameTexture pozadina;
// ... fill it out ...
SDL_RenderCopy(renderer, pozadina.image, NULL, &pozadina.bounds);
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
It depends on how you use them. If aBlock
draws itself, then I'd put it inBlock
, but if aRenderer
draws aBlock
, I'd put it intoRenderer
.
– user1118321
Oct 11 at 16:12
add a comment |
up vote
0
down vote
up vote
0
down vote
This is really not that bad. Despite the variable names not being in English, I'm able to get the gist of it. Here are some useful things that I think would improve the situation.
Avoid Globals
Your first header is mainly a list of global variables. Globals are difficult to work with because they can be changed by any code anywhere in your app. So when a problem occurs with a global, good luck tracking down where it occurs since it could be anywhere. If you put your global data into classes, you'll have minimized the number of places where it could be going wrong.
Let's start with the textures you use. Textures make up a large part of most video games. It would probably make sense to have an object which handles textures. It could load them from disk, give them to code to use, cache recently used textures, etc. I would probably make either a TextureFactory
class, or a TextureCache
class to handle these sorts of tasks. It might not be necessary here since you only have about 5-10 textures, but any more than that and you'll probably want something to organize them.
Use struct
or class
to Combine Data
Notice how after the texture declarations, you have corresponding declarations of rectangles. This is a clue that you should be creating either a struct
or class
that holds both the texture and its rectangle.
Next you declare a bunch of variables for things like the number of lives, current level, the number of blocks on screen, spacing of various elements. These fall into 2 broad categories - game state, and rendering constants. I would make 2 classes for these: GameState
which holds things like the number of lives left and the current level, and GameRenderer
which holds data related to rendering. I notice there's an SDL_Renderer
, so you should probably also put that into your GameRenderer
class.
You make a lot of use of std::pair
for storing coordinates and impact counts. std::pair
is a difficult class to deal with because it's so non-specific. Its data members, first
and second
are meaningless. You should make a Point
or Vector
class
to hold coordinates. You should then make a Block
struct
or class
to hold a Point
or Vector
and an impact count. Then your koordinateBlockovaVektor
vector would be declared as just:
std::vector<Block> koordinateBlokovaVektor;
Naming
I don't speak your language, but I assume Logika
is Logic
and Crtaj
is Draw
? If so, I would recommend using more descriptive names, like UpdateGameState()
and RenderGame()
(or whatever that would be in your native tongue).
I would also avoid putting the type name into the variable's name. So a std::vector
doesn't need to have Vektor
in it's name. If you had a class
or struct
for your textures, you could simply call the rectangle the bounds
or frame
or something along those lines. Something like this:
struct GameTexture {
SDL_Texture* image;
SDL_Rect bounds;
};
Then to access one, you could do:
GameTexture pozadina;
// ... fill it out ...
SDL_RenderCopy(renderer, pozadina.image, NULL, &pozadina.bounds);
This is really not that bad. Despite the variable names not being in English, I'm able to get the gist of it. Here are some useful things that I think would improve the situation.
Avoid Globals
Your first header is mainly a list of global variables. Globals are difficult to work with because they can be changed by any code anywhere in your app. So when a problem occurs with a global, good luck tracking down where it occurs since it could be anywhere. If you put your global data into classes, you'll have minimized the number of places where it could be going wrong.
Let's start with the textures you use. Textures make up a large part of most video games. It would probably make sense to have an object which handles textures. It could load them from disk, give them to code to use, cache recently used textures, etc. I would probably make either a TextureFactory
class, or a TextureCache
class to handle these sorts of tasks. It might not be necessary here since you only have about 5-10 textures, but any more than that and you'll probably want something to organize them.
Use struct
or class
to Combine Data
Notice how after the texture declarations, you have corresponding declarations of rectangles. This is a clue that you should be creating either a struct
or class
that holds both the texture and its rectangle.
Next you declare a bunch of variables for things like the number of lives, current level, the number of blocks on screen, spacing of various elements. These fall into 2 broad categories - game state, and rendering constants. I would make 2 classes for these: GameState
which holds things like the number of lives left and the current level, and GameRenderer
which holds data related to rendering. I notice there's an SDL_Renderer
, so you should probably also put that into your GameRenderer
class.
You make a lot of use of std::pair
for storing coordinates and impact counts. std::pair
is a difficult class to deal with because it's so non-specific. Its data members, first
and second
are meaningless. You should make a Point
or Vector
class
to hold coordinates. You should then make a Block
struct
or class
to hold a Point
or Vector
and an impact count. Then your koordinateBlockovaVektor
vector would be declared as just:
std::vector<Block> koordinateBlokovaVektor;
Naming
I don't speak your language, but I assume Logika
is Logic
and Crtaj
is Draw
? If so, I would recommend using more descriptive names, like UpdateGameState()
and RenderGame()
(or whatever that would be in your native tongue).
I would also avoid putting the type name into the variable's name. So a std::vector
doesn't need to have Vektor
in it's name. If you had a class
or struct
for your textures, you could simply call the rectangle the bounds
or frame
or something along those lines. Something like this:
struct GameTexture {
SDL_Texture* image;
SDL_Rect bounds;
};
Then to access one, you could do:
GameTexture pozadina;
// ... fill it out ...
SDL_RenderCopy(renderer, pozadina.image, NULL, &pozadina.bounds);
answered Oct 11 at 4:40
user1118321
10.7k11145
10.7k11145
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
It depends on how you use them. If aBlock
draws itself, then I'd put it inBlock
, but if aRenderer
draws aBlock
, I'd put it intoRenderer
.
– user1118321
Oct 11 at 16:12
add a comment |
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
It depends on how you use them. If aBlock
draws itself, then I'd put it inBlock
, but if aRenderer
draws aBlock
, I'd put it intoRenderer
.
– user1118321
Oct 11 at 16:12
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
Thanks for all good tips you gave me, my question is: when we talk about global variables, in this case I want to define some const int's like ball width,height, number of blocks per lvl etc. Where do I store them in this case?RenderGame() or at definition of Block?
– Marko Petričević
Oct 11 at 6:20
It depends on how you use them. If a
Block
draws itself, then I'd put it in Block
, but if a Renderer
draws a Block
, I'd put it into Renderer
.– user1118321
Oct 11 at 16:12
It depends on how you use them. If a
Block
draws itself, then I'd put it in Block
, but if a Renderer
draws a Block
, I'd put it into Renderer
.– user1118321
Oct 11 at 16:12
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f205324%2fc-breakout-game-using-sdl%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I don't know if it suits your needs but I made this breakout clone using SDL in the past It's from my noob days into programming, so it's mostly shitty, so take it as it is. Maybe it will guide you in the direction you seek.
– RandomOne
Oct 10 at 19:39