void GetImages() { Brick(100,100,BLUE); //Draw blue brick Brick(130,100,RED); //Draw red brick Brick(160,100,GREEN); //draw green brick Brick(190,100,YELLOW); //draw yellow brick Brick(220,100,PURPLE); //draw purple brick //Taking the area of the images bmpBlueBrick = malloc(imagesize(0,0,20,20)); bmpRedBrick = malloc(imagesize(0,0,20,20)); bmpGreenBrick = malloc(imagesize(0,0,20,20)); bmpYellowBrick = malloc(imagesize(0,0,20,20)); bmpPurpleBrick = malloc(imagesize(0,0,20,20)); bmpBlankBrick = malloc(imagesize(0,0,20,20)); bmpScore = malloc(imagesize(501,51,607,69)); bmpSpeed = malloc(imagesize(501,51,607,69)); bmpLevel = malloc(imagesize(501,51,607,69)); bmpLinesCleared= malloc(imagesize(501,51,607,69)); bmpScreen = malloc(imagesize(0,0,640,480)); //Saving the images getimage(100,100,120,120,bmpBlueBrick); getimage(130,100,150,120,bmpRedBrick); getimage(160,100,180,120,bmpGreenBrick); getimage(190,100,210,120,bmpYellowBrick); getimage(220,100,240,120,bmpPurpleBrick); getimage(0,0,20,20,bmpBlankBrick); getimage(501,51,607,69,bmpScore); getimage(501,51,607,69,bmpSpeed); getimage(501,51,607,69,bmpLevel); getimage(501,51,607,69,bmpLinesCleared); }
bool LevelManager::loadLevel(int levelNumber){ ofFile file = ofFile("level" + ofToString(levelNumber) + ".txt"); if (file.exists()) { currentLevel = levelNumber; vector<string> lines = ofSplitString(ofBufferFromFile(ofToDataPath("level" + ofToString(levelNumber) + ".txt")).getText(), "\n"); vector<vector<Brick> > rows; int brickWidth = ofGetWidth()/10; int brickHeight = ofGetHeight()/15; for(int i = 0; i < lines.size(); i++){ string line = lines[i]; vector<Brick> row; for(int j = 0; j<lines[i].size();j++){ char block = line[j]; if (block == '0'){ } if (block == '1'){ row.push_back(Brick(gm, 1, 10, ofColor::red, ofVec2f(((j+1)*brickWidth) - brickWidth / 2,((i+1)*brickHeight) - brickHeight / 2), brickWidth, brickHeight)); } if (block == '2'){ row.push_back(Brick(gm, 2, 20, ofColor::blueViolet, ofVec2f((j+1)*brickWidth - brickWidth / 2,(i+1)*brickHeight - brickHeight / 2), brickWidth, brickHeight)); } if (block == '3'){ row.push_back(Brick(gm, 3, 50, ofColor::purple, ofVec2f((j+1)*brickWidth - brickWidth / 2,(i+1)*brickHeight- brickHeight / 2), brickWidth, brickHeight)); } if (block == '4'){ row.push_back(Brick(gm, 4, 100, ofColor::chocolate, ofVec2f((j+1)*brickWidth - brickWidth / 2,(i+1)*brickHeight - brickHeight / 2), brickWidth, brickHeight)); } } rows.push_back(row); } levels.push_back(Level(rows)); return true; } else { return false; } }
void Game::initBricks () { bricks.clear (); bricks.resize (numBricks); vec3 start (-1.0, 0.75, 0); float xInc = .125; float yInc = .125; for (unsigned i = 0; i < bricks.size (); ++i){ bricks[i] = Brick (start); initGeometry (&bricks[i]); start.x += xInc; if (start.x > (1.0 - bricks[i].size)) { start.x = -1; start.y -= yInc; } } }
Wall::Wall() { sf::Color clist[5] = { sf::Color(219, 79, 60), sf::Color(231, 231, 93), sf::Color(69, 192, 120), sf::Color(69, 76, 192), sf::Color(225, 70, 184) }; srand(time(NULL)); int design = rand() % 3; for (int i = 0; i < ROWS; i++) { std::vector<Brick> tmpBrick; for (int j = 0; j < COLUMNS; j++) { sf::Vector2f pos((BRICK_BUFFER + BRICK_WIDTH) * j + BRICK_BUFFER / 2, BUFFER_ZONE + (BRICK_HEIGHT + BRICK_BUFFER) * i); sf::Vector2f s_size(BRICK_WIDTH, BRICK_HEIGHT); tmpBrick.push_back(Brick(pos, s_size, get_design(i, j, design, clist))); } grid.push_back(tmpBrick); } }
GameLogic::GameLogic(int Width, int Height, float LogicFPS) { Debug = false; Display = NULL; EventQueue = NULL; Timer = NULL; Bitmap.Logo = NULL; Bitmap.Title = NULL; Font.Small = NULL; Font.Medium = NULL; Font.Big = NULL; Sound.HitWall = NULL; Sound.HitPaddle = NULL; Sound.BackgroundMusic = NULL; UserDataFile = NULL; DisplayWidth = Width; DisplayHeight = Height; TimerStep = 1.0 / LogicFPS; bool key[2] = { false, false }; float alpha = 0; float colr = 0; float colg = 0; float colb = 0; int tick = 0; int menu = 0; int high_score = 0; bool restart = true; int score = 0, multi = 1, final_score = 1; bool game_over, redraw; char scoretxt[8] = ""; char multitxt[4] = ""; char final_scoretxt[16] = ""; char hightxt[16] = ""; // intro screen while (1) { ALLEGRO_EVENT ev; al_wait_for_event(EventQueue, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { // trigger redraw tick++; if(tick < 180) { colr = colg = colb = (0.5 * sin( (tick - 90) * ALLEGRO_PI / 180.0) + 0.5); alpha = 0; } else if(tick < 360) { alpha = (0.5 * sin( (tick + 90) * ALLEGRO_PI / 180.0) + 0.5); colr = colg = colb = 1; } else if(tick > 450 && tick < 630) { colr = colg = colb = alpha = (0.5 * cos( (tick - 90) * ALLEGRO_PI / 180.0) + 0.5); } else if(tick > 632) { break; } redraw = true; } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { return; } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { break; } if(redraw && al_is_event_queue_empty(EventQueue)) { redraw = false; al_clear_to_color(al_map_rgb_f(colr,colg,colb)); al_draw_tinted_bitmap(Bitmap.Logo, al_map_rgba_f(alpha, alpha, alpha, alpha), (DisplayWidth - al_get_bitmap_width(Bitmap.Logo) ) / 2, (DisplayHeight - al_get_bitmap_height(Bitmap.Logo) )/ 2, 0); al_flip_display(); } } al_flip_display(); al_clear_to_color(al_map_rgb(0,0,0)); // load hiscore info UserDataFile = al_fopen("assets/hiscore.txt", "r"); if(UserDataFile) { char *line = (char*) malloc (17); line = al_fgets(UserDataFile, line, 17); high_score = atoi(line); free(line); } else { high_score = 0; } final_score = 0; sprintf(hightxt, "High: %d", high_score); al_fclose(UserDataFile); // main menu loop while (1) { ALLEGRO_EVENT ev; al_wait_for_event(EventQueue, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { // trigger redraw redraw = true; } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { // exit if the Display is closed return; } else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { // track mouse movement if((ev.mouse.y > 350) && (ev.mouse.y < 388) && (ev.mouse.x > 250) && (ev.mouse.x < 388)) { menu = 1; } else { menu = 0; } } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { // track mouse clicks if(menu == 1) { break; } } if(redraw && al_is_event_queue_empty(EventQueue)) { // process entire queue and only render if the Timer has ticked redraw = false; al_clear_to_color(al_map_rgb(0,0,0)); al_draw_bitmap(Bitmap.Title, (DisplayWidth - al_get_bitmap_width(Bitmap.Title) ) / 2, 16, 0); al_draw_text(Font.Small, al_map_rgb(128,128,0), DisplayWidth / 2, 250, ALLEGRO_ALIGN_CENTRE, "Version 0.1"); if(menu == 1) { al_draw_text(Font.Medium, al_map_rgb(128,0,0), DisplayWidth / 2, 350, ALLEGRO_ALIGN_CENTRE, "Play Now!"); } else { al_draw_text(Font.Medium, al_map_rgb(128,128,0), DisplayWidth / 2, 350, ALLEGRO_ALIGN_CENTRE, "Play Now!"); } al_flip_display(); } } // seed rand function srand(al_get_time()); // game wrapper lets us restart the game while(restart) { // hide the cursor //al_hide_mouse_cursor(Display); // assume we don't want to play again restart = false; // Base objects Ball StarterBall = Ball(); Paddle StarterPaddle = Paddle(0); Paddle StarterPaddle2 = Paddle(DisplayHeight - 8); Paddle StarterPaddle3 = Paddle(0, true); Paddle StarterPaddle4 = Paddle(DisplayWidth - 8, true); // TODO: load the right map // set Bitmap.Title // set base speed // create list of block entities // Populate entity lists // Remove static data when we get map loading done for(int i=0; i < 64; i++) { Brick SingleBlockyEntity = Brick((i % 16) * 40, 80 + ( (i / 16) * 10), i % 8); Bricks.push_back(SingleBlockyEntity); } Paddles.push_back(StarterPaddle); Paddles.push_back(StarterPaddle2); Paddles.push_back(StarterPaddle3); Paddles.push_back(StarterPaddle4); Balls.push_back(StarterBall); // save high score if the final score is higher if(final_score > high_score) { high_score = final_score; sprintf (hightxt, "High: %d", high_score); } // reset score if not a continuation // init hud // force initial draw redraw = true; // reset physics game_over = false; // main game loop while(1) { ALLEGRO_EVENT ev; al_wait_for_event(EventQueue, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { // game logic loop if(!game_over) { // calculate each ball's new position and check for... Path CurrentPath; for(int i = 0; i < Balls.size(); i++) { CurrentPath = Balls[i].GetPath(TimerStep); // distance traveled in axis directions in time delta t float NX = Balls[i].Position.DeltaX * TimerStep; float NY = Balls[i].Position.DeltaY * TimerStep; // new unencombered position float NewPositionX = Balls[i].Position.X + NX; float NewPositionY = Balls[i].Position.Y + NY; ClosestEntity Closest; Closest.Magnitude = 10000; // look for collisions for(int j = 0; j < (int)Bricks.size(); j++) { // only check items that haven't been hit in the most recent update if (!Bricks[j].HasBeenHit()) { Intersection Point = Bricks[j].PathIntersect(CurrentPath); if (Point.Type == Intersecting) { // mark this hit so we don't check for it again... // until the next update frame. Bricks[i].Hit = true; // see how far the collision is float Magnitude = sqrt(pow(Point.X - Balls[i].Position.X, 2) + pow(Point.Y - Balls[i].Position.Y, 2)); if (Magnitude < Closest.Magnitude) { // nab the closest collision so we can handle multiple collisions Closest.Magnitude = Magnitude; Closest.EntityIndex = j; Closest.CollisionPoint = Point; } } } } if (Closest.CollisionPoint.Type == Intersecting) { if(Bricks[Closest.EntityIndex].Harm(Balls[i].CollisionDamage)) { // TODO: play a sound // Update the ball to the point of collision Balls[i].Position.X = Closest.CollisionPoint.X; Balls[i].Position.Y = Closest.CollisionPoint.Y; // Reflect the ball in the appropriate direction switch(Closest.CollisionPoint.From) { default: case Top: case Bottom: Balls[i].ReflectY(); break; case Left: case Right: Balls[i].ReflectX(); break; } /* Find the fraction of DeltaT that had to occur before this collision float UnknownT = TimerStep * (Closest.Magnitude / sqrt(pow(NX,2) + pow(NY, 2))); // simlulate the ball movement after the collision Balls[i].GetPath(TimerStep - UnknownT); break;*/ } if(NewPositionX > 0.0f && NewPositionX < DisplayWidth - Balls[i].Width && NewPositionY > 0.0f && NewPositionY < DisplayHeight - Balls[i].Height) { Balls[i].Live = true; Balls[i].Position.X = NewPositionX; Balls[i].Position.Y = NewPositionY; } else { Balls[i].Live = false; } } // make sure at least one ball is in play if(Balls[0].BallCount < 1) { game_over = true; } } } else { // end game animation logic } // trigger a render every tick redraw = true; } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { break; } else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { if(!game_over) { // update each paddle for(int i = 0; i < Paddles.size(); i++) { // horizontal clip if(Paddles[i].IsHorizontal()) { if(ev.mouse.x < (Paddles[i].Width / 2) ) { Paddles[i].Position.X = 0; } else if(ev.mouse.x > DisplayWidth - (Paddles[i].Width / 2) ) { Paddles[i].Position.X = DisplayWidth - Paddles[i].Width; } else { Paddles[i].Position.X = ev.mouse.x - (Paddles[i].Width / 2); } } else { // vertical clip if(ev.mouse.y < (Paddles[i].Height / 2) ) { Paddles[i].Position.Y = 0; } else if(ev.mouse.y > DisplayHeight - (Paddles[i].Height / 2) ) { Paddles[i].Position.Y = DisplayHeight - Paddles[i].Height; } else { Paddles[i].Position.Y = ev.mouse.y - (Paddles[i].Height / 2); } } } } else { // track mouse movement for retry menu logic } } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { if(game_over) { // track mouse clicks for retry menu logic } else { // Debug // add a ball at the current mouse position } } else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { // set keys we are interested in if pressed switch(ev.keyboard.keycode) { case ALLEGRO_KEY_ESCAPE: key[KEY_ESC] = true; break; case ALLEGRO_KEY_SPACE: key[KEY_SPACE] = true; break; } } else if(ev.type == ALLEGRO_EVENT_KEY_UP) { // release keys we are interested in if let go switch(ev.keyboard.keycode) { case ALLEGRO_KEY_ESCAPE: key[KEY_ESC] = false; break; case ALLEGRO_KEY_SPACE: key[KEY_SPACE] = false; break; } } if(redraw && al_is_event_queue_empty(EventQueue)) { //The render loop redraw = false; if(!game_over) { // game play // blank al_clear_to_color(al_map_rgb(128,128,128)); // render each brick for(int i = 0; i < Bricks.size(); i++) { Bricks[i].Render(); } // render each ball for(int i = 0; i < Balls.size(); i++) { Balls[i].Render(); } // render each paddle for(int i = 0; i < Paddles.size(); i++) { Paddles[i].Render(); } // render HUD sprintf (scoretxt, "%d", score); sprintf (multitxt, "%d", multi); al_draw_text(Font.Medium, al_map_rgb(0,0,0), 8, 8, ALLEGRO_ALIGN_LEFT, "Score"); al_draw_text(Font.Medium, al_map_rgb(255,255,255), 128, 8, ALLEGRO_ALIGN_LEFT, scoretxt); al_draw_text(Font.Medium, al_map_rgb(0,0,0), 300, 8, ALLEGRO_ALIGN_LEFT, "x"); al_draw_text(Font.Medium, al_map_rgb(255,255,255), 316, 8, ALLEGRO_ALIGN_LEFT, multitxt); al_draw_text(Font.Medium, al_map_rgb(0,0,0), 424, 8, ALLEGRO_ALIGN_LEFT, hightxt); } else { // render retry menu al_clear_to_color(al_map_rgb(128,128,128)); } // always flip Display al_flip_display(); } } } // save high score if the final score is higher if(final_score > high_score) { high_score = final_score; } sprintf (hightxt, "%d", high_score); // write highscore to file UserDataFile = al_fopen("assets/hiscore.txt", "w"); if(UserDataFile) { al_fputs(UserDataFile, hightxt); al_fclose(UserDataFile); } // proper cleanup is important! al_destroy_bitmap(Bitmap.Title); al_destroy_bitmap(Bitmap.Logo); al_destroy_timer(Timer); al_destroy_display(Display); al_destroy_event_queue(EventQueue); }