Setting-up.html (8718B)
1 <h1 id="content-title">Setting up</h1> 2 <h1 id="content-url" style='display:none;'>In-Practice/2D-Game/Setting-up</h1> 3 <p> 4 Before we get started with the game mechanics, we first need to set up a simple framework for the game to reside in. The game will use several third party libraries of which most have been introduced in earlier chapters. Wherever a new library is required, it will be properly introduced. 5 </p> 6 7 <p> 8 First, we define a so called <def>uber</def> game class that contains all relevant render and gameplay code. The idea of such a game class is that it (sort of) organizes your game code, while also decoupling all windowing code from the game. This way, you could use the same class in a completely different windowing library (like SDL or SFML for example) without much effort. 9 </p> 10 11 <note> 12 There are thousands of ways of trying to abstract and generalize game/graphics code into classes and objects. What you will see in these chapters is just one (relatively simple) approach to solve this issue. If you feel there is a better approach, try to come up with your own improvement of the implementation. 13 </note> 14 15 <p> 16 The game class hosts an initialization function, an update function, a function to process input, and a render function: 17 </p> 18 19 <pre><code> 20 class Game 21 { 22 public: 23 // game state 24 GameState State; 25 bool Keys[1024]; 26 unsigned int Width, Height; 27 // constructor/destructor 28 Game(unsigned int width, unsigned int height); 29 ~Game(); 30 // initialize game state (load all shaders/textures/levels) 31 void Init(); 32 // game loop 33 void ProcessInput(float dt); 34 void Update(float dt); 35 void Render(); 36 }; 37 </code></pre> 38 39 <p> 40 The class hosts what you may expect from a game class. We initialize the game with a width and height (the resolution you want to play the game in) and use the <fun>Init</fun> function to load shaders, textures, and initialize all gameplay state. We can process input as stored within the <var>Keys</var> array by calling <fun>ProcessInput</fun>, and update all gameplay events (like player/ball movement) in the <fun>Update</fun> function. Last, we can render the game by calling <fun>Render</fun>. Note that we split the movement logic from the render logic. 41 </p> 42 43 <p> 44 The <fun>Game</fun> class also hosts a variable called <var>State</var> which is of type <def>GameState</def> as defined below: 45 </p> 46 47 <pre><code> 48 // Represents the current state of the game 49 enum GameState { 50 GAME_ACTIVE, 51 GAME_MENU, 52 GAME_WIN 53 }; 54 </code></pre> 55 56 <p> 57 This allows us to keep track of what state the game is currently in. This way, we can decide to adjust rendering and/or processing based on the current state of the game (we probably render and process different items when we're in the game's menu for example). 58 </p> 59 60 <p> 61 As of now, the functions of the game class are completely empty since we have yet to write the actual game code, but here are the Game class's <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/progress/2.game.h" target="_blank">header</a> 62 and <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/progress/2.game.cpp" target="_blank">code</a> file. 63 </p> 64 65 <h2>Utility</h2> 66 <p> 67 Since we're creating a large application we'll frequently have to re-use several OpenGL concepts, like textures and shaders. It thus makes sense to create a more easy-to-use interface for these two items as similarly done in one of the earlier chapters where we created a shader class. 68 </p> 69 70 <p> 71 We define a shader class that generates a compiled shader (or generates error messages if it fails) from two or three strings (if a geometry shader is present). The shader class also contains a lot of useful utility functions to quickly set uniform values. We also define a texture class that generates a 2D texture image (based on its properties) from a byte array and a given width and height. Again, the texture class also hosts utility functions. 72 </p> 73 74 <p> 75 We won't delve into the details of the classes since by now you should easily understand how they work. For this reason you can find the header and code files, fully commented, below: 76 </p> 77 78 <ul> 79 <li><strong>Shader</strong>: <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/shader.h" target="_blank">header</a>, <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/shader.cpp" target="_blank">code</a>.</li> 80 <li><strong>Texture</strong>: <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/texture.h" target="_blank">header</a>, <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/texture.cpp" target="_blank">code</a>.</li> 81 </ul> 82 83 <p> 84 Note that the current texture class is solely designed for 2D textures only, but could easily be extended for alternative texture types. 85 </p> 86 87 <h2>Resource management</h2> 88 <p> 89 While the shader and texture classes function great by themselves, they do require either a byte array or a list of strings for initialization. We could easily embed file loading code within the classes themselves, but this slightly violates the <def>single responsibility principle</def>. We'd prefer these classes to only focus on either textures or shaders respectively, and not necessarily their file-loading mechanics. 90 </p> 91 92 <p> 93 For this reason it is often considered a more organized approach to create a single entity designed for loading game-related resources called a <def>resource manager</def>. There are several approaches to creating a resource manager; for this chapter we chose to use a singleton static resource manager that is (due to its static nature) always available throughout the project, hosting all loaded resources and their relevant loading functionality. 94 </p> 95 96 <p> 97 Using a singleton class with static functionality has several advantages and disadvantages, with its disadvantages mostly being the loss of several OOP properties and less control over construction/destruction. However, for relatively small projects like this it is easy to work with. 98 </p> 99 100 <p> 101 Like the other class files, the resource manager is listed below: 102 </p> 103 104 <ul> 105 <li><strong>Resource Manager</strong>: <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/resource_manager.h" target="_blank">header</a>, <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/resource_manager.cpp" target="_blank">code</a>.</li> 106 </ul> 107 108 <p> 109 Using the resource manager, we can easily load shaders into the program like: 110 </p> 111 112 <pre><code> 113 Shader shader = ResourceManager::LoadShader("vertex.vs", "fragment.vs", nullptr, "test"); 114 // then use it 115 shader.Use(); 116 // or 117 ResourceManager::GetShader("test").Use(); 118 </code></pre> 119 120 <p> 121 The defined <fun>Game</fun> class, together with the resource manager and the easily manageable <fun>Shader</fun> and <fun>Texture2D</fun> classes, form the basis for the next chapters as we'll be extensively using these classes to implement the Breakout game. 122 </p> 123 124 <h2>Program</h2> 125 <p> 126 We still need a window for the game and set some initial OpenGL state as we make use of OpenGL's <a href="https://learnopengl.com/Advanced-OpenGL/Blending" target="_blank">blending</a> functionality. We do not enable depth testing, since the game is entirely in 2D. All vertices are defined with the same z-values so enabling depth testing would be of no use and likely cause z-fighting. 127 </p> 128 129 <p> 130 The startup code of the Breakout game is relatively simple: we create a window with GLFW, register a few callback functions, create the <fun>Game</fun> object, and propagate all relevant functionality to the game class. The code is given below: 131 </p> 132 133 <ul> 134 <li><strong>Program</strong>: <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/progress/2.program.cpp" target="_blank">code</a>.</li> 135 </ul> 136 137 <p> 138 Running the code should give you the following output: 139 </p> 140 141 <img src="/img/in-practice/breakout/setting-up.png" class="clean" alt="Blank image of start of Breakout game in OpenGL"/> 142 143 <p> 144 By now we have a solid framework for the upcoming chapters; we'll be continuously extending the game class to host new functionality. Hop over to the <a href="https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites" target="_blank">next</a> chapter once you're ready. 145 </p> 146 147 </div> 148 149 <div id="hover"> 150 HI 151 </div> 152 <!-- 728x90/320x50 sticky footer --> 153 <div id="waldo-tag-6196"></div> 154 155 <div id="disqus_thread"></div> 156 157 158 159 160 </div> <!-- container div --> 161 162 163 </div> <!-- super container div --> 164 </body> 165 </html>