| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- // ----------------------------------------------------------------
- // From Game Programming in C++ by Sanjay Madhav
- // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
- //
- // Released under the BSD License
- // See LICENSE in root directory for full details.
- // ----------------------------------------------------------------
- #include "Game.h"
- const int thickness = 15;
- const float paddleH = 100.0f;
- Game::Game()
- :mWindow(nullptr)
- ,mRenderer(nullptr)
- ,mTicksCount(0)
- ,mIsRunning(true)
- ,mPaddleDir(0)
- {
-
- }
- bool Game::Initialize()
- {
- // Initialize SDL
- int sdlResult = SDL_Init(SDL_INIT_VIDEO);
- if (sdlResult != 0)
- {
- SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
- return false;
- }
-
- // Create an SDL Window
- mWindow = SDL_CreateWindow(
- "Game Programming in C++ (Chapter 1)", // Window title
- 100, // Top left x-coordinate of window
- 100, // Top left y-coordinate of window
- 1024, // Width of window
- 768, // Height of window
- 0 // Flags (0 for no flags set)
- );
- if (!mWindow)
- {
- SDL_Log("Failed to create window: %s", SDL_GetError());
- return false;
- }
-
- //// Create SDL renderer
- mRenderer = SDL_CreateRenderer(
- mWindow, // Window to create renderer for
- -1, // Usually -1
- SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
- );
- if (!mRenderer)
- {
- SDL_Log("Failed to create renderer: %s", SDL_GetError());
- return false;
- }
- //
- mPaddlePos.x = 10.0f;
- mPaddlePos.y = 768.0f/2.0f;
- mBallPos.x = 1024.0f/2.0f;
- mBallPos.y = 768.0f/2.0f;
- mBallVel.x = -200.0f;
- mBallVel.y = 235.0f;
- return true;
- }
- void Game::RunLoop()
- {
- while (mIsRunning)
- {
- ProcessInput();
- UpdateGame();
- GenerateOutput();
- }
- }
- void Game::ProcessInput()
- {
- SDL_Event event;
- while (SDL_PollEvent(&event))
- {
- switch (event.type)
- {
- // If we get an SDL_QUIT event, end loop
- case SDL_QUIT:
- mIsRunning = false;
- break;
- }
- }
-
- // Get state of keyboard
- const Uint8* state = SDL_GetKeyboardState(NULL);
- // If escape is pressed, also end loop
- if (state[SDL_SCANCODE_ESCAPE])
- {
- mIsRunning = false;
- }
-
- // Update paddle direction based on W/S keys
- mPaddleDir = 0;
- if (state[SDL_SCANCODE_W])
- {
- mPaddleDir -= 1;
- }
- if (state[SDL_SCANCODE_S])
- {
- mPaddleDir += 1;
- }
- }
- void Game::UpdateGame()
- {
- // Wait until 16ms has elapsed since last frame
- while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16))
- ;
- // Delta time is the difference in ticks from last frame
- // (converted to seconds)
- float deltaTime = (SDL_GetTicks() - mTicksCount) / 1000.0f;
-
- // Clamp maximum delta time value
- if (deltaTime > 0.05f)
- {
- deltaTime = 0.05f;
- }
- // Update tick counts (for next frame)
- mTicksCount = SDL_GetTicks();
-
- // Update paddle position based on direction
- if (mPaddleDir != 0)
- {
- mPaddlePos.y += mPaddleDir * 300.0f * deltaTime;
- // Make sure paddle doesn't move off screen!
- if (mPaddlePos.y < (paddleH/2.0f + thickness))
- {
- mPaddlePos.y = paddleH/2.0f + thickness;
- }
- else if (mPaddlePos.y > (768.0f - paddleH/2.0f - thickness))
- {
- mPaddlePos.y = 768.0f - paddleH/2.0f - thickness;
- }
- }
-
- // Update ball position based on ball velocity
- mBallPos.x += mBallVel.x * deltaTime;
- mBallPos.y += mBallVel.y * deltaTime;
-
- // Bounce if needed
- // Did we intersect with the paddle?
- float diff = mPaddlePos.y - mBallPos.y;
- // Take absolute value of difference
- diff = (diff > 0.0f) ? diff : -diff;
- if (
- // Our y-difference is small enough
- diff <= paddleH / 2.0f &&
- // We are in the correct x-position
- mBallPos.x <= 25.0f && mBallPos.x >= 20.0f &&
- // The ball is moving to the left
- mBallVel.x < 0.0f)
- {
- mBallVel.x *= -1.0f;
- }
- // Did the ball go off the screen? (if so, end game)
- else if (mBallPos.x <= 0.0f)
- {
- mIsRunning = false;
- }
- // Did the ball collide with the right wall?
- else if (mBallPos.x >= (1024.0f - thickness) && mBallVel.x > 0.0f)
- {
- mBallVel.x *= -1.0f;
- }
-
- // Did the ball collide with the top wall?
- if (mBallPos.y <= thickness && mBallVel.y < 0.0f)
- {
- mBallVel.y *= -1;
- }
- // Did the ball collide with the bottom wall?
- else if (mBallPos.y >= (768 - thickness) &&
- mBallVel.y > 0.0f)
- {
- mBallVel.y *= -1;
- }
- }
- void Game::GenerateOutput()
- {
- // Set draw color to blue
- SDL_SetRenderDrawColor(
- mRenderer,
- 0, // R
- 0, // G
- 255, // B
- 255 // A
- );
-
- // Clear back buffer
- SDL_RenderClear(mRenderer);
- // Draw walls
- SDL_SetRenderDrawColor(mRenderer, 255, 255, 255, 255);
-
- // Draw top wall
- SDL_Rect wall{
- 0, // Top left x
- 0, // Top left y
- 1024, // Width
- thickness // Height
- };
- SDL_RenderFillRect(mRenderer, &wall);
-
- // Draw bottom wall
- wall.y = 768 - thickness;
- SDL_RenderFillRect(mRenderer, &wall);
-
- // Draw right wall
- wall.x = 1024 - thickness;
- wall.y = 0;
- wall.w = thickness;
- wall.h = 1024;
- SDL_RenderFillRect(mRenderer, &wall);
-
- // Draw paddle
- SDL_Rect paddle{
- static_cast<int>(mPaddlePos.x),
- static_cast<int>(mPaddlePos.y - paddleH/2),
- thickness,
- static_cast<int>(paddleH)
- };
- SDL_RenderFillRect(mRenderer, &paddle);
-
- // Draw ball
- SDL_Rect ball{
- static_cast<int>(mBallPos.x - thickness/2),
- static_cast<int>(mBallPos.y - thickness/2),
- thickness,
- thickness
- };
- SDL_RenderFillRect(mRenderer, &ball);
-
- // Swap front buffer and back buffer
- SDL_RenderPresent(mRenderer);
- }
- void Game::Shutdown()
- {
- SDL_DestroyRenderer(mRenderer);
- SDL_DestroyWindow(mWindow);
- SDL_Quit();
- }
|