LearnOpenGL

Translation in progress of learnopengl.com.
git clone https://git.mtkn.jp/LearnOpenGL
Log | Files | Refs

Powerups.html (29712B)


      1 <!DOCTYPE html>
      2 <html lang="ja"> 
      3 <head>
      4     <meta charset="utf-8"/>
      5     <title>LearnOpenGL</title>
      6     <link rel="shortcut icon" type="image/ico" href="/favicon.ico"  />
      7 	<link rel="stylesheet" href="../static/style.css" />
      8 	<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script>
      9 	<script src="/static/functions.js"></script>
     10 </head>
     11 <body>
     12 	<nav>
     13 <ol>
     14 	<li id="Introduction">
     15 		<a href="https://learnopengl.com/Introduction">はじめに</a>
     16 	</li>
     17 	<li id="Getting-started">
     18 		<span class="closed">入門</span>
     19 		<ol>
     20 			<li id="Getting-started/OpenGL">
     21 				<a href="https://learnopengl.com/Getting-started/OpenGL">OpenGL </a>
     22 			</li>
     23 			<li id="Getting-started/Creating-a-window">
     24 				<a href="https://learnopengl.com/Getting-started/Creating-a-window">ウィンドウの作成</a>
     25 			</li>
     26 			<li id="Getting-started/Hello-Window">
     27 				<a href="https://learnopengl.com/Getting-started/Hello-Window">最初のウィンドウ</a>
     28 			</li>
     29 			<li id="Getting-started/Hello-Triangle">
     30 				<a href="https://learnopengl.com/Getting-started/Hello-Triangle">最初の三角形</a>
     31 			</li>
     32 			<li id="Getting-started/Shaders">
     33 				<a href="https://learnopengl.com/Getting-started/Shaders">シェーダー</a>
     34 			</li>
     35 			<li id="Getting-started/Textures">
     36 				<a href="https://learnopengl.com/Getting-started/Textures">テクスチャ</a>
     37 			</li>
     38 			<li id="Getting-started/Transformations">
     39 				<a href="https://learnopengl.com/Getting-started/Transformations">座標変換</a>
     40 			</li>
     41 			<li id="Getting-started/Coordinate-Systems">
     42 				<a href="https://learnopengl.com/Getting-started/Coordinate-Systems">座標系</a>
     43 			</li>
     44 			<li id="Getting-started/Camera">
     45 				<a href="https://learnopengl.com/Getting-started/Camera">カメラ</a>
     46 			</li>
     47 			<li id="Getting-started/Review">
     48 				<a href="https://learnopengl.com/Getting-started/Review">まとめ</a>
     49 			</li>
     50 		</ol>
     51 	</li>
     52 	<li id="Lighting">
     53 		<span class="closed">Lighting </span>
     54 		<ol>
     55 			<li id="Lighting/Colors">
     56 				<a href="https://learnopengl.com/Lighting/Colors">Colors </a>
     57 			</li>
     58 			<li id="Lighting/Basic-Lighting">
     59 				<a href="https://learnopengl.com/Lighting/Basic-Lighting">Basic Lighting </a>
     60 			</li>
     61 			<li id="Lighting/Materials">
     62 				<a href="https://learnopengl.com/Lighting/Materials">Materials </a>
     63 			</li>
     64 			<li id="Lighting/Lighting-maps">
     65 				<a href="https://learnopengl.com/Lighting/Lighting-maps">Lighting maps </a>
     66 			</li>
     67 			<li id="Lighting/Light-casters">
     68 				<a href="https://learnopengl.com/Lighting/Light-casters">Light casters </a>
     69 			</li>
     70 			<li id="Lighting/Multiple-lights">
     71 				<a href="https://learnopengl.com/Lighting/Multiple-lights">Multiple lights </a>
     72 			</li>
     73 			<li id="Lighting/Review">
     74 				<a href="https://learnopengl.com/Lighting/Review">Review </a>
     75 			</li>
     76 		</ol>
     77 	</li>
     78 	<li id="Model-Loading">
     79 		<span class="closed">Model Loading </span>
     80 		<ol>
     81 			<li id="Model-Loading/Assimp">
     82 				<a href="https://learnopengl.com/Model-Loading/Assimp">Assimp </a>
     83 			</li>
     84 			<li id="Model-Loading/Mesh">
     85 				<a href="https://learnopengl.com/Model-Loading/Mesh">Mesh </a>
     86 			</li>
     87 			<li id="Model-Loading/Model">
     88 				<a href="https://learnopengl.com/Model-Loading/Model">Model </a>
     89 			</li>
     90 		</ol>
     91 	</li>
     92 	<li id="Advanced-OpenGL">
     93 		<span class="closed">Advanced OpenGL </span>
     94 		<ol>
     95 			<li id="Advanced-OpenGL/Depth-testing">
     96 				<a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing">Depth testing </a>
     97 			</li>
     98 			<li id="Advanced-OpenGL/Stencil-testing">
     99 				<a href="https://learnopengl.com/Advanced-OpenGL/Stencil-testing">Stencil testing </a>
    100 			</li>
    101 			<li id="Advanced-OpenGL/Blending">
    102 				<a href="https://learnopengl.com/Advanced-OpenGL/Blending">Blending </a>
    103 			</li>
    104 			<li id="Advanced-OpenGL/Face-culling">
    105 				<a href="https://learnopengl.cm/Advanced-OpenGL/Face-culling">Face culling </a>
    106 			</li>
    107 			<li id="Advanced-OpenGL/Framebuffers">
    108 				<a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers">Framebuffers </a>
    109 			</li>
    110 			<li id="Advanced-OpenGL/Cubemaps">
    111 				<a href="https://learnopengl.com/Advanced-OpenGL/Cubemaps">Cubemaps </a>
    112 			</li>
    113 			<li id="Advanced-OpenGL/Advanced-Data">
    114 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-Data">Advanced Data </a>
    115 			</li>
    116 			<li id="Advanced-OpenGL/Advanced-GLSL">
    117 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL">Advanced GLSL </a>
    118 			</li>
    119 			<li id="Advanced-OpenGL/Geometry-Shader">
    120 				<a href="https://learnopengl.com/Advanced-OpenGL/Geometry-Shader">Geometry Shader </a>
    121 			</li>
    122 			<li id="Advanced-OpenGL/Instancing">
    123 				<a href="https://learnopengl.com/Advanced-OpenGL/Instancing">Instancing </a>
    124 			</li>
    125 			<li id="Advanced-OpenGL/Anti-Aliasing">
    126 				<a href="https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing">Anti Aliasing </a>
    127 			</li>
    128 		</ol>
    129 	</li>
    130 	<li id="Advanced-Lighting">
    131 		<span class="closed">Advanced Lighting </span>
    132 		<ol>
    133 			<li id="Advanced-Lighting/Advanced-Lighting">
    134 				<a href="https://learnopengl.com/Advanced-Lighting/Advanced-Lighting">Advanced Lighting </a>
    135 			</li>
    136 			<li id="Advanced-Lighting/Gamma-Correction">
    137 				<a href="https://learnopengl.com/Advanced-Lighting/Gamma-Correction">Gamma Correction </a>
    138 			</li>
    139 			<li id="Advanced-Lighting/Shadows">
    140 				<span class="closed">Shadows </span>
    141 				<ol>
    142 					<li id="Advanced-Lighting/Shadows/Shadow-Mapping">
    143 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping">Shadow Mapping </a>
    144 					</li>
    145 					<li id="Advanced-Lighting/Shadows/Point-Shadows">
    146 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows">Point Shadows </a>
    147 					</li>
    148 				</ol>
    149 			</li>
    150 			<li id="Advanced-Lighting/Normal-Mapping">
    151 				<a href="https://learnopengl.com/Advanced-Lighting/Normal-Mapping">Normal Mapping </a>
    152 			</li>
    153 			<li id="Advanced-Lighting/Parallax-Mapping">
    154 				<a href="https://learnopengl.com/Advanced-Lighting/Parallax-Mapping">Parallax Mapping </a>
    155 			</li>
    156 			<li id="Advanced-Lighting/HDR">
    157 				<a href="https://learnopengl.com/Advanced-Lighting/HDR">HDR </a>
    158 			</li>
    159 			<li id="Advanced-Lighting/Bloom">
    160 				<a href="https://learnopengl.com/Advanced-Lighting/Bloom">Bloom </a>
    161 			</li>
    162 			<li id="Advanced-Lighting/Deferred-Shading">
    163 				<a href="https://learnopengl.com/Advanced-Lighting/Deferred-Shading">Deferred Shading </a>
    164 			</li>
    165 			<li id="Advanced-Lighting/SSAO">
    166 				<a href="https://learnopengl.com/Advanced-Lighting/SSAO">SSAO </a>
    167 			</li>
    168 		</ol>
    169 	</li>
    170 	<li id="PBR">
    171 		<span class="closed">PBR </span>
    172 		<ol>
    173 			<li id="PBR/Theory">
    174 				<a href="https://learnopengl.com/PBR/Theory">Theory </a>
    175 			</li>
    176 			<li id="PBR/Lighting">
    177 				<a href="https://learnopengl.com/PBR/Lighting">Lighting </a>
    178 			</li>
    179 			<li id="PBR/IBL">
    180 				<span class="closed">IBL </span>
    181 				<ol>
    182 					<li id="PBR/IBL/Diffuse-irradiance">
    183 						<a href="https://learnopengl.com/PBR/IBL/Diffuse-irradiance">Diffuse irradiance </a>
    184 					</li>
    185 					<li id="PBR/IBL/Specular-IBL">
    186 						<a href="https://learnopengl.com/PBR/IBL/Specular-IBL">Specular IBL </a>
    187 					</li>
    188 				</ol>
    189 			</li>
    190 		</ol>
    191 	</li>
    192 	<li id="In-Practice">
    193 		<span class="closed">In Practice </span>
    194 		<ol>
    195 			<li id="In-Practice/Debugging">
    196 				<a href="https://learnopengl.com/In-Practice/Debugging">Debugging </a>
    197 			</li>
    198 			<li id="In-Practice/Text-Rendering">
    199 				<a href="https://learnopengl.com/In-Practice/Text-Rendering">Text Rendering </a>
    200 			</li>
    201 			<li id="In-Practice/2D-Game">
    202 				<span class="closed">2D Game </span>
    203 				<ol>
    204 					<li id="In-Practice/2D-Game/Breakout">
    205 						<a href="https://learnopengl.com/In-Practice/2D-Game/Breakout">Breakout </a>
    206 					</li>
    207 					<li id="In-Practice/2D-Game/Setting-up">
    208 						<a href="https://learnopengl.com/In-Practice/2D-Game/Setting-up">Setting up </a>
    209 					</li>
    210 					<li id="In-Practice/2D-Game/Rendering-Sprites">
    211 						<a href="https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites">Rendering Sprites </a>
    212 					</li>
    213 					<li id="In-Practice/2D-Game/Levels">
    214 						<a href="https://learnopengl.com/In-Practice/2D-Game/Levels">Levels </a>
    215 					</li>
    216 					<li id="In-Practice/2D-Game/Collisions">
    217 						<span class="closed">Collisions </span>
    218 						<ol>
    219 							<li id="In-Practice/2D-Game/Collisions/Ball">
    220 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Ball">Ball </a>
    221 							</li>
    222 							<li id="In-Practice/2D-Game/Collisions/Collision-detection">
    223 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-detection">Collision detection </a>
    224 							</li>
    225 							<li id="In-Practice/2D-Game/Collisions/Collision-resolution">
    226 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-resolution">Collision resolution </a>
    227 							</li>
    228 						</ol>
    229 					</li>
    230 					<li id="In-Practice/2D-Game/Particles">
    231 						<a href="https://learnopengl.com/In-Practice/2D-Game/Particles">Particles </a>
    232 					</li>
    233 					<li id="In-Practice/2D-Game/Postprocessing">
    234 						<a href="https://learnopengl.com/In-Practice/2D-Game/Postprocessing">Postprocessing </a>
    235 					</li>
    236 					<li id="In-Practice/2D-Game/Powerups">
    237 						<a href="https://learnopengl.com/In-Practice/2D-Game/Powerups">Powerups </a>
    238 					</li>
    239 					<li id="In-Practice/2D-Game/Audio">
    240 						<a href="https://learnopengl.com/In-Practice/2D-Game/Audio">Audio </a>
    241 					</li>
    242 					<li id="In-Practice/2D-Game/Render-text">
    243 						<a href="https://learnopengl.com/In-Practice/2D-Game/Render-text">Render text </a>
    244 					</li>
    245 					<li id="In-Practice/2D-Game/Final-thoughts">
    246 						<a href="https://learnopengl.com/In-Practice/2D-Game/Final-thoughts">Final thoughts </a>
    247 					</li>
    248 				</ol>
    249 			</li>
    250 		</ol>
    251 	</li>
    252 	<li id="Guest-Articles">
    253 		<span class="closed">Guest Articles </span>
    254 		<ol>
    255 			<li id="Guest-Articles/How-to-publish">
    256 				<a href="https://learnopengl.com/Guest-Articles/How-to-publish">How to publish </a>
    257 			</li>
    258 			<li id="Guest-Articles/2020">
    259 				<span class="closed">2020 </span>
    260 				<ol>
    261 					<li id="Guest-Articles/2020/OIT">
    262 						<span class="closed">OIT </span>
    263 						<ol>
    264 							<li id="Guest-Articles/2020/OIT/Introduction">
    265 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Introduction">Introduction </a>
    266 							</li>
    267 							<li id="Guest-Articles/2020/OIT/Weighted-Blended">
    268 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Weighted-Blended">Weighted Blended </a>
    269 							</li>
    270 						</ol>
    271 					</li>
    272 					<li id="Guest-Articles/2020/Skeletal-Animation">
    273 						<a href="https://learnopengl.com/Guest-Articles/2020/Skeletal-Animation">Skeletal Animation </a>
    274 					</li>
    275 				</ol>
    276 			</li>
    277 			<li id="Guest-Articles/2021">
    278 				<span class="closed">2021 </span>
    279 				<ol>
    280 					<li id="Guest-Articles/2021/CSM">
    281 						<a href="https://learnopengl.com/Guest-Articles/2021/CSM">CSM </a>
    282 					</li>
    283 					<li id="Guest-Articles/2021/Scene">
    284 						<span class="closed">Scene </span>
    285 						<ol>
    286 							<li id="Guest-Articles/2021/Scene/Scene-Graph">
    287 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Scene-Graph">Scene Graph </a>
    288 							</li>
    289 							<li id="Guest-Articles/2021/Scene/Frustum-Culling">
    290 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling">Frustum Culling </a>
    291 							</li>
    292 						</ol>
    293 					</li>
    294 					<li id="Guest-Articles/2021/Tessellation">
    295 						<span class="closed">Tessellation </span>
    296 						<ol>
    297 							<li id="Guest-Articles/2021/Tessellation/Height-map">
    298 								<a href="https://learnopengl.com/Guest-Articles/2021/Tessellation/Height-map">Height map </a>
    299 							</li>
    300 						</ol>
    301 					</li>
    302 				</ol>
    303 			</li>
    304 		</ol>
    305 	</li>
    306 	<li id="Code-repository">
    307 		<a href="https://learnopengl.com/Code-repository">Code repository </a>
    308 	</li>
    309 	<li id="Translations">
    310 		<a href="https://learnopengl.com/Translations">Translations </a>
    311 	</li>
    312 	<li id="About">
    313 		<a href="https://learnopengl.com/About">About </a>
    314 	</li>
    315 </ol>
    316 	</nav>
    317 	<main>
    318     <h1 id="content-title">Powerups</h1>
    319 <h1 id="content-url" style='display:none;'>In-Practice/2D-Game/Powerups</h1>
    320 <p>
    321   Breakout is close to finished, but it would be cool to add at least one more gameplay mechanic so it's not your average standard Breakout clone; what about powerups?
    322 </p>
    323 
    324 <p>
    325   The idea is that whenever a brick is destroyed, the brick has a small chance of spawning a powerup block. Such a block will slowly fall downwards and if it collides with the player paddle, an interesting effect occurs based on the type of powerup. For example, one powerup makes the paddle larger, and another powerup allows the ball to pass through objects. We also include several negative powerups that affect the player in a negative way.
    326 </p>
    327 
    328 <p>
    329   We can model a powerup as a <fun>GameObject</fun> with a few extra properties. That's why we define a class <fun>PowerUp</fun> that inherits from <fun>GameObject</fun>:
    330 </p>
    331 
    332 <pre><code>
    333 const glm::vec2 SIZE(60.0f, 20.0f);
    334 const glm::vec2 VELOCITY(0.0f, 150.0f);
    335 
    336 class PowerUp : public GameObject 
    337 {
    338 public:
    339     // powerup state
    340     std::string Type;
    341     float       Duration;	
    342     bool        Activated;
    343     // constructor
    344     PowerUp(std::string type, glm::vec3 color, float duration, 
    345             glm::vec2 position, Texture2D texture) 
    346         : GameObject(position, SIZE, texture, color, VELOCITY), 
    347           Type(type), Duration(duration), Activated() 
    348     { }
    349 };  
    350 </code></pre>
    351 
    352 <p>
    353   A <fun>PowerUp</fun> is just a <fun>GameObject</fun> with extra state, so we can simply define it in a single header file which you can find <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/power_up.h" target="_blank">here</a>.
    354 </p>
    355 
    356 <p>
    357   Each powerup defines its type as a string, a duration for how long it is active, and whether it is currently activated. Within Breakout we're going to feature a total of 4 positive powerups and 2 negative powerups:
    358 </p>
    359 
    360 <img src="/img/in-practice/breakout/powerups.png" class="clean" alt="PowerUps used in OpenGL Breakoout"/>
    361   
    362 <ul>
    363   <li><strong>Speed</strong>: increases the velocity of the ball by 20%. </li> 
    364   <li><strong>Sticky</strong>: when the ball collides with the paddle, the ball remains stuck to the paddle unless the spacebar is pressed again. This allows the player to better position the ball before releasing it. </li> 
    365   <li><strong>Pass-Through</strong>: collision resolution is disabled for non-solid blocks, allowing the ball to pass through multiple blocks.</li> 
    366   <li><strong>Pad-Size-Increase</strong>: increases the width of the paddle by 50 pixels.</li> 
    367   <li><strong>Confuse</strong>: activates the confuse postprocessing effect for a short period of time, confusing the user. </li> 
    368   <li><strong>Chaos</strong>: activates the chaos postprocessing effect for a short period of time, heavily disorienting the user.</li> 
    369 </ul>
    370   
    371 <p>
    372  You can find the textures here:
    373 </p>
    374   
    375 <ul>
    376   <li><strong>Textures</strong>: <a href="/img/in-practice/breakout/textures/powerup_speed.png" target="_blank">Speed</a>, <a href="/img/in-practice/breakout/textures/powerup_sticky.png" target="_blank">Sticky</a>, <a href="/img/in-practice/breakout/textures/powerup_passthrough.png" target="_blank">Pass-Through</a>, <a href="/img/in-practice/breakout/textures/powerup_increase.png" target="_blank">Pad-Size-Increase</a>, <a href="/img/in-practice/breakout/textures/powerup_confuse.png" target="_blank">Confuse</a>, <a href="/img/in-practice/breakout/textures/powerup_chaos.png" target="_blank">Chaos</a>.
    377 </ul>
    378   
    379 <p>
    380    Similar to the level block textures, each of the powerup textures is completely grayscale. This makes sure the color of the powerups remain balanced whenever we multiply them with a color vector. 
    381 </p>
    382   
    383 <p>
    384   Because powerups have state, a duration, and certain effects associated with them, we would like to keep track of all the powerups currently active in the game; we store them in a vector:
    385 </p>
    386   
    387 <pre><code>
    388 class Game {
    389     public:
    390         [...]
    391         std::vector&lt;PowerUp&gt;  PowerUps;
    392         [...]
    393         void SpawnPowerUps(GameObject &block);
    394         void UpdatePowerUps(float dt);
    395 };
    396 </code></pre>
    397   
    398 <p>
    399   We've also defined two functions for managing powerups. <fun>SpawnPowerUps</fun> spawns a powerups at the location of a given block and <fun>UpdatePowerUps</fun> manages all powerups currently active within the game.
    400 </p>
    401   
    402 <h3>Spawning PowerUps</h3>
    403 <p>
    404   Each time a block is destroyed we would like to, given a small chance, spawn a powerup. This functionality is found inside the game's <fun>SpawnPowerUps</fun> function:
    405 </p>
    406   
    407 <pre><code>
    408 bool ShouldSpawn(unsigned int chance)
    409 {
    410     unsigned int random = rand() % chance;
    411     return random == 0;
    412 }
    413 void Game::SpawnPowerUps(GameObject &block)
    414 {
    415     if (ShouldSpawn(75)) // 1 in 75 chance
    416         this-&gt;PowerUps.push_back(
    417              PowerUp("speed", glm::vec3(0.5f, 0.5f, 1.0f), 0.0f, block.Position, tex_speed
    418          ));
    419     if (ShouldSpawn(75))
    420         this-&gt;PowerUps.push_back(
    421             PowerUp("sticky", glm::vec3(1.0f, 0.5f, 1.0f), 20.0f, block.Position, tex_sticky 
    422         );
    423     if (ShouldSpawn(75))
    424         this-&gt;PowerUps.push_back(
    425             PowerUp("pass-through", glm::vec3(0.5f, 1.0f, 0.5f), 10.0f, block.Position, tex_pass
    426         ));
    427     if (ShouldSpawn(75))
    428         this-&gt;PowerUps.push_back(
    429             PowerUp("pad-size-increase", glm::vec3(1.0f, 0.6f, 0.4), 0.0f, block.Position, tex_size    
    430         ));
    431     if (ShouldSpawn(15)) // negative powerups should spawn more often
    432         this-&gt;PowerUps.push_back(
    433             PowerUp("confuse", glm::vec3(1.0f, 0.3f, 0.3f), 15.0f, block.Position, tex_confuse
    434         ));
    435     if (ShouldSpawn(15))
    436         this-&gt;PowerUps.push_back(
    437             PowerUp("chaos", glm::vec3(0.9f, 0.25f, 0.25f), 15.0f, block.Position, tex_chaos
    438         ));
    439 }  
    440 </code></pre>
    441   
    442 <p>
    443   The <fun>SpawnPowerUps</fun> function creates a new <fun>PowerUp</fun> object based on a given chance (1 in 75 for normal powerups and 1 in 15 for negative powerups) and sets their properties. Each powerup is given a specific color to make them more recognizable for the user and a duration in seconds based on its type; here a duration of <code>0.0f</code> means its duration is infinite. Additionally, each powerup is given the position of the destroyed block and one of the textures from the beginning of this chapter.
    444 </p>
    445   
    446 <h3>Activating PowerUps</h3>
    447 <p>
    448   We then have to update the game's <fun>DoCollisions</fun> function to not only check for brick and paddle collisions, but also collisions between the paddle and each non-destroyed PowerUp. Note that we call <fun>SpawnPowerUps</fun> directly after a block is destroyed.
    449 </p>
    450   
    451 <pre><code>
    452 void Game::DoCollisions()
    453 {
    454     for (GameObject &box : this-&gt;Levels[this-&gt;Level].Bricks)
    455     {
    456         if (!box.Destroyed)
    457         {
    458             Collision collision = CheckCollision(*Ball, box);
    459             if (std::get&lt;0&gt;(collision)) // if collision is true
    460             {
    461                 // destroy block if not solid
    462                 if (!box.IsSolid)
    463                 {
    464                     box.Destroyed = true;
    465                     this-&gt;SpawnPowerUps(box);
    466                 }
    467                 [...]
    468             }
    469         }
    470     }        
    471     [...] 
    472     for (PowerUp &powerUp : this-&gt;PowerUps)
    473     {
    474         if (!powerUp.Destroyed)
    475         {
    476             if (powerUp.Position.y &gt;= this-&gt;Height)
    477                 powerUp.Destroyed = true;
    478             if (CheckCollision(*Player, powerUp))
    479             {	// collided with player, now activate powerup
    480                 ActivatePowerUp(powerUp);
    481                 powerUp.Destroyed = true;
    482                 powerUp.Activated = true;
    483             }
    484         }
    485     }  
    486 }
    487 </code></pre>
    488 
    489 <p>
    490   For all powerups not yet destroyed, we check if the powerup either reached the bottom edge of the screen or collided with the paddle. In both cases the powerup is destroyed, but when collided with the paddle, it is also activated.
    491 </p>
    492   
    493 <p>
    494   Activating a powerup is accomplished by settings its <var>Activated</var> property to <code>true</code> and enabling the powerup's effect by giving it to the <fun>ActivatePowerUp</fun> function:
    495 </p>
    496   
    497 <pre><code>
    498 void ActivatePowerUp(PowerUp &powerUp)
    499 {
    500     if (powerUp.Type == "speed")
    501     {
    502         Ball-&gt;Velocity *= 1.2;
    503     }
    504     else if (powerUp.Type == "sticky")
    505     {
    506         Ball-&gt;Sticky = true;
    507         Player-&gt;Color = glm::vec3(1.0f, 0.5f, 1.0f);
    508     }
    509     else if (powerUp.Type == "pass-through")
    510     {
    511         Ball-&gt;PassThrough = true;
    512         Ball-&gt;Color = glm::vec3(1.0f, 0.5f, 0.5f);
    513     }
    514     else if (powerUp.Type == "pad-size-increase")
    515     {
    516         Player-&gt;Size.x += 50;
    517     }
    518     else if (powerUp.Type == "confuse")
    519     {
    520         if (!Effects-&gt;Chaos)
    521             Effects-&gt;Confuse = true; // only activate if chaos wasn't already active
    522     }
    523     else if (powerUp.Type == "chaos")
    524     {
    525         if (!Effects-&gt;Confuse)
    526             Effects-&gt;Chaos = true;
    527     }
    528 } 
    529 </code></pre>
    530   
    531 <p>
    532   The purpose of <fun>ActivatePowerUp</fun> is exactly as it sounds: it activates the effect of a powerup as we've described at the start of this chapter. We check the type of the powerup and change the game state accordingly. For the <code>"sticky"</code> and <code>"pass-through"</code> effect, we also change the color of the paddle and the ball respectively to give the user some feedback as to which effect is currently active.
    533 </p>
    534   
    535 <p>
    536    Because the sticky and pass-through effects somewhat change the game logic we store their effect as a property of the ball object; this way we can change the game logic based on whatever effect on the ball is currently active. The only thing we've changed in the <fun>BallObject</fun> header is the addition of these two properties, but for completeness' sake its updated code is listed below:
    537 </p>
    538   
    539 <ul>
    540   <li><strong>BallObject</strong>: <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/ball_object.h" target="_blank">header</a>, <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/ball_object.cpp" target="_blank">code</a>.</li>
    541 </ul>
    542   
    543 <p>
    544   We can then easily implement the sticky effect by slightly updating the <fun>DoCollisions</fun> function at the collision code between the ball and the paddle:
    545 </p>
    546   
    547 <pre><code>
    548 if (!Ball-&gt;Stuck && std::get&lt;0&gt;(result))
    549 {
    550     [...]
    551     Ball-&gt;Stuck = Ball-&gt;Sticky;
    552 }
    553 </code></pre>
    554   
    555 <p>
    556   Here we set the ball's <var>Stuck</var> property equal to the ball's <var>Sticky</var> property. If the sticky effect is activated, the ball will end up stuck to the player paddle whenever it collides; the user then has to press the spacebar again to release the ball.
    557 </p>
    558   
    559 <p>
    560   A similar small change is made for the pass-through effect within the same <fun>DoCollisions</fun> function. When the ball's <var>PassThrough</var> property is set to <code>true</code> we do not perform any collision resolution on the non-solid bricks.
    561 </p>
    562   
    563 <pre><code>
    564 Direction dir = std::get&lt;1&gt;(collision);
    565 glm::vec2 diff_vector = std::get&lt;2&gt;(collision);
    566 if (!(Ball-&gt;PassThrough && !box.IsSolid)) 
    567 {
    568     if (dir == LEFT || dir == RIGHT) // horizontal collision
    569     {
    570         [...]
    571     }
    572     else 
    573     {
    574         [...]
    575     }
    576 }  
    577 </code></pre>
    578   
    579 <p>
    580   The other effects are activated by simply modifying the game's state like the ball's velocity, the paddle's size, or an effect of the <fun>PostProcesser</fun> object.
    581 </p>
    582   
    583 <h3>Updating PowerUps</h3>
    584 <p>
    585   Now all that is left to do is make sure that powerups are able to move once they've spawned and that they're deactivated as soon as their duration runs out; otherwise powerups will stay active forever.
    586 </p>
    587   
    588 <p>
    589   Within the game's <fun>UpdatePowerUps</fun> function we move the powerups based on their velocity and decrease the active powerups their duration. Whenever a powerup's duration is decreased to <code>0.0f</code>, its effect is deactivated and the relevant variables are reset to their original state:
    590 </p>
    591   
    592 <pre><code>
    593 void Game::UpdatePowerUps(float dt)
    594 {
    595     for (PowerUp &powerUp : this-&gt;PowerUps)
    596     {
    597         powerUp.Position += powerUp.Velocity * dt;
    598         if (powerUp.Activated)
    599         {
    600             powerUp.Duration -= dt;
    601 
    602             if (powerUp.Duration &lt;= 0.0f)
    603             {
    604                 // remove powerup from list (will later be removed)
    605                 powerUp.Activated = false;
    606                 // deactivate effects
    607                 if (powerUp.Type == "sticky")
    608                 {
    609                     if (!isOtherPowerUpActive(this-&gt;PowerUps, "sticky"))
    610                     {	// only reset if no other PowerUp of type sticky is active
    611                         Ball-&gt;Sticky = false;
    612                         Player-&gt;Color = glm::vec3(1.0f);
    613                     }
    614                 }
    615                 else if (powerUp.Type == "pass-through")
    616                 {
    617                     if (!isOtherPowerUpActive(this-&gt;PowerUps, "pass-through"))
    618                     {	// only reset if no other PowerUp of type pass-through is active
    619                         Ball-&gt;PassThrough = false;
    620                         Ball-&gt;Color = glm::vec3(1.0f);
    621                     }
    622                 }
    623                 else if (powerUp.Type == "confuse")
    624                 {
    625                     if (!isOtherPowerUpActive(this-&gt;PowerUps, "confuse"))
    626                     {	// only reset if no other PowerUp of type confuse is active
    627                         Effects-&gt;Confuse = false;
    628                     }
    629                 }
    630                 else if (powerUp.Type == "chaos")
    631                 {
    632                     if (!isOtherPowerUpActive(this-&gt;PowerUps, "chaos"))
    633                     {	// only reset if no other PowerUp of type chaos is active
    634                         Effects-&gt;Chaos = false;
    635                     }
    636                 }                
    637             }
    638         }
    639     }
    640     this-&gt;PowerUps.erase(std::remove_if(this-&gt;PowerUps.begin(), this-&gt;PowerUps.end(),
    641         [](const PowerUp &powerUp) { return powerUp.Destroyed && !powerUp.Activated; }
    642     ), this-&gt;PowerUps.end());
    643 }  
    644 </code></pre>
    645   
    646 <p>
    647   You can see that for each effect we disable it by resetting the relevant items to their original state. We also set the powerup's <var>Activated</var> property to <code>false</code>. At the end of <fun>UpdatePowerUps</fun> we then loop through the <var>PowerUps</var> vector and erase each powerup if they are destroyed <strong>and</strong> deactivated. We use the <fun>remove_if</fun> function from the <fun>algorithm</fun> header to erase these items given a lambda predicate.
    648 </p>
    649   
    650 <note>
    651   The <fun>remove_if</fun> function moves all elements for which the lambda predicate is true to the end of the container object and returns an iterator to the start of this <em>removed elements</em> range. The container's <fun>erase</fun> function then takes this iterator and the vector's end iterator to remove all the elements between these two iterators.
    652 </note>
    653   
    654 <p>
    655   It may happen that while one of the powerup effects is active, another powerup of the same type collides with the player paddle. In that case we have more than 1 powerup of that type currently active within the game's <var>PowerUps</var> vector. Whenever one of these powerups gets deactivated, we don't want to disable its effects yet since another powerup of the same type may still be active. For this reason we use the <fun>IsOtherPowerUpActive</fun> function to check if there is still another powerup active of the same type. Only if this function returns <code>false</code> we deactivate the powerup. This way, the powerup's duration of a given type is extended to the duration of its last activated powerup:
    656 </p>
    657   
    658 <pre><code>
    659 bool IsOtherPowerUpActive(std::vector&lt;PowerUp&gt; &powerUps, std::string type)
    660 {
    661     for (const PowerUp &powerUp : powerUps)
    662     {
    663         if (powerUp.Activated)
    664             if (powerUp.Type == type)
    665                 return true;
    666     }
    667     return false;
    668 }  
    669 </code></pre>
    670 
    671 <p>
    672   The function checks for all activated powerups if there is still a powerup active of the same type and if so, returns <code>true</code>.
    673 </p>
    674   
    675 <p>
    676   The last thing left to do is render the powerups:
    677 </p>
    678   
    679 <pre><code>
    680 void Game::Render()
    681 {
    682     if (this->State == GAME_ACTIVE)
    683     {
    684         [...]
    685         for (PowerUp &powerUp : this-&gt;PowerUps)
    686             if (!powerUp.Destroyed)
    687                 powerUp.Draw(*Renderer);
    688         [...]
    689     }
    690 }    
    691 </code></pre>
    692   
    693 <p>
    694   Combine all this functionality and we have a working powerup system that not only makes the game more fun, but also a lot more challenging. It'll look a bit like this:
    695 </p>
    696 
    697 <div class="video paused" onclick="ClickVideo(this)">
    698   <video width="600" height="450" loop>
    699     <source src="/video/in-practice/breakout/powerups.mp4" type="video/mp4" />
    700     <img src="/img/in-practice/breakout/powerups_video.png" class="clean"/>
    701   </video>
    702 </div>
    703   
    704 <p>
    705   You can find the updated game code here (there we also reset all powerup effects whenever the level is reset):
    706 </p>
    707   
    708 <ul>
    709   <li><strong>Game</strong>: <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/progress/8.game.h" target="_blank">header</a>, <a href="/code_viewer_gh.php?code=src/7.in_practice/3.2d_game/0.full_source/progress/8.game.cpp" target="_blank">code</a>.</li>
    710 </ul>  
    711        
    712 
    713     </div>
    714     
    715     <div id="hover">
    716         HI
    717     </div>
    718    <!-- 728x90/320x50 sticky footer -->
    719 <div id="waldo-tag-6196"></div>
    720 
    721    <div id="disqus_thread"></div>
    722 
    723     
    724 
    725 
    726 </div> <!-- container div -->
    727 
    728 
    729 </div> <!-- super container div -->
    730 </body>
    731 </html>
    732 	</main>
    733 </body>
    734 </html>