//Ukazka C++ kodu. Islo o zadanie v ktorom sa mal použiť prilozeny Engine #include "SDL.h" #include "..\Engine\System.h" #include "..\Engine\Image.h" #include "..\Engine\Input.h" #include #include "..\Engine\Font.h" using namespace std; //define the variable needed for board size #define boardX 12 #define boardY 12 #define maxLevels 10 class Brick { public: int hp; bool alive, bomb, antyBomb, addBall, ballSpeed, powerBall, detonateAll; bool haveSpecialEfect; int x1, x2, y1, y2; Image myImage; void SetEffect( int bombRate, int antyBombRate, int addBallRate, int speedRate, int powerRate); void SetUniqueEffect(bool doDetonateAll); }; //seting function for special efect seting on brick void Brick::SetEffect( int bombRate, int antyBombRate, int addBallRate, int speedRate, int powerRate) { int value = rand() % 100; int rate = 99; //i have %rate +1 for purposes bool abilitySet = false; if (bombRate > 0) { rate -= bombRate; if (value >= rate) { bomb = true; abilitySet = true; } } if (abilitySet == false && antyBombRate > 0) { rate -= antyBombRate; if (value >= rate) { antyBomb = true; abilitySet = true; } } if (abilitySet == false && addBallRate > 0) { rate -= addBallRate; if (value >= rate) { addBall = true; abilitySet = true; } } if (abilitySet == false && speedRate > 0) { rate -= speedRate; if (value >= rate) { ballSpeed = true; abilitySet = true; } } if (abilitySet == false && powerRate > 0) { rate -= powerRate; if (value >= rate) { powerBall = true; abilitySet = true; } } if (abilitySet == true) haveSpecialEfect = true; }//set effect //probably dont need it void Brick::SetUniqueEffect(bool doDetonateAll) { if (doDetonateAll) { detonateAll = true; haveSpecialEfect = true; } } class Board { public: int level=0; int sup; // support variable public: Brick bricks[boardX][boardY]; void CreateLevel(int forcedLevel); int RetunCurentLvel() { return level; } //for game counting of sucesed levels }; void Board::CreateLevel(int forcedLevel){ if (forcedLevel < 1 || forcedLevel > maxLevels) level = rand() % maxLevels + 1; //random number from 1 to maxLevels else level = forcedLevel; bool creationDone = false; //standart reset of field for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { Brick brick; brick.x1 = 35 + (i * 61); brick.x2 = brick.x1 + 61; brick.y1 = 50 + 50 + (j * 22); brick.y2 = brick.y1 + 22; brick.bomb = false; brick.antyBomb = false; brick.addBall = false; brick.ballSpeed = false; brick.powerBall = false; brick.detonateAll = false; brick.haveSpecialEfect = false; brick.alive = true; brick.hp = 5; bricks[i][j] = brick; } } if (level == 1) { // 5 rows hp as row //small wall for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (j < 5) { bricks[i][j].hp = j + 1; if (j == 4) { bricks[i][j].SetEffect(5, 5, 0, 5, 2); } } else { bricks[i][j].hp = 0; bricks[i][j].alive = false; } } } creationDone = true; } if (level == 2) { // all gray //painball ready for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { bricks[i][j].hp = 1; if (j > 9) { //dificulty decrasing bricks[i][j].alive = false; } else { bricks[i][j].SetEffect( 5, 5, 5, 5, 0); } } } creationDone = true; } if (level == 3) { // 8 colums random hp //emotional painting for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (j < 8) { int r = rand() % 5 + 1; bricks[i][j].hp = r; bricks[i][j].SetEffect(5, 5, 5, 5, 5); } else { bricks[i][j].alive = false; } } } creationDone = true; } if (level == 4) { // 10 colus 2full 2 emty hp =3 //barels for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (i == 1 || i == 2 || i == 5 || i==6 || i==9 || i==10) { bricks[i][j].hp = 3; bricks[i][j].SetEffect(5, 0, 5, 0, 3); } else { bricks[i][j].alive = false; } } } creationDone = true; } if (level == 5) { // 10 colus 2full 2 emty hp 1x3, 2x2 //sheep fence for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (j == 1 || j == 2 || j == 9 || j == 10) { bricks[i][j].hp = 2; } else if (j == 5 || j == 6) { bricks[i][j].hp = 3; bricks[i][j].SetEffect(0, 0, 5, 0, 3); } else { bricks[i][j].alive = false; } } } creationDone = true; } if (level == 6) { // 6x6 colus around hp=5 insade hp=1-3 //granny garden for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (j > 2 && j < 9) { if (i > 2 && i < 9) { int r = rand() % 3 + 1; if (j == 3 || j == 8) { r = 5; } else if (i == 3 || i == 8) { r = 5; } bricks[i][j].hp = r; bricks[i][j].SetEffect(5, 0, 0, 5, 10); } else { bricks[i][j].alive = false; } } else { bricks[i][j].alive = false; } } } creationDone = true; } if (level == 7) { //diamond int stred = 6; int k = stred, l = stred; for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (j >= k && j <= l) { if (j > k && j < l) { bricks[i][j].hp = 1; if (i != stred && j != stred) { bricks[i][j].SetEffect(0, 0, 5, 5, 20); } else { //bricks[stred][stred].SetUniqueEffect(true); //detonateAll bricks[stred][stred].detonateAll = true; bricks[stred][stred].haveSpecialEfect = true; bricks[stred][stred].hp = 3; } } else { bricks[i][j].hp = 5; } if (j == 11 && i == stred) bricks[i][j].hp = 6; } else { bricks[i][j].alive = false; } } if (i < 6) { k--; l++; } else { k++; l--; } } creationDone = true; } if (level == 8) { // diner Pot for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++){ if(i > 0 && i < boardX - 1 && j > 0 && j < boardY -2){ if (i > 1 && i < boardX - 2 && j > 0 && j < boardY - 3) { int r = rand() % 4 + 1; bricks[i][j].hp = r; bricks[i][j].SetEffect(5, 5, 5, 5, 10 ); } else { bricks[i][j].hp = 5; } } else { bricks[i][j].alive = false; } if (i == boardX - 2 && (j == 6 || j == 5)) { bricks[i][j].hp = 8; bricks[i][j].detonateAll = true; bricks[i][j].haveSpecialEfect = true; } } } creationDone = true; } if (level == 9) { // pulover int k = 1; bool increase = true; for (int j = 0; j < boardY; j++){ for (int i = 0; i < boardX; i++) { if (j < 10) { bricks[i][j].hp = k; bricks[i][j].SetEffect(5, 5, 5, 5, 15); } else { bricks[i][j].alive = false; } } if (increase == true) { k++; if (k == 5) increase = false; } else { k--; if (k == 1) //shall not need it increase = true; } } creationDone = true; } if (level == 10) { // Invaders for (int j = 0; j < boardY; j++) { for (int i = 0; i < boardX; i++) { if (j > 0) { bricks[i][j].hp = 1; bricks[i][j].SetEffect(0, 50, 15, 5, 0); } else { bricks[i][j].alive = false; if (i == 6) { bricks[i][j].alive = true; bricks[i][j].hp = 5; bricks[i][j].detonateAll = true; bricks[i][j].powerBall = true; bricks[i][j].addBall = true; bricks[i][j].ballSpeed = true; bricks[i][j].haveSpecialEfect = true; } } } } creationDone = true; } //if (creationDone == false) // CreateLevel(1); //this shall clear some mis hits } class Ball2 { public: int ball_x = 400, ball_y = 400; float ball_dx = 1, ball_dy = 1, speed; int lastXOfBoard=0; int pointOfHit = 0; float value = 0; bool onBoard = false, ballInAction = false; bool simpleBounc = false; bool directionChanged = false; void Update(int ball_speed, int window_Offset, int window_size_x, int window_size_y, int window_upy, int player_x, int player_y); void HitThePlayer(int player_x, int player_y); void StickTheBall(int player_x, int player_y); }; void Ball2::Update(int ball_speed, int window_Offset, int window_size_x, int window_size_y, int window_upy, int player_x, int player_y) { if (onBoard == false) { speed = (float)( 6 + ball_speed); //ball_x += (int)(ball_dx * (float)ball_speed) ; //ball_y += (int)(ball_dy * (float)ball_speed) ; ball_x += (int)(ball_dx * speed ); ball_y += (int)(ball_dy * speed ); if (ball_x < 0) ball_dx = abs(ball_dx); //was 1 if (ball_x + 18 > window_size_x) ball_dx = -abs(ball_dx); //was -1 if (ball_y < window_upy) ball_dy = abs(ball_dy); //was 1 if (ball_y > window_size_y) { //ball_dy = -1; //standart bounce from bottom ballInAction = false; } } else { ball_x = player_x + 35; } } void Ball2::HitThePlayer(int player_x, int player_y) { if (onBoard == false) if (ball_y + 18 >= player_y && ball_y <= player_y + 25) { //bal 18x18 board 85x25 if (ball_x <= player_x + 85 && ball_x+18 >= player_x) { if (simpleBounc == true) { ball_dy = -ball_dy; if (ball_x + 9 > player_x + 42) { ball_dx = abs(ball_dx); //was 1 } else { ball_dx = -abs(ball_dx); } //was -1} } else { pointOfHit = -(player_x + 42) + ball_x; value = (float)pointOfHit / 100; float dirx = 0.5f + (abs(value) ); float diry = 1 - (abs(value) ); if (pointOfHit > 0) { ball_dx = dirx; } else { ball_dx = -dirx; } if (ball_y + 9 > player_y + 25) { ball_dy = diry; } else { ball_dy = -diry; } } } } } void Ball2::StickTheBall(int player_x, int player_y) { ball_x = player_x + 15; //35 before ball_y = player_y - 21; //18 size, visual +9 //last 40 onBoard = true; if (simpleBounc == true) { ball_dy = -abs(ball_dy); } else { ball_dy = -1; ball_dx = 0; } lastXOfBoard = player_x; } int main(int argc, char* argv[]) { Image im_ball, im_background, im_player, im_brick_grey, im_brick_green, im_brick_blue, im_brick_orange, im_brick_red; //p1 Image im_special, im_effect; System system; int window_size_x = 800, window_size_y = 600, window_upy = 50, window_Offset =10; int player_x = 400, player_y = 550; bool someBrickAreAlive = false, gameOn = false, simpleMenuOn = true; bool escapeDown =false; bool space = false; int ball_speed = 1, ball_maxSpeed = 5, ball_originalSpeed=1, player_Speed = 10; int forcedLevel = 0, currentLevel = 0; int powerOfBAll = 1; //controll int keysTimer = 0, escapeTimer=0; bool keyPressed = false, escapedLevel = false; int lives = 0, bricksAlive=0, bricksHP=0; bool levelsDone[maxLevels +1]; for (int i = 0; i < maxLevels + 1; i++) { levelsDone[i] = false; } std::string boardHead; std::string levelNames[maxLevels +1]; levelNames[0] = "Free"; levelNames[1] = "Small wall"; levelNames[2] = "Painball ready"; levelNames[3] = "Emotional Painting"; levelNames[4] = "Barels"; levelNames[5] = "Fence for Sheeps"; levelNames[6] = "Grany Garden"; levelNames[7] = "Diamont"; levelNames[8] = "Dinner Pot"; levelNames[9] = "Pulover"; levelNames[10] = "Alien Invaders"; //Notice for myself always chesk if array leng are correct Ball2 myball2; myball2.StickTheBall(player_x, player_y); Brick brick1; brick1.alive = true; brick1.hp = 1; Board myBoard; //myBoard.CreateLevel(); //moved if (!system.Init()) { return 0; } Input inputSystem; bool running = true; im_ball.LoadImage(system.GetRenderer(), "../data/graphics/ball.bmp"); //p1 im_background.LoadImage(system.GetRenderer(), "../data/graphics/background.bmp"); im_player.LoadImage(system.GetRenderer(), "../data/graphics/pad_normal_04.bmp"); im_brick_grey.LoadImage(system.GetRenderer(), "../data/graphics/brick_grey.bmp"); im_brick_green.LoadImage(system.GetRenderer(), "../data/graphics/brick_green.bmp"); im_brick_blue.LoadImage(system.GetRenderer(), "../data/graphics/brick_blue.bmp"); im_brick_orange.LoadImage(system.GetRenderer(), "../data/graphics/brick_orange.bmp"); im_brick_red.LoadImage(system.GetRenderer(), "../data/graphics/brick_red.bmp"); im_special.LoadImage(system.GetRenderer(), "../data/graphics/power_up_laser.bmp"); im_effect.LoadImage(system.GetRenderer(), "../data/graphics/power_up_enlarge.bmp"); Font arialFond; arialFond.LoadFromFile("../data/fonts/arial.ttf"); do { inputSystem.Update(); SDL_Event event; while (SDL_PollEvent(&event)) { inputSystem.ProcessInputEvent(event); switch (event.type) { case SDL_QUIT: { running = false; } break; } } //escape function //running &= !inputSystem.IsEscapeKeyDown(); //original escapeDown = !inputSystem.IsEscapeKeyDown(); if (escapeDown == false) { keyPressed = true; if (gameOn == true) { gameOn = false; simpleMenuOn = true; escapedLevel = true; } //the program shall not end itself right from level if (simpleMenuOn == true && escapedLevel == false) { running = false; } } system.Clear(); //level lost if(gameOn == true){ if (currentLevel == 0) { currentLevel = myBoard.RetunCurentLvel(); } if (myball2.ballInAction == false) { if (lives > 0) { lives--; myball2.StickTheBall(player_x, player_y); myball2.ballInAction = true; ball_speed = ball_originalSpeed; powerOfBAll = 1; } else { gameOn = false; simpleMenuOn = true; } } //padle control bool left = inputSystem.IsLeftKeyDown(); //p1 bool right = inputSystem.IsRightKeyDown(); //p1 if (left == true) { player_x -= player_Speed + ball_speed; } //p1 if (right == true) { player_x += player_Speed + ball_speed; } //p1 if (player_x < 0) player_x = 0; if (player_x + 85 > window_size_x) player_x = window_size_x - 85; space= inputSystem.IsDownKeySpace(); if (space == true) { //launch ball from pad, re catch not implemented myball2.onBoard = false; } im_background.Render(system.GetRenderer(), 0, 0, 1, 1, 0); //p1 im_player.Render(system.GetRenderer(), player_x, player_y, 1, 1, 0); //p1 myball2.Update(ball_speed, window_Offset, window_size_x, window_size_y, window_upy, player_x, player_y); //test of display im_ball.Render(system.GetRenderer(), myball2.ball_x, myball2.ball_y, 1, 1, 0); //atemt on solve multiple bounces by one ball agaist multiple bricks at once myball2.directionChanged = false; //display and manipulation with brick for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (myBoard.bricks[i][j].alive) { if (myBoard.bricks[i][j].hp >= 5) myBoard.bricks[i][j].myImage = im_brick_red; else if (myBoard.bricks[i][j].hp == 4) myBoard.bricks[i][j].myImage = im_brick_orange; else if (myBoard.bricks[i][j].hp == 3) myBoard.bricks[i][j].myImage = im_brick_blue; else if (myBoard.bricks[i][j].hp == 2) myBoard.bricks[i][j].myImage = im_brick_green; else myBoard.bricks[i][j].myImage = im_brick_grey; //for potentional bug where hp is lover that 1, but is still mark as alive, so player will not see hit emty space but brick myBoard.bricks[i][j].myImage.Render(system.GetRenderer(), myBoard.bricks[i][j].x1, myBoard.bricks[i][j].y1, 1, 1, 0); if (myBoard.bricks[i][j].haveSpecialEfect == true && myBoard.bricks[i][j].detonateAll == false){ im_effect.Render(system.GetRenderer(), myBoard.bricks[i][j].x1 +20, myBoard.bricks[i][j].y1, 0.75, 0.75, 0); } if (myBoard.bricks[i][j].detonateAll == true) { im_special.Render(system.GetRenderer(), myBoard.bricks[i][j].x1 + 20, myBoard.bricks[i][j].y1, 0.75, 0.75, 0); } //ball hit the brick //if i have multiple balls then there shall be for(for each ball(limited array of max balls)), and if(active) if (myball2.ball_x + 18 >= myBoard.bricks[i][j].x1 && myball2.ball_x <= myBoard.bricks[i][j].x2) { if (myball2.ball_y + 18 >= myBoard.bricks[i][j].y1 && myball2.ball_y <= myBoard.bricks[i][j].y2) { myBoard.bricks[i][j].hp -= powerOfBAll; if (myBoard.bricks[i][j].hp <= 0) { myBoard.bricks[i][j].alive = false; //special effect on hit by ball not tested due intervention of higger force //bomb reduce hp on lines if (myBoard.bricks[i][j].bomb == true) { for (int k = 0; k < boardX; k++) { if (myBoard.bricks[i][k].alive == true) { myBoard.bricks[i][k].hp--; } if (myBoard.bricks[k][j].alive == true) { myBoard.bricks[k][j].hp--; } } } //anti bomb increase the hp of near brick in square if (myBoard.bricks[i][j].antyBomb == true) { for (int k = 0; k < boardX; k++) { if (myBoard.bricks[i][k].alive == true) { myBoard.bricks[i][k].hp++; } if (myBoard.bricks[k][j].alive == true) { myBoard.bricks[k][j].hp++; } } } if (myBoard.bricks[i][j].addBall == true) { lives++; } //ball speed increase if (myBoard.bricks[i][j].ballSpeed == true) { if (ball_speed < ball_maxSpeed) { ball_speed++; } else { lives++; } } //that shall reset every time if no active ball on field if (myBoard.bricks[i][j].powerBall == true) { powerOfBAll++; } if (myBoard.bricks[i][j].detonateAll == true) { for (int i1 = 0; i1 < boardX; i1++) { for (int j1 = 0; j1 < boardY; j1++) { if(myBoard.bricks[i1][j1].alive == true ) myBoard.bricks[i1][j1].hp -= 1; } } } }//hp 0; int ball_Offset = 1; //ball bouncing from the brick if (myball2.directionChanged == false) { //only one change of direction per tic if (myball2.ball_x + 8 <= myBoard.bricks[i][j].x1) { myball2.ball_dx = -abs(myball2.ball_dx); myball2.directionChanged = true; } if (myball2.ball_x + 8 >= myBoard.bricks[i][j].x2) { myball2.ball_dx = abs(myball2.ball_dx); myball2.directionChanged = true; } if (myball2.ball_y + 8 <= myBoard.bricks[i][j].y1) { myball2.ball_dy = -abs(myball2.ball_dy); myball2.directionChanged = true; } if (myball2.ball_y + 8 >= myBoard.bricks[i][j].y2){ myball2.ball_dy = abs(myball2.ball_dy); myball2.directionChanged = true; } } // } } //secondary security doing for -hp from bomb if (myBoard.bricks[i][j].hp <= 0) { myBoard.bricks[i][j].alive = 0; } }//alive } } //victory condition and statistic someBrickAreAlive = false; bricksAlive = 0; bricksHP = 0; for (int i = 0; i < boardX; i++) { for (int j = 0; j < boardY; j++) { if (myBoard.bricks[i][j].alive) { someBrickAreAlive = true; bricksAlive++; bricksHP += myBoard.bricks[i][j].hp; } } } //victory procesing if (someBrickAreAlive == false) { levelsDone[currentLevel] = true; player_x = 400; myball2.StickTheBall(player_x, player_y); myBoard.CreateLevel(forcedLevel +1); //add +1 bacause canot test, ower pass will be solved insade function bool levelSet = false; int secureNumber = 0, levelOder=0; while (levelSet ==false) { secureNumber++; if (secureNumber > 20){ levelSet = true; forcedLevel = 0; // random option } levelOder = rand() % 6 + 1; if (levelsDone[levelOder] == false) { levelSet = true; forcedLevel = levelOder; } } myBoard.CreateLevel(forcedLevel); ball_speed = ball_originalSpeed; if (lives < 3) lives = 3; powerOfBAll = 1; } //someBrickAreAlive myball2.HitThePlayer(player_x, player_y); boardHead = "Lives: " + std::to_string(lives) + " Speed: " + std::to_string(ball_speed) + " Power: " + std::to_string(powerOfBAll) + " Bricks: " + std::to_string(bricksAlive) + " All-HP: " + std::to_string(bricksHP) + " " + levelNames[currentLevel]; arialFond.Render(system.GetRenderer(), boardHead, 0, 0, 1, 1, 1); //security measure by displaying wariables about ball int vv = myball2.pointOfHit; int vx = (int)(myball2.ball_dx * 100); int vy = (int)(myball2.ball_dy * 100); string ballData = "value: " + std::to_string(vv) + " dx:" + std::to_string(vx) + " dy:" + std::to_string(vy); arialFond.Render(system.GetRenderer(), ballData, 550, 0, 1, 1, 1); } //Game menu, creation of menu with buttons hit a obstacles that leads to drop down the hopes for menu if (simpleMenuOn == true) { if (currentLevel != 0) currentLevel = 0; // \n /n dint working here std::string s1 = "Use arows Up and down. For continue pres Space Bar. For Exit press Esc."; std::string s2 = "Next Lelel is: "; std::string s3 = "Random"; std::string s4 = "Level Name"; std::string stringA = ""; if (forcedLevel == 0) { stringA = s2 + s3; } else { stringA = s2+ std::to_string(forcedLevel); } int step = 100; arialFond.Render(system.GetRenderer(), s1, 100,100, 1 ,1 ,1 ); step += 20; arialFond.Render(system.GetRenderer(), stringA, 100, step, 1, 1, 255); //potential solution if we have a manny of levels, //but then there will be problem whit not enof space to display all //that can be solved by limited display based on last played, free and, player navigation trough menu float colorA = 1, colorB = 1; std::string stringb = ""; for (int i = 1; i < maxLevels + 1; i++) { step += 20; if (levelsDone[i] == true) colorA = 255; else colorA = 1; if (i == forcedLevel) colorB = 255; else colorB = 1; stringb = std::to_string(i) + " - " + levelNames[i]; arialFond.Render(system.GetRenderer(), stringb, 100, step, 1, colorB, colorA); } //security display of time denied efect for IsDownKey and not IsPresedDown (or something similiar) step += 20; arialFond.Render(system.GetRenderer(), ("key timer: "+ std::to_string(keysTimer) ), 100, step, 1, 1, 1); //Menu Operator space = inputSystem.IsDownKeySpace(); if (space == true && keyPressed == false) { simpleMenuOn = false; gameOn = true; myBoard.CreateLevel(forcedLevel); someBrickAreAlive = true; if(lives < 3) lives = 3; ball_speed = ball_originalSpeed; //for secure purpose, powerOfBAll = 1; player_x = 400; player_y = 550; myball2.StickTheBall(player_x, player_y); //when scrip whit more balls will be aviable reset to one } if (escapedLevel == true) { escapeTimer++; if (escapeTimer >= 10) { escapeTimer = 0; escapedLevel = false; } } if (keyPressed == true) { keysTimer++; if (keysTimer >= 20) { keysTimer = 0; keyPressed = false; } } if (inputSystem.IsUpKeyDown() == true && keyPressed == false) { forcedLevel--; keyPressed =true; if (forcedLevel > maxLevels) forcedLevel = 0; } if (inputSystem.IsDownKeyDown() == true && keyPressed == false) { forcedLevel++; keyPressed = true; if (forcedLevel < 0) forcedLevel = maxLevels; } } //simpleMenuOn system.Flip(); } while (running); return 0; }