{
    "componentChunkName": "component---src-templates-blog-post-js",
    "path": "/tau-dash/",
    "result": {"data":{"site":{"siteMetadata":{"title":"Unlimish","author":"Unlimish"}},"markdownRemark":{"id":"4ab0b1ff-b42b-5e33-93ee-4d445b1035a3","excerpt":"Concept TAU Dash is a retro map exploration and landmark hunting game built for the Rabbit Pie board — a Raspberry Pi Pico (RP2040) with a 128×64 monochrome…","html":"<h2>Concept</h2>\n<p>TAU Dash is a retro map exploration and landmark hunting game built for the <strong>Rabbit Pie</strong> board — a Raspberry Pi Pico (RP2040) with a 128×64 monochrome OLED, a joystick, four buttons and an I2S DAC.</p>\n<p>The map is not decoration. It is the <strong>Tama Art University Hachioji Campus</strong> itself, extracted from OpenStreetMap and baked into 4,460 vector line segments that the Pico redraws every frame. You scroll, rotate and zoom the real campus while a countdown pushes you from one building to the next — the feeling of an art student sprinting between studios to make a deadline, compressed into 45 seconds.</p>\n<div style=\"max-width: 340px; margin: 0 auto;\">\n<div class=\"gatsby-resp-iframe-wrapper\" style=\"padding-bottom: 177.77777777777777%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem\" > <iframe src=\"https://www.youtube.com/embed/Z9azmeOfoNU\" title=\"TAU Dash running on the Rabbit Pie board\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\" style=\" position: absolute; top: 0; left: 0; width: 100%; height: 100%; \"></iframe> </div>\n</div>\n<p><em>Playing on the Rabbit Pie board — joystick to scroll, SW2 to cycle zoom.</em>\n<img src=\"/6581ad62e31e3cd8c78133f2c030b0c2/tau_dash_play.gif\" alt=\"Play-through: the target landmark, the player crosshair, and the live distance / timer HUD\"></p>\n<p><em>Replayed from the firmware’s own render path — the same 4,460 map segments, clipping and HUD the board draws, driven by a scripted joystick instead of a real one.</em></p>\n<h2>Game Rules</h2>\n<ol>\n<li><strong>Locate the target landmark.</strong> The HUD names your next destination (<code class=\"language-text\">GO TO: Library</code>). If it is off-screen, a pointer arrow blinks at the screen border to aim you at it.</li>\n<li><strong>The crosshair is you.</strong> The map scrolls underneath the player, with acceleration and inertia — release the stick and you slide smoothly to a stop.</li>\n<li><strong>Proximity alerts.</strong> Passing close to any of the 24 registered buildings pops up a <code class=\"language-text\">Near: [Building]</code> box.</li>\n<li><strong>Arrive and earn time.</strong> Reaching a target centroid within 15 m plays a three-note victory chime and extends the clock. The bonus decays exponentially as your score climbs — <code class=\"language-text\">1.5 + 8.5 × e^(−0.22 × score)</code> seconds — bottoming out at a merciless 1.5 s.</li>\n<li><strong>Game over at 0.0 s.</strong> Under five seconds the game starts ticking a warning beep on every second boundary. When the timer runs out the BGM stops dead and an 8-bit slide-down plays.</li>\n</ol>\n<h2>Interface Design for 128×64 Pixels</h2>\n<p>Every element had to survive in one bit of colour and a screen smaller than a postage stamp.</p>\n<ul>\n<li><strong>Three zoom levels</strong> (<code class=\"language-text\">0.5x</code> / <code class=\"language-text\">1.0x</code> / <code class=\"language-text\">1.8x</code>) — zoom out to find the target, zoom in to land on it.</li>\n<li><strong>Map rotation</strong> by holding SW0 and pushing the stick sideways; camera inertia freezes while rotating so the world does not drift under you.</li>\n<li><strong>A volume HUD</strong> that appears on a long press of SW1, so the sound can be tuned without a menu screen.</li>\n<li><strong>Target skip</strong> on SW3 for when a landmark is hopeless — at the cost of five seconds and a warning buzz.</li>\n</ul>\n<p><img src=\"/6581ad62e31e3cd8c78133f2c030b0c2/tau_dash_play.gif\" alt=\"Play-through: the target landmark, the player crosshair, and the live distance / timer HUD\"></p>\n<p><em>Replayed from the firmware’s own render path — the same 4,460 map segments, clipping and HUD the board draws, driven by a scripted joystick instead of a real one.</em></p>\n<p><figure class=\"gatsby-resp-image-figure\" style=\"margin: 0 0;\">\n    <span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1024px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0a2453e3df4e8dfcca4a2d6418bd7d19/bcc59/tau_dash_volume.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAACHElEQVQozy3Q3UvyYBgG8FsUDVFnbu7D+THWyvks92hzsumCrJWDYshESUqkGCoKngmeqOBZeiYE/bkv2fs7ug7uCy5u8DzPsqzRaAQAtVptMpkMh0PP8z4+PiRJsixrPp+/v7/3+/35fG7bdrVardfr2WwWAEBRlJeXF13XASCVSlWr1XK5HAwGTdNECNVqNc/zNE1jGKZYLDqOMxgMTNP8Xy4Wi5VKpd1uy7LMsmypVMIY8zzPcZymaaqqYozz+TzP8zRN393djUYjx3Gurq4EQQBJksLhcLlcvr29fX5+bjQaCCHXdYfDYa/XM03z7e2tVCrd39+7rmvbtqZpuq6bpvk7VpZlkiQ1TctkMoIg2Lbt+/7n5+disZhOp51Op9vtNptNx3EeHx8FQYhGo5ZltVotnueBZdlWq/X09BQKhQBgMBj8/Pzs9/vD4XA8Hne7HULo8vJSFEWMcSwW+/urqqq/9+fn55IkKYpC03Q8Hk+lUiRJFgoFlmX/MnOSyWQoikqcqCdnZ2eQSCRyuRxBEKIo5k+y2axhGBcXFwghjDFJkoZh2LZtGEaj0RBFMZlMRiKRTqcDNE1jjAGAIIhYLBYKhTiOKxQKDMO02+2bmxuKojiOA4B0Oq3r+vX1dTqdJgji4eEBxuPxfr93XXc2m223W8dx1uv19/e37/vL5XKz2Xx9fSGEACAQCKxWK9/3X19fd7udoij/AB35em5mBrfGAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/0a2453e3df4e8dfcca4a2d6418bd7d19/f6ff9/tau_dash_volume.webp 340w,\n/static/0a2453e3df4e8dfcca4a2d6418bd7d19/ad3d6/tau_dash_volume.webp 680w,\n/static/0a2453e3df4e8dfcca4a2d6418bd7d19/f186c/tau_dash_volume.webp 1024w\"\n              sizes=\"(max-width: 1024px) 100vw, 1024px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/0a2453e3df4e8dfcca4a2d6418bd7d19/017ed/tau_dash_volume.png 340w,\n/static/0a2453e3df4e8dfcca4a2d6418bd7d19/56a38/tau_dash_volume.png 680w,\n/static/0a2453e3df4e8dfcca4a2d6418bd7d19/bcc59/tau_dash_volume.png 1024w\"\n            sizes=\"(max-width: 1024px) 100vw, 1024px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/0a2453e3df4e8dfcca4a2d6418bd7d19/bcc59/tau_dash_volume.png\"\n            alt=\"Volume adjustment overlaid on the live map\"\n            title=\"Volume adjustment overlaid on the live map\"\n            loading=\"lazy\"\n            decoding=\"async\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span>\n    <figcaption class=\"gatsby-resp-image-figcaption\">Volume adjustment overlaid on the live map</figcaption>\n  </figure></p>\n<p>Drawing OSM geometry on a 128×64 buffer meant lines constantly ran off-canvas, and U8g2’s coordinates wrap rather than clip. The renderer runs <strong>Cohen-Sutherland line clipping</strong> on every segment before it reaches the display, which is what keeps the map from tearing itself apart at the screen edges.</p>\n<p><figure class=\"gatsby-resp-image-figure\" style=\"margin: 0 0;\">\n    <span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1024px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4a3552d4adca0de10de4b3c992392f2c/bcc59/tau_dash_gameover.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbklEQVQoz62RX6vaQBDFt0ETIwZRDKJxDWYxySSyCbvBKJqIeZAYWRf8A+JHEL//c+m19d6W0qeepzmH+c3ADEL/Rd9+SdM0VVU1TTMMQ1VVXdfr9Xq73W42m/+CEUKGYZzP5+v1+nw+7/e7bdtJklRVdbvdDodDo9H4O9bpdEajkWmanPPxeBx/aDqduq4bhuF6vSaEmKb57v8N9n2/LMvH4yGlxBgDwGazCYJgu93u9/vVamXbdp7nCCFFUT7Jl7EsK/zQYrEAgOFwSCl1XZdSCgCO40wmE9/3e71et9vVdf3niNfmVquV5zkAcM6rqoqiiFJaFAVjjBCiKEqSJFmW7Xa7y+VSFEWtVkP9fj+O49lsFoZhEASEkMFgsFwu0zS1LMvzPADAGFNKGWOU0iiKGGNxHHuehwghaZpKKYUQWZYlSQIAp9NJCIExdhyHc84Yk1KWZTmfzxljQojj8fgD/uPPb/u+ytf8VbyT7+wYP7v9ulFXAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/4a3552d4adca0de10de4b3c992392f2c/f6ff9/tau_dash_gameover.webp 340w,\n/static/4a3552d4adca0de10de4b3c992392f2c/ad3d6/tau_dash_gameover.webp 680w,\n/static/4a3552d4adca0de10de4b3c992392f2c/f186c/tau_dash_gameover.webp 1024w\"\n              sizes=\"(max-width: 1024px) 100vw, 1024px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/4a3552d4adca0de10de4b3c992392f2c/017ed/tau_dash_gameover.png 340w,\n/static/4a3552d4adca0de10de4b3c992392f2c/56a38/tau_dash_gameover.png 680w,\n/static/4a3552d4adca0de10de4b3c992392f2c/bcc59/tau_dash_gameover.png 1024w\"\n            sizes=\"(max-width: 1024px) 100vw, 1024px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/4a3552d4adca0de10de4b3c992392f2c/bcc59/tau_dash_gameover.png\"\n            alt=\"Game over: final score and total distance walked\"\n            title=\"Game over: final score and total distance walked\"\n            loading=\"lazy\"\n            decoding=\"async\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span>\n    <figcaption class=\"gatsby-resp-image-figcaption\">Game over: final score and total distance walked</figcaption>\n  </figure></p>\n<h2>Sound on the Second Core</h2>\n<p>The RP2040’s two cores are split down the middle: <strong>Core 0</strong> handles input and rendering, <strong>Core 1</strong> runs a Mozzi synthesizer over the I2S DAC. The background track is a two-voice swing loop — a 32-step melody over a bass line — written to sound cosy in the way <em>Animal Crossing</em> is cosy, so that the countdown feels hectic instead of hostile. Sound effects (arrival chime, warning tick, sweep, skip buzz) are triggered by flags shared across the cores.</p>\n<p><figure class=\"gatsby-resp-image-figure\" style=\"margin: 0 0;\">\n    <span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 282px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/a646dd29101a2586b6a16421ceddaf73/233d8/tau_dash_device.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 177.3049645390071%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAjABQDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAECAwQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHw19F50CY0pLC4mw1kGP/EABsQAAEEAwAAAAAAAAAAAAAAAAIAASAhAxAS/9oACAEBAAEFAq1SDliymJReX//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/AWP/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AV//xAAbEAABBAMAAAAAAAAAAAAAAAABABAREiIwMf/aAAgBAQAGPwJ8uIVEa//EABsQAQACAwEBAAAAAAAAAAAAAAEAERAhYUGB/9oACAEBAAE/Ia6lHZ9RAQo8IHsjmLcrUJRjxi7n/9oADAMBAAIAAwAAABBTFLIL/wD/xAAYEQADAQEAAAAAAAAAAAAAAAAAAREQIf/aAAgBAwEBPxC9KNabP//EABgRAAIDAAAAAAAAAAAAAAAAAAAQAREx/9oACAECAQE/EHZGr//EAB8QAQACAQUAAwAAAAAAAAAAAAEAESEQMVFhgZGhsf/aAAgBAQABPxCzZ+sT3/Mrl8SIWS6N+mMCKyACvO9FcqwWsXoWFFwXhajwL7BeWCyYWZ//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/a646dd29101a2586b6a16421ceddaf73/fc18d/tau_dash_device.webp 282w\"\n              sizes=\"(max-width: 282px) 100vw, 282px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/a646dd29101a2586b6a16421ceddaf73/233d8/tau_dash_device.jpg 282w\"\n            sizes=\"(max-width: 282px) 100vw, 282px\"\n            type=\"image/jpeg\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/a646dd29101a2586b6a16421ceddaf73/233d8/tau_dash_device.jpg\"\n            alt=\"Running on the Rabbit Pie board\"\n            title=\"Running on the Rabbit Pie board\"\n            loading=\"lazy\"\n            decoding=\"async\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span>\n    <figcaption class=\"gatsby-resp-image-figcaption\">Running on the Rabbit Pie board</figcaption>\n  </figure></p>\n<h2>Hardware</h2>\n<table>\n<thead>\n<tr>\n<th align=\"left\">Part</th>\n<th align=\"left\">Pins</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"left\">Joystick X / Y</td>\n<td align=\"left\"><code class=\"language-text\">GP26 (A0)</code> / <code class=\"language-text\">GP27 (A1)</code></td>\n</tr>\n<tr>\n<td align=\"left\">SW0-SW3</td>\n<td align=\"left\"><code class=\"language-text\">GP19</code> / <code class=\"language-text\">GP18</code> / <code class=\"language-text\">GP17</code> / <code class=\"language-text\">GP16</code></td>\n</tr>\n<tr>\n<td align=\"left\">SSD1306 128×64 OLED</td>\n<td align=\"left\">Hardware I2C — SDA <code class=\"language-text\">GP4</code>, SCL <code class=\"language-text\">GP5</code></td>\n</tr>\n<tr>\n<td align=\"left\">I2S DAC</td>\n<td align=\"left\">BCK <code class=\"language-text\">GP20</code>, WS <code class=\"language-text\">GP21</code>, DATA <code class=\"language-text\">GP22</code></td>\n</tr>\n</tbody>\n</table>\n<h4><a href=\"https://github.com/unlimish/tau_dash\">github.com/unlimish/tau_dash</a></h4>","frontmatter":{"title":"TAU Dash","date":"May 29, 2026","description":"8-bit campus map exploration game for a Raspberry Pi Pico handheld, drawn from real OpenStreetMap data.","client":null,"skills":["Arduino / C++","RP2040","U8g2","Mozzi","OpenStreetMap"],"role":["Game Designer","Programmer","Sound Designer"],"length":null,"thumbnail":{"childImageSharp":{"resize":{"src":"/static/f02be61ae7bd5160d81994748bf1310c/f3583/tau_dash_map.png","height":600,"width":1200},"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB90lEQVQozy2R3ev5YBjGb3mdjFlrzEM2no01DA8bIQc7mJeSlyxFkqTIqZzgwJGc+oe/+e13n911XXfX57phPp93u93tdgsAhJDj8bjZbGaz2W63y+fznU7nfD6v1+vlcnk+ny3LqlarhmGk02kAAE3TxuNxq9UCAJ7nTdOsVCqhUKjf7+u6TghxHKfdbmcyGU3ThsPhZrPp9XqZTOZnVhSlXq8TQnieBwCWZf9fBeA4rl6vI4Tc1ev1mqY5Go1qtZosy6IoAsbY5/MpimLbNsdx0WhUkiRXjRDied77bwCgVCqNx2NRFBmGIYSYpgmFQoFlWUVROI6jKAohVCwWAYCiKNu2W60Wy7KyLGOMO51Os9mMRqPJZLLb7f4CJhIJy7IajUY2m5UkqdlsLhaLWCxG07TjOJfLRVVVnudpmjYMw0UoFAqqqvr9fmAYRlXVQCAQiUTC4TDDMI7jGIZRKpVqtVoul0MISZKUy+Uwxvl8HmOcSqWKxSJFUUDT9A8dwOPxuKjhcFgQhHg8jjHmOM4ttVwui6JICAkGg65mOp3+3qPrutszwzAuNsYYITQYDNrtdiqVctMKgmAYhq7rgiDEYjHLsuB4PH4+n8lkcjqdns+nbduPx+P7/R4Oh+v1er/f3++3qqputNvttt/vV6vV6/XSNO0Pz3picZrVzwEAAAAASUVORK5CYII=","aspectRatio":2,"src":"/static/f02be61ae7bd5160d81994748bf1310c/a8378/tau_dash_map.png","srcSet":"/static/f02be61ae7bd5160d81994748bf1310c/c972b/tau_dash_map.png 340w,\n/static/f02be61ae7bd5160d81994748bf1310c/27625/tau_dash_map.png 680w,\n/static/f02be61ae7bd5160d81994748bf1310c/a8378/tau_dash_map.png 1024w","sizes":"(max-width: 1024px) 100vw, 1024px"}}}}}},"pageContext":{"slug":"/tau-dash/","prev":{"fields":{"slug":"/meme-stratum/"},"frontmatter":{"title":"Meme Stratum"}},"next":{"fields":{"slug":"/web3-dao/"},"frontmatter":{"title":"Web3 DAO Platform"}}}},
    "staticQueryHashes": ["63159454"]}