Now that we’ve made this much progress, it might be time to consider re-working the code to actually do something, this might actually be something that is better left to another github repo so we can keep using this one as a testing ground for ideas.
I think what we’ll do now is take what we’ve learned messing with physics and try to make a game, a Pong clone seems like the obvious choice to get started considering the subject matter thus far, there will be problems to overcome, but I think we’re well equipped to sort them out!
The new repo is https://github.com/Atrixium/pong and we’ll set up our initial commit now.
The first thing we need to do is include SDL, SDL_image and SDL_ttf and get a window open and ready, that means we need to:
- Modify the build options to link to SDL2, SDL2_image and SDL2_ttf
- Initialize SDL video and audio subsystems
- Create a Window
- Create a Renderer
[pastacode lang=”cpp” manual=”%23include%20%3Ciostream%3E%0A%23include%20%3CSDL2%2FSDL.h%3E%0A%23include%20%3CSDL2%2FSDL_image.h%3E%0A%23include%20%3CSDL2%2FSDL_ttf.h%3E%0A%0A%0Aint%20main(int%20argc%2C%20char%20*argv%5B%5D)%0A%7B%0A%20%20%20%20if(%20SDL_Init(SDL_INIT_VIDEO%20%7C%20SDL_INIT_AUDIO)%20!%3D0%20)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22SDL%20Init%20Failed!%20%22%20%3C%3C%20SDL_GetError()%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(%20IMG_Init(IMG_INIT_PNG)%20!%3D%20IMG_INIT_PNG%20)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22SDL_Image%20Init%20Failed!%20%22%20%3C%3C%20IMG_GetError()%20%3C%3Cstd%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20SDL_Quit()%3B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(%20TTF_Init()%20!%3D%200%20)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22SDL_TTF%20Init%20Failed!%20%22%20%3C%3C%20TTF_GetError()%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20IMG_Quit()%3B%0A%20%20%20%20%20%20%20%20SDL_Quit()%3B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20SDL_Window*%20window%20%3D%20SDL_CreateWindow(%22Pong%22%2C%20SDL_WINDOWPOS_CENTERED%2C%20SDL_WINDOWPOS_CENTERED%2C%20640%2C%20480%2C%200)%3B%0A%20%20%20%20if%20(!window)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22SDL%20Window%20Creation%20Failed!%20%22%20%3C%3C%20SDL_GetError()%20%3C%3C%20std%3A%3A%20endl%3B%0A%20%20%20%20%20%20%20%20TTF_Quit()%3B%0A%20%20%20%20%20%20%20%20IMG_Quit()%3B%0A%20%20%20%20%20%20%20%20SDL_Quit()%3B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%0A%20%20%20%20SDL_Renderer*%20renderer%20%3D%20SDL_CreateRenderer(window%2C%20-1%2C%20SDL_RENDERER_PRESENTVSYNC)%3B%0A%20%20%20%20if(!renderer)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22SDL%20Renderer%20Creation%20Failed!%20%22%20%3C%3C%20SDL_GetError()%20%3C%3C%20std%3A%3A%20endl%3B%0A%20%20%20%20%20%20%20%20TTF_Quit()%3B%0A%20%20%20%20%20%20%20%20IMG_Quit()%3B%0A%20%20%20%20%20%20%20%20SDL_DestroyWindow(window)%3B%0A%20%20%20%20%20%20%20%20SDL_Quit()%3B%0A%20%20%20%20%20%20%20%20return%201%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20SDL_RenderClear(renderer)%3B%0A%20%20%20%20SDL_RenderPresent(renderer)%3B%0A%0A%20%20%20%20SDL_Delay(2000)%3B%0A%0A%0A%20%20%20%20%2F%2FCleanup%0A%20%20%20%20SDL_DestroyRenderer(renderer)%3B%0A%20%20%20%20SDL_DestroyWindow(window)%3B%0A%20%20%20%20IMG_Quit()%3B%0A%20%20%20%20TTF_Quit()%3B%0A%20%20%20%20SDL_Quit()%3B%0A%7D%0A” message=”” highlight=”” provider=”manual”/]
With this start code, we now have a cleared black window on the screen and we can setup the event handler and the render loop:
[pastacode lang=”cpp” manual=”%2F%2Fstart%20render%20loop%0A%0A%20%20%20%20bool%20quit%20%3D%20false%3B%0A%0A%20%20%20%20while(!quit)%0A%20%20%20%20%7B%0A%0A%20%20%20%20%20%20%20%20%2F%2Fstart%20event%20handler%0A%0A%20%20%20%20%20%20%20%20SDL_Event%20event%3B%0A%0A%20%20%20%20%20%20%20%20while(%20SDL_PollEvent(%26event)%20)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20switch(event.type)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20SDL_QUIT%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20quit%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%20SDL_KEYDOWN%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch(event.key.keysym.sym)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_q%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20quit%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%0A%20%20%20%20%20%20%20%20SDL_RenderClear(renderer)%3B%0A%20%20%20%20%20%20%20%20SDL_RenderPresent(renderer)%3B%0A%0A%20%20%20%20%7D%2F%2F%20end%20main” message=”” highlight=”” provider=”manual”/]
Now clicking the x or pressing ‘q’ will close the window.
Next up we should work on a state machine that will track our games current state, allowing us to perform different actions in different modes such as going from a menu state to a playing state. We’ll implement this with a simple enum and a switch statement:
[pastacode lang=”cpp” manual=”%20%20%20%20%2F%2Fstart%20render%20loop%0A%0A%20%20%20%20while(gameState%20!%3D%20STATE_QUIT)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%2F%2Fstart%20event%20handler%0A%0A%20%20%20%20%20%20%20%20SDL_Event%20event%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2Freact%20to%20input%20based%20on%20game%20state%0A%20%20%20%20%20%20%20%20switch(gameState)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20case%20STATE_MENU%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Entered%20menu%20state%22%20%3C%3C%20std%3A%3Aendl%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20while(%20SDL_PollEvent(%26event)%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch(event.type)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDL_QUIT%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_QUIT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDL_KEYDOWN%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch(event.key.keysym.sym)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_q%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_QUIT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_1%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_MENU%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Changed%20to%20menu%20state%22%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_2%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_PLAYING%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Changed%20to%20playing%20state%22%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20case%20STATE_PLAYING%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Entered%20playing%20state%22%20%3C%3C%20std%3A%3Aendl%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20while(%20SDL_PollEvent(%26event)%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch(event.type)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDL_QUIT%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_QUIT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDL_KEYDOWN%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch(event.key.keysym.sym)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_q%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_QUIT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_1%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_MENU%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Changed%20to%20menu%20state%22%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20SDLK_2%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gameState%20%3D%20STATE_PLAYING%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Changed%20to%20playing%20state%22%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%0A%20%20%20%20%20%20%20%20SDL_RenderClear(renderer)%3B%0A%20%20%20%20%20%20%20%20SDL_RenderPresent(renderer)%3B%0A%0A%20%20%20%20%7D” message=”” highlight=”” provider=”manual”/]
This simply switch and enum combination allows us to perform different actions with the same inputs depending on the game state, currently it only displays what state it’s in and checks for a few keys to be pressed, but this demonstrates how we will be able to use this to implement the different logic required for a menu system and for the actual game itself.
We’ll leave this here for now, it’s a good start and gives us a good starting ground for implementing the first version of our Pong clone.