<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Get Info: #particles</title>
    <description>Posts tagged “particles” — Blog of independent game and app developer Matt Sephton. Featuring vintage Macintosh, game development, digital artwork, Japanese esoterica, video game reviews, hacks and tips, and much more.</description>
    <link>https://blog.gingerbeardman.com/tag/particles/</link>
    <atom:link href="https://blog.gingerbeardman.com/tag/particles/index.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 30 Jun 2026 01:15:23 +0000</pubDate>
    <lastBuildDate>Tue, 30 Jun 2026 01:15:23 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>

    
      
        <item>
          <title>Easter egg emoji: converting pixels into particles</title>
          <description>&lt;p&gt;I’m &lt;a href=&quot;/2019/08/14/moai-games/&quot;&gt;fascinated with Moai&lt;/a&gt; so I always try to squeeze an appearance into my games. Moai in video games is a meme, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Easter_egg_(media)&quot;&gt;easter egg&lt;/a&gt;, going all the way back to 1983. But my game YOYOZO (&lt;a href=&quot;https://play.date/games/yoyozo/&quot;&gt;out now for the Playdate handheld&lt;/a&gt;) is about capturing stars in space using a yoyo, so how could I get a Moai in it?&lt;/p&gt;

&lt;p&gt;The source of my inspiration was a trip to Japan back in 2004 (my only one, so far). Visiting in August meant that one of the things we did was go to an &lt;a href=&quot;https://www.japan-guide.com/e/e2267.html&quot;&gt;annual hanabi fireworks festival&lt;/a&gt;, where I saw &lt;a href=&quot;https://blog.gaijinpot.com/four-types-of-japanese-fireworks/&quot;&gt;katamono&lt;/a&gt; for the first time. These are fireworks that explode in the shapes of drawings, like a smiley face or a magic 8-ball. I was amazed and the experience has stuck with me for over 20 years. Maybe I could add Moai into YOYOZO by making the explosions appear like the katamono?&lt;/p&gt;

&lt;p&gt;I started off by coding the patterns by hand, as a test, but my calculations weren’t precise enough and the whole endeavour quickly grew too complicated to manage by hand. I needed a better, more automated way. The method that I arrived at is what I’ll document in this post.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;pixels-as-code&quot;&gt;Pixels as code&lt;/h2&gt;

&lt;p&gt;Instead of plotting values by hand in code I figured that it would make more sense if I could draw the patterns and then somehow convert them into coordinates. I use &lt;a href=&quot;/2023/05/10/piskel-for-playdate/&quot;&gt;Piskel&lt;/a&gt; as my Playdate-centric graphics editor. It’s a really useful tool. So I drew a few emoji-like patterns, keeping in mind that they would be converted into a cluster of points and exploded from an origin. This took a bit of experimentation but I ended up with a sort of already exploded look.&lt;/p&gt;

&lt;p class=&quot;screen&quot;&gt;&lt;img src=&quot;https://cdn.gingerbeardman.com/images/posts/yoyozo-emoji.png#pixel&quot; alt=&quot;EMOJI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To get the pixel data out of Piskel in text form I make use of its “export as a C file” feature. This results in code definitions similar to the below. (I use a script that does some simple regex search/replace to reformat these definitions to be a little more succinct and readable in my Lua code.)&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define EMOJI-TABLE-11-11_FRAME_COUNT 3
#define EMOJI-TABLE-11-11_FRAME_WIDTH 11
#define EMOJI-TABLE-11-11_FRAME_HEIGHT 11
&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* Piskel data for &quot;emoji-table-11-11&quot; */&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emoji&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;121&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;pixels-as-points&quot;&gt;Pixels as points&lt;/h2&gt;

&lt;p&gt;With this data in hand, my plan was to convert them into points expressed as an angle and distance from an origin. This way of expressing points is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Polar_coordinate_system&quot;&gt;polar coordinate system&lt;/a&gt; so there was no need to invent anything, I just needed to code a function that would take a grid of pixels expressed as &lt;em&gt;(x, y)&lt;/em&gt; and convert them to a series of distances and angles expressed as &lt;em&gt;(r, θ)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The way I do this is to read the point data in from a grid of pixels, offsetting that data by half the width and height of the &lt;em&gt;odd-sized&lt;/em&gt; grid so that the centre of the grid &lt;em&gt;(0, 0)&lt;/em&gt; is the middle of the centre pixel. And finally I convert those adjusted &lt;em&gt;(x, y)&lt;/em&gt; values to polar &lt;em&gt;(r, θ)&lt;/em&gt; coordinates. This worked really well!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Below is a work-in-progress GIF captured on 14 September 2023, shortly after getting the feature working. This animation also shows an early version of the HUD and debug values for ball size and the length of the beam.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.gingerbeardman.com/images/posts/yoyozo-emoji.gif#playdate&quot; alt=&quot;EMOJI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The finishing touches (not shown in the above animation) were to add some small amount of &lt;em&gt;pseudo-randomisation&lt;/em&gt; to the initial rotation of the emoji, the initial “colour” of each particle, and changing the coordinates of each point slightly so they appear more organic and move at slightly different speeds. I eventually settled on over a dozen such pixel patterns in the game (how many have you spotted?). Once your score is higher than 50M points every explosion is an emoji! &lt;a href=&quot;https://play.date/games/yoyozo/#gameListingMoreInfo&quot;&gt;Check out the game manual&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;pseudo-random&quot;&gt;Pseudo-random?&lt;/h2&gt;

&lt;p&gt;I try to limit my use math.random values if I can help it, or at least use it in controlled way. I already use that for the positions of the stars, so if I also used it for explosions that would mean it would become far less controlled. Controlling the use of random is important in making a game system deterministic, if you want it to react the same way every time.&lt;/p&gt;

&lt;p&gt;If you’re wondering how you can get pseudo-random values, the main method I use is a trick I learned from the old arcade game &lt;a href=&quot;/2011/10/26/flicky-1984/&quot;&gt;Flicky (1984, SEGA)&lt;/a&gt; which is a game &lt;a href=&quot;https://www.flicky1984.com/post/709058873877790720/just-a-quick-reminder-that-you-can-play-my-flicky&quot;&gt;I own as a physical cabinet&lt;/a&gt;. Anyway, in Flicky there is a diamond that appears under seemingly random conditions.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;One of the MAME programmers was kind enough &lt;a href=&quot;https://www.flicky1984.com/post/54534135892/the-best-jewel-thief-in-the-world&quot;&gt;reverse engineer Flicky on my behalf and figured out what makes the diamond appear&lt;/a&gt;. It turns out the diamond will appear only if you knock out an enemy cat and it disappears outside of the centre third of the play area &lt;em&gt;and&lt;/em&gt; if the x coordinate at which the cat finally comes to rest is even. So, about 50% chance &lt;em&gt;but&lt;/em&gt; only if you position the screen correctly during play.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, taking a cue from that wonderful Flicky logic, I use modulus—which returns the remainder of a division—as my main mechanism of generating pseudo-random values. It ensures a value in the range &lt;em&gt;[0,n-1]&lt;/em&gt;. They key thing to note is that if you base it on values in your game system that are constantly changing you can get seemingly random values that have the benefit of being deterministic if the player is skilled enough at repeating their inputs. The deterministic thing is how pretty much all the old school arcade games operated from Pac-Man to Flicky and more.&lt;/p&gt;

&lt;p&gt;Common game variables I use are: game tick (my alternative to timer), x-coordinate, y-coordinate, speed, angle, or combinations of more than one of these. I also used this approach in YOYOZO for the starfield particles, and in &lt;a href=&quot;/2023/04/13/sparrow-solitaire-for-playdate/&quot;&gt;Sparrow Solitaire&lt;/a&gt; for the falling particles that make up the &lt;a href=&quot;https://www.reddit.com/r/PlaydateConsole/comments/12vcrm6/dynamic_weather_effects_and_more_in_the_sparrow/&quot;&gt;weather effects&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;playdate-particles&quot;&gt;Playdate particles&lt;/h2&gt;

&lt;p&gt;There are &lt;a href=&quot;https://github.com/PossiblyAxolotl/pdParticles&quot;&gt;one or more libraries&lt;/a&gt; available that can be used to manage particles in a performant way on Playdate. Though I tend to code my own system that is bespoke to the game I’m working on at the time (I start each game from a blank file and use minimal libraries, force of habit). But the important thing for such limited platforms, especially when using Lua, is to use a pool of particles so that you’re not constantly creating and destroying particles which would wreak havoc on performance through overuse of Lua’a garbage collector.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;further-reading&quot;&gt;Further reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2023/11/21/yoyozo-how-i-made-a-playdate-game-in-39kb/&quot;&gt;&lt;em&gt;YOYOZO&lt;/em&gt; (or, how I made a Playdate game in 39KiB)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2023/12/09/dynamic-music-and-sound-techniques-for-video-games/&quot;&gt;Dynamic music and sound techniques for video games&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.date/games/yoyozo/#gameListingMoreInfo&quot;&gt;&lt;em&gt;YOYOZO&lt;/em&gt; manual/player’s guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
          <author>by Matt Sephton</author>
          <pubDate>Sun, 26 Nov 2023 20:41:00 +0000</pubDate>
          <link>https://blog.gingerbeardman.com/2023/11/26/easter-egg-emoji-converting-pixels-into-particles/</link>
          <guid isPermaLink="true">https://blog.gingerbeardman.com/2023/11/26/easter-egg-emoji-converting-pixels-into-particles/</guid>
        </item>
      
    

  </channel>
</rss>
