123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- <!DOCTYPE html>
- <html lang="en-us">
- <head>
- <meta charset="utf-8">
- <meta name="generator" content="Hugo 0.92.0" />
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="/assets/css/theme.css">
- <link rel="alternate" href="/rss.xml" type="application/rss+xml" title="Pleasant Programmer">
- <script type="text/javascript" src="//use.typekit.net/iwm5axp.js"></script>
- <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
- <title>Audventure - Pleasant Programmer</title>
- </head>
- <body>
- <header id="header" role="banner">
- <div id="thomas">
- <img src="/assets/img/thomas.gif" alt="DJ THOMAS IN DA HAUS">
- <img src="/assets/img/thomas.png" alt="Pleasant Programmer">
- </div>
- <h1 class="site-title"><a href="/">Pleasant Programmer</a></h1>
- <nav id="menu" role="navigation">
- <ul>
- <li><a href="/pages/projects.html">projects</a></li>
- <li><a href="/posts.html">archives</a></li>
- <li><a href="/tags.html">tags</a></li>
- <li><a href="/rss.xml">rss</a></li>
- </ul>
- </nav>
- </header>
- <div id="container">
- <main id="content" role="main">
- <article itemscope itemtype="http://schema.org/BlogPosting">
- <h1 class="p-name entry-title" itemprop="headline name">
- <a href="/posts/audventure.html">Audventure</a></h1>
- <small>
- <span class="dateline">Posted: <time itemprop="datePublished" datetime="2017-11-19">2017-11-19</time></span>
- | More posts about
-
- <a class="tag p-category" href="/tags/games.html" rel="tag">
- games
- </a>
-
- <a class="tag p-category" href="/tags/programming.html" rel="tag">
- programming
- </a>
-
- </small>
- <div class="e-content entry-content" itemprop="entry-text">
- <p>Sometime around 2013 I wrote a clone of the GBA game <a href="https://www.nintendo.co.jp/n08/bit_g/">bit Generations
- SoundVoyager</a> called
- <a href="https://audventure.pleasantprogrammer.com">audventure</a>. SoundVoyager is
- actually a collection of mini-games where sound is the main focus. You can
- actually play the game blind, and at some point, that’s pretty much what
- happens.</p>
- <h2 id="sound-catcher">sound catcher</h2>
- <p>The signature mini-game in SoundVoyager is sound catcher. In the mini-game, you
- can only move left and right at the bottom of the stage, while a “sound” falls
- from the top. Your goal is to catch the sound which is signified by a green dot.
- When you catch it, the sound or beat becomes part of the BGM and a new dot
- appears with a different sound.</p>
- <p>You can of course use your eyes and move accordingly, but if you put on
- earphones, you can actually hear where the dot is, either on your left or right,
- with it getting louder as it gets close to you. As you collect more sounds, the
- dot gets more and more transparent. Eventually (and this is where it gets fun),
- you won’t be able to see the sounds anymore and will have to rely mostly on your
- ears.</p>
- <p>You can see what the original game looks like in <a href="https://www.youtube.com/watch?v=C12WRgfIOC8">this
- video</a> or you can play it under
- <em>sound safari</em> in <a href="https://audventure.pleasantprogrammer.com">audventure</a>.</p>
- <h2 id="webaudio-vs-flash">WebAudio vs Flash</h2>
- <p>At the time I wrote audventure, only Chrome supported WebAudio. Also, the API
- looked (and still looks) quite complicated. Flash on the other hand, was
- starting to die, but still well-supported so I went with that. For the most
- part, it worked okay though Chrome actually had timing issues when playing
- sounds. Now, it doesn’t work in any browser. I tried to debug the issues but
- ultimately ended up just rewriting it to use WebAudio instead.</p>
- <p>For the game, I needed to simulate the source of the sound in 2D/3D space. Flash
- only really gives you stereo panning and volume control. With some maths, we can
- actually get an acceptable solution. Less importantly, I needed to be able to
- get frequency data of the currently playing “sound” to pulse the background. For
- this, I actually had to implement the feature in the Flash library I was using.</p>
- <p>With WebAudio, spatial audio is already built-in and you can simply give it the
- coordinates of the sounds and the listener. There are some other options to
- tweak, but for the most part, no complex math is needed. Getting frequency data
- for a sound is also actually built-in and didn’t take too long to integrate.</p>
- <p>Overall, I was impressed by how much you can do with WebAudio out-of-the-box. I
- kind of understand why it’s complicated, but there’s some simple functionality
- that I wish was included. For example, there is no API to pause and then resume
- playing an audio buffer. You have to manually save the elapsed time and play
- from there.</p>
- <h2 id="other-mini-games">Other mini-games</h2>
- <p>So far I’ve only actually implemented the sound catcher mini-game. There are
- around 4 different categories with slight variations in between.</p>
- <h3 id="sound-catcher--sound-slalom">sound catcher / sound slalom</h3>
- <p>I’ve explained sound catcher a while ago; sound slalom is a minor variation on
- that. Instead of waiting for the “sound” to reach you, you now have to guide
- yourself in between 2 “poles” of sound, as in <a href="https://en.wikipedia.org/wiki/Slalom_skiing">slalom
- skiing</a>. But this time, you can
- also accelerate forward. The goal is to finish the course before the time runs
- out.</p>
- <h3 id="sound-drive--sound-chase">sound drive / sound chase</h3>
- <p>In sound drive, you’re driving against the flow on a 5 lane road. You have to
- avoid oncoming cars, trucks and animals until you reach the end. You’re allowed
- to change lanes and accelerate, and the game tracks your best time. Sound chase
- is pretty much the same, except you’re trying to catch up to a “sound”.</p>
- <h3 id="sound-cannon">sound cannon</h3>
- <p>In sound cannon, you’re immobile but can rotate within a 180 degree angle. Your
- goal is too shoot down “sounds” which are heading your way. If a sound reaches
- you, it’s game over. You win when you kill all the sounds.</p>
- <h3 id="sound-picker--sound-cock">sound picker / sound cock</h3>
- <p>In sound picker, you can move in a giant square field where various sounds are
- scattered around. Your goal is to pick up all the sounds within the time limit.
- Sound cock is similar, except the sounds are chickens and you have to chase them
- around.</p>
- <h2 id="source-code">Source Code</h2>
- <p>If you want to see the source code, you can check it out
- <a href="https://git.pleasantprogrammer.com/games/audventure">here</a>. The sound files
- aren’t in the repo though, since I’m not quite sure about the licensing. If you
- want to contribute music or sound effects, I’d gladly appreciate it.</p>
- </div>
- <aside class="postpromonav">
- <nav>
- <ul class="pager clearfix">
-
- <li class="previous">
- <a href="/posts/openpreppad.html" rel="prev" title="OpenPrepPad">← Previous post</a>
- </li>
-
-
- <li class="next">
- <a href="/posts/isp-issues.html" rel="next" title="ISP Issues">Next post →</a>
- </li>
-
- </ul>
- </nav>
- </aside>
- <section class="comments">
- <script
- data-isso="https://isso.pleasantprogrammer.com/"
- data-isso-require-author="true"
- data-isso-vote="false"
- src="https://isso.pleasantprogrammer.com/js/embed.min.js">
- </script>
- <section id="isso-thread"></section>
- </section>
- </article>
- </main>
- <footer id="footer" role="contentinfo">
- <p>
- <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_US">
- <img alt="CC-BY-SA" style="border-width:0" src="https://licensebuttons.net/l/by-sa/3.0/80x15.png">
- </a> © 2022 Thomas Dy - Powered by <a href="http://gohugo.io">Hugo</a></p>
- </footer>
- </div>
- <script src="/assets/js/konami.js"></script>
- <script>
- var easter_egg = new Konami();
- easter_egg.code = function() {
- var el = document.getElementById('thomas');
- if(el.className == "whoa") {
- el.className = "";
- }
- else {
- el.className = "whoa";
- }
- document.body.scrollTop = document.documentElement.scrollTop = 0;
- }
- easter_egg.load();
- </script>
- </body>
- </html>
|