<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom"
>
  <channel>
    <title>Made in Bugs - Blog</title>
    <link>https://www.madeinbugs.com.br/en/blog</link>
    <description>Technical articles about game development by Made in Bugs studio.</description>
    <language>en</language>
    <lastBuildDate>Thu, 28 May 2026 12:32:11 GMT</lastBuildDate>
    <atom:link href="https://www.madeinbugs.com.br/en/blog/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title><![CDATA[Polaroid Awards]]></title>
      <link>https://www.madeinbugs.com.br/en/blog/polaroid-awards</link>
      <guid isPermaLink="true">https://www.madeinbugs.com.br/en/blog/polaroid-awards</guid>
      <description><![CDATA[How we built a photography system integrated into games for festivals]]></description>
      <content:encoded><![CDATA[<h2>15 minutes 🕑</h2>
<p>We found out that&#39;s the average time a player spends with our game during a festival. So, <em>how do you turn 15 minutes of gameplay into something lasting?</em></p>
<p>I was asking myself this a few days before <em>Fórum Eaí Jogos</em>, which took place in late April. <a href="https://www.madeinbugs.com.br/en/projects/asumi">Asumi: Little Ones</a> is a <em>photography</em> game, so it was obvious to me: The <strong>photos</strong> are lasting.</p>
<p>Players always want to <strong>show off their best shots</strong>, right? But when you&#39;re at an in-person event, <em>how do you let a player share their photos with friends?</em> You can&#39;t ask everyone to bring a USB drive!</p>
<p>The answer came in an unprecedented and complex format — a <strong>photography competition</strong> integrated into the game.</p>
<p><img src="/assets/blog/polaroid-awards/polaroids.png" alt="Screenshot of the in-game camera while photographing an animal"></p>
<h3>The flow</h3>
<ol>
<li>Player plays the demo at the festival booth</li>
<li>During the session, they take photos with the in-game camera</li>
<li>Photos automatically go to a <strong>dedicated website</strong> and the <strong>community Discord</strong></li>
<li>Other people vote on the best photos</li>
<li>We announce winners weeks later, creating prolonged engagement</li>
</ol>
<hr>
<h2>Requirements ✅</h2>
<p>We knew a few things were necessary:</p>
<ul>
<li><strong>Zero friction for the player</strong>: photos upload by themselves, no login required</li>
<li><strong>Anonymity</strong>: each player gets a 5-letter code (<code>BAKOM</code>, <code>TIRUP</code>) instead of a real name</li>
<li><strong>Offline resilience</strong>: the system must work even if the event&#39;s internet is unstable or nonexistent (<strong>This was super important!</strong>)</li>
<li><strong>Public voting</strong>: people who didn&#39;t attend the event can vote on photos via the website</li>
</ul>
<hr>
<h2>⚙ The architecture ⚙</h2>
<p>The stack: <strong>Unity Engine</strong> (our game lives there lol), <strong>Supabase</strong> (database), <strong>Next.js + Vercel</strong>, a Discord bot, <strong>Brevo</strong> for personalized emails, and, of course, players to take photos.</p>
<p><img src="/assets/blog/polaroid-awards/diagrama.png" alt="Architecture diagram"></p>
<h3>Database</h3>
<p>We created an online database with three tables.</p>
<ul>
<li><strong><code>contest_sessions</code></strong> — one row per player, indexed by the 5-letter code</li>
<li><strong><code>contest_pictures</code></strong> — one row per photo, with photo metadata (visible animal species, time of day, camera mode)</li>
<li><strong><code>contest_votes</code></strong> — anonymous votes linked to a fingerprint</li>
</ul>
<h3>Offline queue</h3>
<p>The most critical component on the Unity side is the <code>ContestUploader</code> — a persistent on-disk queue inspired by message brokers. When the player takes a photo, it&#39;s saved locally and enqueued in a JSON file. An async loop attempts to send in 4 sequential stages (PNG upload, DB insert, Discord post, done). Each stage is idempotent — if the game crashes between stage 1 and 2, on relaunch it resumes exactly where it left off.</p>
<p>Confused? 😫 TL;DR: <strong>If the internet fails, the system retries</strong>. After 5 consecutive failures, the item goes to a <code>dead letter queue</code>, which is a technical name for a queue of failed items. This means the machine can be offline for hours — or entire days — without losing a single photo. On reconnection, everything uploads automatically.</p>
<p>In practice, this allowed us to operate at events <strong>completely without internet</strong> (I&#39;m looking at you, <strong>Gamescom Latam</strong> 🙄).</p>
<hr>
<h2>The website 🌐</h2>
<p>Photos go through two pages:</p>
<div class="blog-columns">
<div><h3><a href="https://www.madeinbugs.com.br/en/picture-contest">Player page</a></h3>
<p>The player enters their 5-letter code and sees all session photos in polaroid format. They can <strong>choose a favorite photo</strong> to officially enter the competition.</p>
<br>
<br>
<br><h3><a href="https://www.madeinbugs.com.br/en/picture-contest/voting">Public voting</a></h3>
<p>Shows all the best photos in a grid. <em>Anyone can vote without logging in</em> — identification via anonymous fingerprint 🤓.</p>
</div><p><img src="/assets/blog/polaroid-awards/site.png" alt="Website"></p>
</div><hr>
<h2><a href="https://discord.gg/YX9aDaYwnx">Discord</a> and emails 📩</h2>
<p>On Discord, a simple bot counts all ⭐ votes on player photos. It serves as a voting channel parallel to the website.</p>
<p>For player communication, we use <strong>Brevo</strong> to send personalized emails with a direct link to each person&#39;s page. When the booth operates offline, the email-to-code matching is done by temporal correlation — the Forms timestamp matches the session&#39;s <code>created_at</code> within 1-2 minutes in the natural flow.</p>
<hr>
<h2>It&#39;s Not All Sunshine and Rainbows + What We Learned 🌹</h2>
<p>Events are hostile environments for network-dependent software. Internet drops, hotspots die, firewalls block. Even working offline, <em>one of the Gamescom booths unfortunately couldn&#39;t participate in the competition</em> 😢</p>
<p>Still, we&#39;re very happy with everyone who managed to participate 💖</p>
<p><strong>165 photos were taken</strong>, from <strong>more than 15 players</strong>. We never expected this level of participation from a game so new on the market.</p>
<p><video src="/assets/blog/polaroid-awards/demo.mp4" autoplay loop muted playsinline></video></p>
<hr>
<p>There&#39;s so much more I could talk about here, <em>like the anti-spam and anti-bot tools, the voting grid randomization system, and the unique password generator</em>, but this is the heart of the system.</p>
<p>The Polaroid Awards lives on in our community (and in the polaroids we mailed out).</p>
<blockquote>
<p>📢 <strong>Want to participate?</strong> There&#39;s still time to vote until <strong>May 31st</strong>!
<a href="https://go.madeinbugs.com.br/blog-vote">Vote here</a></p>
</blockquote>
<p>If you&#39;re thinking about doing something similarly wild for your game, I hope this post serves as both a map and a warning about the bumps in the road.</p>
]]></content:encoded>
      <pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate>
      <author>Andress Martin</author>
      <category>engineering</category>
      <category>events</category>
      <category>asumi</category>
      <enclosure url="https://www.madeinbugs.com.br/assets/blog/polaroid-awards/polaroids.png" type="image/png" />
    </item>
  </channel>
</rss>