<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Pikon Devlog]]></title><description><![CDATA[Pikon Devlog]]></description><link>https://pikon-world.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 23 Oct 2026 02:05:59 GMT</lastBuildDate><atom:link href="https://pikon-world.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[From Dart polygons to a stone wall: a Pikon World development note]]></title><description><![CDATA[How Pikon World reuses clipped Voronoi polygons for 3D terrain, picking and stone wall construction with Flutter Scene.]]></description><link>https://pikon-world.hashnode.dev/from-dart-polygons-to-a-stone-wall-a-pikon-world-development-note</link><guid isPermaLink="true">https://pikon-world.hashnode.dev/from-dart-polygons-to-a-stone-wall-a-pikon-world-development-note</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><dc:creator><![CDATA[jbjrwww]]></dc:creator><pubDate>Mon, 12 Oct 2026 13:22:48 GMT</pubDate><content:encoded><![CDATA[<p>I'm developing Pikon World, a 3D archipelago for my Flutter strategy game, using flutter_scene and Flutter GPU. Pikon itself is already available on iOS and Android; the world shown here is under development.</p>
<h2>The scene in 30 seconds</h2>
<p><a href="https://www.youtube.com/watch?v=E56hZT_j4Ps">Watch the 30-second Pikon World demo</a></p>
<p>The demo shows boats, a storm, territory conquest feedback and a stone wall being built. It uses a local development fixture.</p>
<h2>One polygon model, several uses</h2>
<p>Each island has 24 clipped Voronoi territories. The Dart model creates a seeded set of sites using farthest-point sampling, then clips the island's convex coastline against the half-planes between each pair of sites.</p>
<p>For sites A and B, the boundary is their perpendicular bisector:</p>
<pre><code class="language-text">normal = B - A
limit = (B dot B - A dot A) / 2
keep P where P dot normal &lt;= limit
</code></pre>
<p>The clipping helper computes the signed distance to that boundary. This is the edge-intersection part from the current Dart implementation:</p>
<pre><code class="language-dart">final a = polygon[i], b = polygon[(i + 1) % polygon.length];
final da = side(a), db = side(b);
if (da &lt;= 1e-10) result.add(a);
if ((da &lt; -1e-10 &amp;&amp; db &gt; 1e-10) ||
    (da &gt; 1e-10 &amp;&amp; db &lt; -1e-10)) {
  final t = da / (da - db);
  result.add(LandPoint(
    a.x + (b.x - a.x) * t,
    a.y + (b.y - a.y) * t,
  ));
}
</code></pre>
<p>Here <code>side(P)</code> is <code>P.x * normal.x + P.y * normal.y - limit</code>. The small tolerance handles points close to the clipping plane. This implementation assumes a convex island footprint.</p>
<p>The scene reuses these territory polygons for the land surfaces, picking and the fortification perimeter. A fortification change can therefore animate construction along the same boundary that defines the territory. Keeping these uses on one model makes it easier to keep visual boundaries and interaction aligned.</p>
<h2>Working on the world independently</h2>
<p>The world lives in its own package with an example app, so scene behavior can be developed independently of account and multiplayer state. Mobile rendering also has its own quality policy: an initial memory-based preset, followed by quality reductions when frame pacing drops.</p>
<p>I'd be interested in how other Dart developers share geometry between rendering, picking and construction animation.</p>
<h2>Try Pikon</h2>
<ul>
<li><a href="https://apps.apple.com/app/id6804834624">iOS — App Store</a></li>
<li><a href="https://play.google.com/store/apps/details?id=com.jbonjour.pikon">Android — Google Play</a></li>
</ul>
<p>Disclosure: this development note was drafted by an AI assistant from the project's current implementation.</p>
]]></content:encoded></item></channel></rss>