It's time for my annual self review. In last year's review I said I didn't have clear goals for 2023, and I would probably just do whatever was interesting. I did a bunch of interesting things. Unlike last year, I didn't spend much time on art or science. The first part of the year I was learning about drag & drop on the web. Then I worked on map generation. and the last part of the year were productive, but I felt kind of aimless in the middle.

Diagram showing how I make interactive diagrams

New pages

I wrote only two full articles, each taking over a month to write. Both are for the small audience of people making interactive tutorials. Neither is for the large audience of people making games.

  1. Many years ago I wrote my interactive tutorials with d3.js. I now use vue.js for some of them. In 2018 I had written a page that showed how I used d3.js to make my line-drawing page. This year I wrote a page showing how I used vue.js to make the circle-drawing page. It's an interactive tutorial about making interactive tutorials.
  2. While writing the making-of circle-drawing page, I realized I had been "cargo culting" the mouse event handling code. In particular, I had been using preventDefault() and stopPropagation() all the time, instead of using them because I had a specific need for them. I decided to take a week to learn this, and discovered it was a deep rabbit hole that took months to figure out! I wrote up my recommendations.

In writing the "making of" circle-drawing page, I discovered several places where I could improve the circle-drawing page. And in writing the "making of" event-handling page, I discovered lots of things I could improve on my existing pages, including making them more consistent and more mobile-friendly. I'm very happy with both of these projects.

While learning about event handling, I made various test pages (one, two, three), and the scenarios got increasingly more ridiculous as I went on:

  • what if you drag to move an object but the page uses drag to scroll
  • what if you switch to another window in the middle of dragging
  • what if you drag an object while you've selected text, which is also draggable
  • what happens if you rotate your phone while dragging
  • what if you drag with one finger but then use two other fingers to pinch to zoom
  • what happens if you hold down the left mouse button, then the right, then let go of the left
  • what if you plug in two mice and start dragging with the first but let go with the second
  • what if you set up an ipad as a second screen on a mac and you use the stylus to drag from the ipad to the mac screen
  • what if you start a drag operation and put the computer to sleep in the middle

Event handling is tricky! I didn't try to solve all of these problems, but I tried to handle common cases.

Diagram showing how the event handler and state handlers are related

I really like the way I designed the event handling code. In popular libraries like jquery-ui and react-draggable, the library gives you a set of features to choose from, such as a drag handle, snap to grid, and constrain position to a rectangle. But what if I want to snap to a hex grid, or constrain to a non-rectangle? I'm out of luck. In my projects, the event handler is decoupled from a state handler, which can implement any of those features, and a lot more. I'm working on an examples page to show the kinds of things I do with it. I had hoped it would be ready by now but I keep thinking of more examples to add to it.

I think both of these pages may be useful to a wider audience of web developers. For example, the second article was used to improve touch events on ClickHouse. I didn't have that audience in mind when writing these pages but it's something I'll consider for future pages.

Updating pages

I treat my site like a personal wiki. I publish new pages, but I also go back and improve old pages. I don't consider them "final". I continue to update pages I wrote nearly 30 years ago. So this year is no different — I've made improvements to existing pages.

The biggest project was mapgen4. Towards the end of that project, I felt like I never wanted to see the code again. It took me a few years before I wanted to work on it again. Last year I switched the code from JavaScript to TypeScript. This year I changed changed the internal naming convention at the suggestion of Tom Forsyth. I'm much happier with the new naming.

Screenshot of Delaunay triangulation with a double border

Updating the code reminded me that there was an unsolved problem I had hidden under the edges. The map edges were jagged! They weren't even consistently jagged. They looked awful. My "fix" back in 2018 was to slightly zoom in on the map so that you couldn't see the edges. That fix works. But it's unsatisfying.

I went back and investigated. I found several bugs and fixed them. I wrote up the results. I was very happy to have finally fixed this!

Screenshot of mapgen4 showing how the edges are straight and also show the underground areas

Working on the edges reminded me of a feature I wanted but couldn't implement because of the jagged edges: showing the sides of the map to make it look 3 dimensional. I implemented that and loved how it looks! Nobody will see it because the default map view is top-down, but I'm very happy to have it there.

On the noise-based map generation article, I added sliders to the sample code. Instead of seeing a number you want to change, scrolling down, finding the corresponding slider, moving it, and then scrolling back up to see the map, you can change the number in place and see the map at the same time.

At the suggestion of a reader, I updated my hexagon coloring page with a rock-paper-scissors rule showing which hexes "beat" adjacent hexes. I added a sector restriction option to my circle drawing page. I added an explanation of the Layout class for my hexagon library. There were many other changes too small to list here.

Experiments

A few years ago I had fallen into a perfectionism trap. My hexagon and A* pages were so polished that starting a new page felt daunting. I couldn't live up to my expectations. I had to give myself permission to make incomplete, unpolished pages. That's been a great success. Most of my work now starts out as unpolished pages that are just for myself and not intended for sharing. Some of them I end up sharing.

Screenshot of possible flying paths between hex edges

Most of the experiments are incomplete but that's ok. A sample:

Learning

Screenshot showing everywhere two Bresenham implementations differ

After many years of encouraging lerp instead of Bresenham's Line Algorithm, I decided I should test the properties of these algorithms. To my great disappointment, lerp wasn't always a winner. To my great surprise, there doesn't seem to be a single canonical "Bresenham's Line Algorithm" implementation, and the many implementations I found differ in their results. I have a page where I'm testing the implementations but I haven't written up the results yet.

A reader sent in an idea for storing hexagon-shaped maps in rhombuses, and I tried it out. Neat idea, but I haven't had a chance to use it in a real project. A reader sent in an idea for making irregular rectangular room maps, and I tried it out. It's simpler and easier than any other algorithm I've seen for making this style of map, and I ended up using it later in a game project.

I continued learning browser technologies, including web components, the drag-and-drop API, Vue dynamic templates, CSS grid, import maps, oklab colors, and Petite Vue.

I've spent time with local large language models (LLMs), especially finding Simon Willison's blog to be helpful, and also following reddit r/LocalLLaMA. Mostly I'm doing this out of curiosity. I've tried and failed to do some useful things, like building an index to ask questions of my notes, calculating which of my pages are most similar to each other, and code completion. Next I want to try llamafile with emacs integration.

Games

Diagram showing how game objects might be related to each other

Last year I had attempted to make a Dwarf Fortress clone in a week. I failed. This year I decided I needed a much smaller scope for the summer r/roguelikedev event. I made a colony simulator that had a procedurally generated rooms instead of build-your-own-rooms like other colony simulators. I made a lot of progress and wrote up the results. I was happy with the technical aspects of the project, but didn't get a game design I liked.

While working on that project I realized some of the data structures were error prone, and I decided I would draw on relational databases to design something simpler. It's not ECS, but it's related. I wrote a blog post about it.

I tried once again to make a spaceship flyer game but once again I lost motivation. I may have to accept that this is one of those projects where I want to have done it but I don't want actually do it.

Site management

Many people have noticed that search engines and social media aren't as useful as they once were. In the old days of the web, everyone shared links to the good stuff, because you couldn't find it on search engines. We don't have enough people linking anymore. My game programming site started out as a link sharing site. I linked to the articles I found useful for my projects. I now have over 4000 links from my site.

Over time, a lot of these links have broken.

  1. For links from my pages to the outside world: I've integrated gradual link checking into my web site build process. It's no longer something separate that I have to remember to run. The UI is terrible but I'm slowly working on that.
  2. For links to my pages from the outside world: I try to maintain forwarding links forever. I wrote up some of what I do to keep links working.

One of my goals for 2024 is to figure out how to make site management easier, both in terms of link checking and also in terms of page organization/searching.

For search engines, I've started using Kagi. I love the idea behind Teclis: crawl a page with and without an ad blocker, and remove pages that are full of ads. I also love the idea behind Marginalia: focus on discovering non-commercial pages.

For social media, I read Twitter, HN, Reddit, StackOverflow, but I don't post often anymore. I am active on my blog and Discord. I'm not on Mastodon or BlueSky or Threads. I don't want to switch from Twitter to another social network. I want to switch to my own site. One of my goals for 2024 is to figure out how to move my Blogspot blog to my own site.

For project tracking, I had moved away from Trello when Atlassian bought them. I switched to Notion, but now Notion has become frustrating. I want to share links to my project pages like this but sometimes (inconsistently) Notion will require a login. A lot of sites are doing this now (including Twitter and Reddit), and it discourages me from posting on those sites. One of my goals for 2024 is to move my project tracking to my own site.

I am still optimistic about the web. I think the good parts of the web are still there. Instead of using ad blockers to spend time & attention on the parts of the web I don't like, I want to spend my effort to find and share the parts of the web I do like. I visit random IndieWeb sites to discover new gems. I link to things I find interesting. I think this is how we take back the web: not by spending our energy hating, but by finding and celebrating things to love.

I wish everyone a good 2024!

Labels:

0 comments: