Introduction to hexagons, part 3 #

In part one, I described how I was making a new diagram for my hexagon grid guide, but that I didn't know how to evaluate the design choices I had to make. In part two, I described how I looked at the introductory section of the page to decide the purpose of the new diagram and how it fit in with the others.

Even more diagrams
Test page with many diagrams

Labels: , ,

Introduction to hexagons, part 2 #

In part one, I described how I created lots of variants of a diagram to try to figure out which one to use on my hexagon guide.

Lots more diagrams
Test page with many diagrams

Labels: , ,

Introduction to hexagons, part 1 #

When I started making interactive diagrams the hard part was making them interactive part. But over the years I've gotten much better at that. Now the problem is designing the diagrams. A few weeks ago I was looking at the beginning of my hexagons guide to see what I could improve. I noticed this paragraph had no corresponding diagram:

In math, the "circumradius" is the distance from the center to a corner (I call this size); the "inradius" is the distance from the center to the middle of an edge, sqrt(3/4)*size. The "maximal diameter" is twice the circumradius; the "minimal diameter" is twice the inradius. Wikipedia has more.

My first thought was to add a diagram for this. I already have a diagram about angles, so I could add a diagram showing the inradius and circumradius:

Angle diagram Radius diagram
Introductory diagrams

Labels: , ,

Connected Components #

Occasionally someone will ask me how to implement Connected Components, which is useful for several things, including

  • determining whether there's a path between two points; if there isn't, you can skip running pathfinding
  • finding the islands/continents on a procedurally generated map

It's actually a clever use of Breadth First Search. Every time the queue is empty, you find an unvisited node and put it into the queue, and then run the loop some more. When you have no more unvisited nodes, you're done.

Connected Components

Labels:

Little details #

Back in 2019 I started a page with a list of all the little things I do on my pages. One of the things I have a problem with is that I don't finish something, and then I don't share it, and then nobody benefits. I'm wanting to share more partial projects. So I shared that page, even though it wasn't finished.

Since then I've added sections about

  • coloring controls to match the diagrams
  • state machines
  • linkable sections
  • arrows in svg, canvas, and outside the container
  • two column layout
  • backwards compatibility
  • removing build steps
  • adding build steps
  • markup languages
  • topic-based vs time-based projects
  • pre-rendering
  • meta tags for social media
  • support for printing

https://www.redblobgames.com/making-of/little-things/

The page is uneven, with some sections being detailed and others being simple links to other pages I've written, but I am hoping it's useful for people writing explanations on the web. More importantly, I'm building it as a reference for myself. I'm adding code snippets there too, so that the next time I need a draggable svg, I can go to that page and grab the code, and also read about the gotchas that I might've forgotten to check.

Labels:

Hexagon conversions #

On my hexagon grid guide I have a function to convert pixel (cartesian) coordinates to hexagon "cube" coordinates. I reuse a hex_round() function that I needed for line drawing. However, there are many other algorithms out there that work differently. I had made a list on a separate page. But I hadn't actually implemented them … until now.

Labels:

Procedural tree generator #

I'm still a bit sad about Flash going away. Yes, I know lots of people hated it. But it was an amazing tool for creativity. One of the tiny fun projects I did was procedurally generating trees:

Set of procedurally generated trees
Procedurally generated trees

Upgrading my PRNG for procedural generation #

For a long time now I've been using a very simple Park-Miller LCG random number generator for my procedural generation projects. This is in part because back in the Flash days, Michael Baczynski's "polygonal.de" library was popular, and it had an implementation of Park-Miller. When I switched to Haxe, I used his Haxe data structures library. And then when I switched to Javascript, I used the Javascript port of polygonal's library, and then I wrote my own. I love how simple the core algorithm is.

However I know that it's not a great random number generator.

The original Flash version and the Javascript port both point to Robin Whittle's page about this algorithm, which explained that 16807 was the original multiplier used in this random number generator, but that "47271 or 69621" would be better. I ended up making my own code that used 47271. But I noticed today that the Wikipedia page says 48271 is better, so I'm wondering if 47271 is a typo. So I looked at the paper and indeed, 48271 and 69621 are listed. Not 47271. So for years now I've been using a multiplier based on a typo.

Doh!

Labels:

Improving island shaping for map generation, again #

Back in 2019 I rewrote the island section of my noise-based map generation page. I had high hopes for that rewrite. It was ok, but I was still quite unhappy with it. So I rewrote it again.

Island map generation: demo and main ideas

Labels:

Offline access with File / Save As #

One of my low priority goals for my site is to make my pages work offline. I had looked into "web manifests" but they seem more suited for web apps and not for documents like mine. So I looked at what it would take to make File→Save As work, preserving interactivity. It turns out it does not work in general on my site. Why?

I tried to make the original HTML + JavaScript should work offline in the sense that they only access resources on the current server and not from any CDN, Google Fonts, etc. So if you save the HTML + JavaScript it should work on a local web server. However, File→Save As doesn't work this way!

Diagram showing what happens when using Save As in the browser on an interactive page
Save As for an interactive page (diagram made with excalidraw)

Labels: