/* FlappyBird Copyright (C) 2024 Patrick_Pluto This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include bool sdlPipe ( SDL_Rect* pipeRect, SDL_Rect* birdRect, SDL_Renderer* renderer, SDL_Texture* flappyBird, SDL_Texture* pipe ) { // Render the pipes SDL_RenderCopy ( renderer, pipe, nullptr, pipeRect ); // Draw pipes and check for collisions. if ( SDL_HasIntersection ( pipeRect, birdRect ) ) { return true; } pipeRect->y += 1150 ; // move sprite for rendering the bottom pipe SDL_RenderCopyEx ( renderer, pipe, nullptr, pipeRect, 0.0, nullptr, SDL_FLIP_VERTICAL ); pipeRect->x -= 2; if ( SDL_HasIntersection ( pipeRect, birdRect ) ) { return true; } pipeRect->y -= 1150 ; // moving it back if ( pipeRect->x <= -50 ) { std::random_device rd; // Obtain a random number from hardware std::mt19937 eng ( rd() ); // Seed the generator std::uniform_int_distribution<> distr ( -950, -650 ); // Define the range // Generate the random number pipeRect->y = distr ( eng ); pipeRect->x = 800; } return false; } int main ( int argc, char* argv[] ) { // Initialize SDL if ( SDL_Init ( SDL_INIT_VIDEO ) < 0 ) { std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; return 1; } // Create a window SDL_Window* window = SDL_CreateWindow ( "Flappy Bird", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN ); if ( window == nullptr ) { std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; SDL_Quit(); return 1; } // Create a renderer SDL_Renderer* renderer = SDL_CreateRenderer ( window, -1, SDL_RENDERER_ACCELERATED ); if ( renderer == nullptr ) { std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl; SDL_DestroyWindow ( window ); SDL_Quit(); return 1; } // Load the sprite texture SDL_Texture* flappyBird = IMG_LoadTexture ( renderer, "bird.png" ); if ( flappyBird == nullptr ) { std::cerr << "Failed to load texture! SDL_Error: " << SDL_GetError() << std::endl; // Handle error } SDL_Texture* pipe = IMG_LoadTexture ( renderer, "pipe.png" ); if ( pipe == nullptr ) { std::cerr << "Failed to load texture! SDL_Error: " << SDL_GetError() << std::endl; // Handle error } // Sprite position and size SDL_Rect birdRect; birdRect.x = 300; // Initial x position birdRect.y = 200; // Initial y position birdRect.w = 48; // Width of the sprite birdRect.h = 36; // Height of the sprite // Create a random number generator std::random_device rd; // Obtain a random number from hardware std::mt19937 eng ( rd() ); // Seed the generator std::uniform_int_distribution<> distr ( -950, -650 ); // Define the range SDL_Rect pipe1Rect; pipe1Rect.x = 650; pipe1Rect.y = distr ( eng ) ; pipe1Rect.w = 64; pipe1Rect.h = 1024; SDL_Rect pipe2Rect; pipe2Rect.x = 850; pipe2Rect.y = distr ( eng ) ; pipe2Rect.w = 64; pipe2Rect.h = 1024; SDL_Rect pipe3Rect; pipe3Rect.x = 1050; pipe3Rect.y = distr ( eng ) ; pipe3Rect.w = 64; pipe3Rect.h = 1024; SDL_Rect pipe4Rect; pipe4Rect.x = 1250; pipe4Rect.y = distr ( eng ) ; pipe4Rect.w = 64; pipe4Rect.h = 1024; // Sprite Velocity double velocityY = 0; // Main loop flag bool quit = false; SDL_Event e; Uint32 frameStart; int frameTime; const int TARGET_FPS = 60; const int FRAME_DELAY = 1000 / TARGET_FPS; // Delay in milliseconds // Main loop while ( !quit ) { frameStart = SDL_GetTicks(); // Handle events while ( SDL_PollEvent ( &e ) != 0 ) { // User requests quit if ( e.type == SDL_QUIT ) { quit = true; } if ( e.type == SDL_KEYDOWN ) { switch ( e.key.keysym.sym ) { case SDLK_SPACE: // Flap velocityY = -5; break; } } } velocityY += 0.25; birdRect.y += velocityY; // Clear the window with a color (e.g., white) SDL_SetRenderDrawColor ( renderer, 63, 63, 255, 255 ); // White color SDL_RenderClear ( renderer ); // Set the color for the bottom part (green) SDL_SetRenderDrawColor ( renderer, 0, 255, 0, 255 ); // Green color // Define the rectangle for the bottom part of the screen SDL_Rect bottomRect; bottomRect.x = 0; // Start from the left edge bottomRect.y = 550; // Start from the vertical position (adjust as needed) bottomRect.w = 800; // Width of the screen (adjust based on your window size) bottomRect.h = 50; // Height of the green area (adjust as needed) // Render the green rectangle SDL_RenderFillRect ( renderer, &bottomRect ); // Render the sprite SDL_RenderCopy ( renderer, flappyBird, nullptr, &birdRect ); quit = sdlPipe ( &pipe1Rect, &birdRect, renderer, flappyBird, pipe ); if (!quit) { quit = sdlPipe ( &pipe2Rect, &birdRect, renderer, flappyBird, pipe ); } if (!quit) { quit = sdlPipe ( &pipe3Rect, &birdRect, renderer, flappyBird, pipe ); } if (!quit) { quit = sdlPipe ( &pipe4Rect, &birdRect, renderer, flappyBird, pipe ); } // Present the renderer SDL_RenderPresent ( renderer ); frameTime = SDL_GetTicks() - frameStart; if ( frameTime < FRAME_DELAY ) { SDL_Delay ( FRAME_DELAY - frameTime ); } if ( SDL_HasIntersection ( &bottomRect, &birdRect ) ) { quit = true; } } // Clean up SDL_DestroyTexture ( flappyBird ); SDL_DestroyTexture ( pipe ); SDL_DestroyRenderer ( renderer ); SDL_DestroyWindow ( window ); SDL_Quit(); return 0; }