learn-wgpu/showcase/pong/index.html

211 lines
61 KiB
HTML
Raw Normal View History

2020-11-24 06:49:43 +00:00
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Pong | Learn Wgpu</title>
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2020-09-21T18:16:28.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Pong"><meta property="og:type" content="website"><meta property="og:url" content="/showcase/pong/"><meta name="twitter:title" content="Pong"><meta name="twitter:url" content="/showcase/pong/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin R Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.7acc6ef6.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.da448c16.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/2.da3fd46f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/20.70e640cc.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/10.de8cadfb.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.65c8dcc2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.26aabcb1.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.7cd9aa08.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.b2a56b9f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.057386b5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.9abecf13.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.f03fd0c9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.d3691f26.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.e9350ae9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.19d2890c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.2132e362.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.1a88f225.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6ef5d54e.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.b4a2e728.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.f5a0678a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.04f788d9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.a3ac06e2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.281013fa.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.2d0dff45.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.dc887be9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/4.430752ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.5e4953de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.cc40d32a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88810c81.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.de43c958.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.ecb6e79c.js">
2020-11-24 06:49:43 +00:00
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.7acc6ef6.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-swapchain/" class="sidebar-link">The Swapchain</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" class="sidebar-link">Foreward</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="active sidebar-link">Pong</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/pong/#the-architecture" class="sidebar-link">The Architecture</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/pong/#input" class="sidebar-link">Input</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/pong/#render" class="sidebar-link">Render</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/pong/#sound" class="sidebar-link">Sound</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/pong/#summary" class="sidebar-link">Summary</a></li></ul></li><li><a href="/learn-wgpu/showcase/compute/" class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><a href="/learn-wgpu/sho
<span class="token keyword">pub</span> <span class="token keyword">enum</span> <span class="token type-definition class-name">GameState</span> <span class="token punctuation">{</span>
<span class="token class-name">MainMenu</span><span class="token punctuation">,</span>
<span class="token class-name">Serving</span><span class="token punctuation">,</span>
<span class="token class-name">Playing</span><span class="token punctuation">,</span>
<span class="token class-name">GameOver</span><span class="token punctuation">,</span>
<span class="token class-name">Quiting</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>The <code>State</code> class didn't have any methods on it as I was taking a more data oriented approach. Instead I created a <code>System</code> trait, and created multiple structs that implemented it.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">System</span> <span class="token punctuation">{</span>
<span class="token attribute attr-name">#[allow(unused_variables)]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">start</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> state<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">State</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">fn</span> <span class="token function-definition function">update_state</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">,</span>
input<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">input<span class="token punctuation">::</span></span><span class="token class-name">Input</span><span class="token punctuation">,</span>
state<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">State</span><span class="token punctuation">,</span>
events<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token class-name">Vec</span><span class="token operator">&lt;</span><span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">Event</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>The systems would be in charge of controlling updating the different objects state (position, visibility, etc), as well as updating the <code>game_state</code> field. I created all the systems on startup, and used a <code>match</code> on <code>game_state</code> to determine which ones should be allow to run (the <code>visiblity_system</code> always runs as it is always needed).</p> <div class="language-rust extra-class"><pre class="language-rust"><code>visiblity_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">match</span> state<span class="token punctuation">.</span>game_state <span class="token punctuation">{</span>
<span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">MainMenu</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
menu_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> state<span class="token punctuation">.</span>game_state <span class="token operator">==</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">Serving</span> <span class="token punctuation">{</span>
serving_system<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">Serving</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
serving_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
play_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> state<span class="token punctuation">.</span>game_state <span class="token operator">==</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">Playing</span> <span class="token punctuation">{</span>
play_system<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">Playing</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
ball_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
play_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> state<span class="token punctuation">.</span>game_state <span class="token operator">==</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">Serving</span> <span class="token punctuation">{</span>
serving_system<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> state<span class="token punctuation">.</span>game_state <span class="token operator">==</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">GameOver</span> <span class="token punctuation">{</span>
game_over_system<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">GameOver</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
game_over_system<span class="token punctuation">.</span><span class="token function">update_state</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>input<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">mut</span> events<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> state<span class="token punctuation">.</span>game_state <span class="token operator">==</span> <span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">MainMenu</span> <span class="token punctuation">{</span>
menu_system<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">GameState</span><span class="token punctuation">::</span><span class="token class-name">Quiting</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>It's definitely not the cleanest code, but it works.</p> <p>I ended up having 6 systems in total.</p> <ol><li><p>I added the <code>VisibilitySystem</code> near the end of development. Up to that point, all the systems had to set the <code>visible</code> field of the objects. That was a pain, and cluttered the logic. Instead I decided to create the <code>VisiblitySystem</code> to handle that.</p></li> <li><p>The <code>MenuSystem</code> handled controlling what text was focused, and what would happen when the user pressed the enter key. If the <code>Play</code> button was focused, pressing enter would change <code>game_state</code> to <code>GameState::Serving</code> which would start the game. The <code>Quit</code> button would shift to <code>GameState::Quiting</code>.</p></li> <li><p>The <code>ServingSystem</code> sets the balls position to <code>(0.0, 0.0)</code>, updates the score texts, and shifts into <code>GameState::Playing</code> after a timer.</p></li> <li><p>The <code>PlaySystem</code> controls the players. It allows them to move, and keeps them from leaving the play space. This system runs on both <code>GameState::Playing</code> as well as <code>GameState::Serving</code>. I did this to allow the players to reposition themselves before the serve. The <code>PlaySystem</code> also will shift into <code>GameState::GameOver</code> when on of the players scores is greater than 2.</p></li> <li><p>The <code>BallSystem</code> system controls the balls movement as well as its bouncing of walls/players. It also updates the score and shifts to <code>GameState::Serving</code> when the ball goes off the side of the screen.</p></li> <li><p>The <code>GameOver</code> system updates the <code>win_text</code> and shifts to <code>GameState::MainMenu</code> after a delay.</p></li></ol> <p>I found the system approach to quite nice to work with. My implementation wasn't the best, but I would like working with it again. I might even implement my own ECS.</p> <h2 id="input"><a href="#input" class="header-anchor">#</a> Input</h2> <p>The <code>System</code> trait, originally had a <code>process_input</code> method. This became a problem when I was implementing allowing players to move between serves. The players would get stuck when the <code>game_state</code> switched from <code>Serving</code> to <code>Playing</code> as the inputs were getting stuck. I only called <code>process_input</code> on systems that were currently in use. Changing that would be finicky, so I decided to move all the input code into its own struct.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">winit<span class="token punctuation">::</span>event<span class="token punctuation">::</span></span><span class="token punctuation">{</span><span class="token class-name">VirtualKeyCode</span><span class="token punctuation">,</span> <span class="token class-name">ElementState</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token attribute attr-name">#[derive(Debug, Default)]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Input</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> p1_up_pressed<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> p1_down_pressed<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> p2_up_pressed<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> p2_down_pressed<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> enter_pressed<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token keyword">impl</span> <span class="token class-name">Input</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">Self</span> <span class="token punctuation">{</span>
<span class="token class-name">Default</span><span class="token punctuation">::</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">update</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> key<span class="token punctuation">:</span> <span class="token class-name">VirtualKeyCode</span><span class="token punctuation">,</span> state<span class="token punctuation">:</span> <span class="token class-name">ElementState</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">bool</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> pressed <span class="token operator">=</span> state <span class="token operator">==</span> <span class="token class-name">ElementState</span><span class="token punctuation">::</span><span class="token class-name">Pressed</span><span class="token punctuation">;</span>
<span class="token keyword">match</span> key <span class="token punctuation">{</span>
<span class="token class-name">VirtualKeyCode</span><span class="token punctuation">::</span><span class="token class-name">Up</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>p2_up_pressed <span class="token operator">=</span> pressed<span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token class-name">VirtualKeyCode</span><span class="token punctuation">::</span><span class="token class-name">Down</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>p2_down_pressed <span class="token operator">=</span> pressed<span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token class-name">VirtualKeyCode</span><span class="token punctuation">::</span><span class="token class-name">W</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>p1_up_pressed <span class="token operator">=</span> pressed<span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token class-name">VirtualKeyCode</span><span class="token punctuation">::</span><span class="token class-name">S</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>p1_down_pressed <span class="token operator">=</span> pressed<span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token class-name">VirtualKeyCode</span><span class="token punctuation">::</span><span class="token class-name">Return</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>enter_pressed <span class="token operator">=</span> pressed<span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
_ <span class="token operator">=&gt;</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">ui_up_pressed</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">bool</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>p1_up_pressed <span class="token operator">||</span> <span class="token keyword">self</span><span class="token punctuation">.</span>p2_up_pressed
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">ui_down_pressed</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">bool</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>p1_down_pressed <span class="token operator">||</span> <span class="token keyword">self</span><span class="token punctuation">.</span>p2_down_pressed
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>This works really well. I simply pass this struct into the <code>update_state</code> method.</p> <h2 id="render"><a href="#render" class="header-anchor">#</a> Render</h2> <p>I used <a href="https://docs.rs/wgpu_glyph" target="_blank" rel="noopener noreferrer">wgpu_glyph<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> for the text, and white quads for the ball and paddles. There's not much to say here, it's Pong after all.</p> <p>I did mess around with batching however. It was totally overkill for this project, but it was a good learning experience. Here's the code if you're interested.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">QuadBufferBuilder</span> <span class="token punctuation">{</span>
vertex_data<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator">&lt;</span><span class="token class-name">Vertex</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
index_data<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator">&lt;</span><span class="token keyword">u32</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
current_quad<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token keyword">impl</span> <span class="token class-name">QuadBufferBuilder</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">Self</span> <span class="token punctuation">{</span>
<span class="token keyword">Self</span> <span class="token punctuation">{</span>
vertex_data<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
index_data<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
current_quad<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">push_ball</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">,</span> ball<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">Ball</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">Self</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> ball<span class="token punctuation">.</span>visible <span class="token punctuation">{</span>
<span class="token keyword">let</span> min_x <span class="token operator">=</span> ball<span class="token punctuation">.</span>position<span class="token punctuation">.</span>x <span class="token operator">-</span> ball<span class="token punctuation">.</span>radius<span class="token punctuation">;</span>
<span class="token keyword">let</span> min_y <span class="token operator">=</span> ball<span class="token punctuation">.</span>position<span class="token punctuation">.</span>y <span class="token operator">-</span> ball<span class="token punctuation">.</span>radius<span class="token punctuation">;</span>
<span class="token keyword">let</span> max_x <span class="token operator">=</span> ball<span class="token punctuation">.</span>position<span class="token punctuation">.</span>x <span class="token operator">+</span> ball<span class="token punctuation">.</span>radius<span class="token punctuation">;</span>
<span class="token keyword">let</span> max_y <span class="token operator">=</span> ball<span class="token punctuation">.</span>position<span class="token punctuation">.</span>y <span class="token operator">+</span> ball<span class="token punctuation">.</span>radius<span class="token punctuation">;</span>
<span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">push_quad</span><span class="token punctuation">(</span>min_x<span class="token punctuation">,</span> min_y<span class="token punctuation">,</span> max_x<span class="token punctuation">,</span> max_y<span class="token punctuation">)</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">push_player</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">,</span> player<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">state<span class="token punctuation">::</span></span><span class="token class-name">Player</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">Self</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> player<span class="token punctuation">.</span>visible <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">push_quad</span><span class="token punctuation">(</span>
player<span class="token punctuation">.</span>position<span class="token punctuation">.</span>x <span class="token operator">-</span> player<span class="token punctuation">.</span>size<span class="token punctuation">.</span>x <span class="token operator">*</span> <span class="token number">0.5</span><span class="token punctuation">,</span>
player<span class="token punctuation">.</span>position<span class="token punctuation">.</span>y <span class="token operator">-</span> player<span class="token punctuation">.</span>size<span class="token punctuation">.</span>y <span class="token operator">*</span> <span class="token number">0.5</span><span class="token punctuation">,</span>
player<span class="token punctuation">.</span>position<span class="token punctuation">.</span>x <span class="token operator">+</span> player<span class="token punctuation">.</span>size<span class="token punctuation">.</span>x <span class="token operator">*</span> <span class="token number">0.5</span><span class="token punctuation">,</span>
player<span class="token punctuation">.</span>position<span class="token punctuation">.</span>y <span class="token operator">+</span> player<span class="token punctuation">.</span>size<span class="token punctuation">.</span>y <span class="token operator">*</span> <span class="token number">0.5</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">push_quad</span><span class="token punctuation">(</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> min_x<span class="token punctuation">:</span> <span class="token keyword">f32</span><span class="token punctuation">,</span> min_y<span class="token punctuation">:</span> <span class="token keyword">f32</span><span class="token punctuation">,</span> max_x<span class="token punctuation">:</span> <span class="token keyword">f32</span><span class="token punctuation">,</span> max_y<span class="token punctuation">:</span> <span class="token keyword">f32</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">Self</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>vertex_data<span class="token punctuation">.</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token punctuation">[</span>
<span class="token class-name">Vertex</span> <span class="token punctuation">{</span>
position<span class="token punctuation">:</span> <span class="token punctuation">(</span>min_x<span class="token punctuation">,</span> min_y<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">into</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token class-name">Vertex</span> <span class="token punctuation">{</span>
position<span class="token punctuation">:</span> <span class="token punctuation">(</span>max_x<span class="token punctuation">,</span> min_y<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">into</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token class-name">Vertex</span> <span class="token punctuation">{</span>
position<span class="token punctuation">:</span> <span class="token punctuation">(</span>max_x<span class="token punctuation">,</span> max_y<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">into</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token class-name">Vertex</span> <span class="token punctuation">{</span>
position<span class="token punctuation">:</span> <span class="token punctuation">(</span>min_x<span class="token punctuation">,</span> max_y<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">into</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>index_data<span class="token punctuation">.</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token punctuation">[</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">,</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">,</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">*</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">3</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>current_quad <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">self</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">build</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">,</span> device<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Device</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token punctuation">(</span><span class="token class-name">StagingBuffer</span><span class="token punctuation">,</span> <span class="token class-name">StagingBuffer</span><span class="token punctuation">,</span> <span class="token keyword">u32</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">(</span>
<span class="token class-name">StagingBuffer</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>device<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>vertex_data<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token class-name">StagingBuffer</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>device<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>index_data<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>index_data<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="sound"><a href="#sound" class="header-anchor">#</a> Sound</h2> <p>I used <a href="https://docs.rs/rodio" target="_blank" rel="noopener noreferrer">rodio<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> for sound. I created a <code>SoundPack</code> class to store the sounds. Deciding how to get the sounds to play took some thinking. I chose to pass in a <code>Vec&lt;state::Event&gt;</code> into the <code>update_state</code> method. The system would then push an event to the <code>Vec</code>. The <code>Event</code> enum is listed below.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[derive(Debug, Copy, Clone)]</span>
<span class="token keyword">pub</span> <span class="token keyword">enum</span> <span class="token type-definition class-name">Event</span> <span class="token punctuation">{</span>
<span class="token class-name">ButtonPressed</span><span class="token punctuation">,</span>
<span class="token class-name">FocusChanged</span><span class="token punctuation">,</span>
<span class="token class-name">BallBounce</span><span class="token punctuation">(</span><span class="token namespace">cgmath<span class="token punctuation">::</span></span><span class="token class-name">Vector2</span><span class="token operator">&lt;</span><span class="token keyword">f32</span><span class="token operator">&gt;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token class-name">Score</span><span class="token punctuation">(</span><span class="token keyword">u32</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>I was going to have <code>BallBounce</code> play a positioned sound using a <code>SpatialSink</code>, but I was getting clipping issues, and I wanted to be done with the project. Aside from that, the events system worked nicely.</p> <h2 id="summary"><a href="#summary" class="header-anchor">#</a> Summary</h2> <p>A fun project to work on. It was overly architected, and kinda hard to make changes, but a good experience none the less.</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">9/21/2020, 6:16:28 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
2020-11-24 06:49:43 +00:00
<a href="/learn-wgpu/showcase/gifs/" class="prev">
Creating gifs
</a></span> <span class="next"><a href="/learn-wgpu/showcase/compute/">
Compute Example: Tangents and Bitangents
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.da448c16.js" defer></script><script src="/learn-wgpu/assets/js/2.da3fd46f.js" defer></script><script src="/learn-wgpu/assets/js/20.70e640cc.js" defer></script>
2020-11-24 06:49:43 +00:00
</body>
</html>