Showing posts with label mapgen4. Show all posts
Showing posts with label mapgen4. Show all posts

Improving Mapgen4's boundaries, part 3 #

In the last post I described how I investigated and fixed several bugs in mapgen4's boundary points and rendering. I was a bit annoyed at myself because I didn't initially follow great practices while debugging, so it took longer than it should have. But I was also glad I found and fixed the bugs.

One reason I wanted to try a double boundary layer was that I thought it might be neat to "fold" the edges downwards a bit, so that when you look at the map from the side, it'd have some depth. So I tried it, and … it worked! And it was so easy (after I fixed the earlier bugs). I then changed the underground color and added a faint line at the fold:

Underground view

Labels: , ,

Improving Mapgen4's boundaries, part 2 #

Last time I mentioned that I made some changes to my dual-mesh helper library. I use it for my Delaunay/Voronoi map and art projects. Part of the motivation was that I want to work on some new map projects, and wanted to fix some of the issues with the library. I then realized I need to test out the changes in mapgen4.

I made a list of mapgen4 bugs I wanted to fix. The main one I'm going to talk about here is that the edges of the map are jagged. Why didn't anyone notice? Because I set the default zoom level to be slightly zoomed in, so that you don't see the edges!

Map edges are quite jagged

Labels: , , ,

Improving Mapgen4's boundaries, part 1 #

I've been wanting to refamiliarize myself with the mapgen4 code because I'd like to do some new map projects and will want to reuse some of the code from my existing projects.

The first thing I decided to work on was my dual-mesh library. I had originally written it to be a generally useful wrapper around Delaunator. Since then, I wrote the Delaunator Guide, which has all the same functions, but in a way that you can adapt to your own needs. I also realized that by making this library public, I was making it harder for my own needs. So version 3 of this library is going to be primarily for my own needs.

Boundary points (blue) surrounding Poisson Disc points (red)

Labels: , , , ,

Mapgen4: finished #

Not with a bang but a whimper

Back in July, I started mapgen4, the successor to mapgen2, my Voronoi-polygon map generator from 2010. Back in August I posted that I had planned to finish the map generator “in a month”, and then write a tutorial.

That was three months ago.

Labels: ,

Mapgen4: beta #

I put mapgen4 on hold a few weeks ago because I was having some seemingly random unreproducible freezes, where it would still calculate the map updates but it wouldn't draw them. I had tried everything (or so I thought), gotten frustrated, and taken a break. I often find that I need to take a break from something, and then when I get back to it, I figure out the problem. During this break I've been "productively procrastinating", working on several other things that I've wanted to do, including map generation on a sphere, a procedural face generator, improving touch support on many of my pages, and improving my tower defense pathfinding page. I ended up also experimenting with a better interface for my mouse-drag code, a recursive renderer in Vue.js, and a D3 + Vue.js experiment in which Vue keeps track of dependencies for D3.

Mapgen4's style takes inspiration from hand drawn fantasy maps

Labels:

Mapgen4: river representation #

I've reached the point in mapgen4 development when I just want it to be over. So I'm cutting all remaining features and am focusing on finishing. Most of the remaining work isn't interesting enough to blog about so I'm going to describe the river representation I started using last year. It's worked very well for the needs of this project. Take a look at the rivers in this screenshot:

Rivers are binary trees

Labels: , ,

Mapgen4: outlines #

Usually when I make a map generator I focus on the underlying algorithms and data. The data will be used by a game project, so the visuals are meant to be informative and not necessarily pretty. For this project I wanted to make the output pretty. I previously blogged about the unusual projection I'm using for the graphics. It allows you to see the rivers and coastlines top-down but see the mountains from the side. There are two other interesting graphical tricks I'm using to make the maps prettier.

Non-photorealistic shading

Labels: , ,

Mapgen4: bug fixes #

The past week has been troubleshooting. The biggest problem was water pouring out of my house's electrical panel, but that's not what this blog post is about. I've been working on bugs in the map generator. There are some bugs I've been putting off because I didn't understand them.

The first problem was that rivers haven't been reaching the ocean. This has been a problem for a while, but I didn't want to fix it until I stopped changing the algorithm. I'm mostly happy with the river algorithm now so I decided to investigate. One thing that the Game AI Summit at GDC emphasizes is building debug visualizations; I'm a fan of that technique and tried it here:

Debugging coastal and river triangles

Labels: , ,

Mapgen4: oblique projection #

One of my goals for mapgen4 was to explore non-realistic approaches, both to map generation and to map rendering. I wanted to explain the unusual projection I'm using.

For procedurally generated wilderness maps, it's very common to see a top-down view, often using colors to represent height or biomes:

Top-down view

It's simple to implement, especially in 2D, and it shows the areas of the map, including coastlines and rivers and lakes. You can see where the mountains are, but only because of the color and lighting.

Labels: , , ,

Mapgen4: rainfall #

Last time I rewrote elevation painting. The next thing I wanted to work on was biomes. I'm not actually even sure I need them, but I wanted to try a variant of an approach I had tried in the 1990s and again in 2009:

Rain cycle

Labels: , ,

Mapgen4: elevation painting, revisited #

A few weeks ago I described elevation painting for mapgen4. The idea was to let the user paint areas for mountains, valleys, and oceans, and then use distance fields to interpolate between the areas. After some user testing, I decided to abandon this approach.

When I originally implemented it, I painted mountains and valleys on a minimap. On the main map, I used distance fields to transition between the mountain and valley areas.

Elevation constraints (red and green), and resulting elevation

Labels: , ,

Mapgen4: river appearance #

Earlier this week I moved all the heavy computation into its own thread. The rest of the week I wanted to work on rivers. The last time I worked on rivers, I replaced the slow CPU-based renderer with a fast GPU-based renderer. However, the output was ugly:

Jagged rivers from my previous river renderer
Jagged rivers

Labels: , , ,

Mapgen4: threads #

Today I am making mapgen4 multithreaded. I'm trying to blog more often, so I'm putting my notes here instead of keeping them to myself.

Multithreaded Javascript? Yes, with Web Workers. I've known about these for a while but I've never used them until now. The basics:

  • Web Workers are more like separate processes rather than threads. They have their own memory. Some browsers support shared memory but it's not something I can count on right now. Introduction and reference.
  • Workers can communicate by sending a message to another worker. The message is a data-only object (no functions or resources). Details.
  • You can also transfer data to another worker, if it's a contiguous array. This is particularly useful for large arrays of numbers such as WebGL data or, in my case, mapgen4 data including the Voronoi mesh. It avoids a copy.

I find that I learn best by reading a little bit and then playing with something. So I decided to make a simple worker and try it out.

Labels: ,

Mapgen4: elevation painting #

Last week I described the plan for elevation in mapgen4. The goal was to allow painting mountains, valleys, and oceans on the map. I used a jittered grid to pick positions for mountain peaks, and then implemented three distance fields:

  1. Distance from closest mountain peak. I use this to create distinct mountains instead of noise-based continuous mountains.
  2. Distance from coastline. On the ocean side, I use this to make shallow water near the coast. On the land side, I use this to keep mountains away from coasts. (not sure I should)
  3. Distance from mountain ranges. I use this to make a gradual drop from mountains to valleys.

I continued optimizing. The main map regeneration is now around 400ms for the one-time initialization and 120ms to regenerate the map while painting. I implemented a simple paint interface, with small/medium/large brushes and ocean/valley/mountain tools. It works on touch devices too, and it feels pretty good on a tablet.

Example painted map
Map painting

Labels: , ,

Mapgen4: elevation #

Last week I posted about mapgen4, the procedural map generation project I'm working on this summer. I had been trying to limit the scope of the project, and also shifting my thinking from maps for a game to maps that look pretty. I've been spending a lot of time optimizing and restructuring the code for this. It occurred to me that I'm approaching elevation all wrong.

Labels: , , ,

Mapgen4: goals #

I've been posting on Twitter but was reminded that I should be posting more to my blog. I don't want Twitter to be the only place to read about what I'm doing.

Screenshot of a procedurally generated map

Back in 2010 I had written an influential article about map generation, making maps specifically designed for one game. I made a Flash demo called mapgen2. At the time I didn't emphasize enough how each of the layers of the process could be different. Many people took the recipe as the way to do it, even though the recipe was specifically for the needs of that one game. In mapgen2 the rivers depended on elevation which depended on coastlines. But it could've been coastlines depended on elevation which depended on rivers. There are lots of different ways to glue the pieces together. In 2017, I wanted to go back and try a different recipe with the same ingredients (Voronoi, elevation, rivers, biomes, etc.). For a while I thought the new project, mapgen4, will do all the things! I experimented with lots of things but the task seemed overwhelming. I decided to step back and limit my scope. I rebuilt the same algorithms with the new framework (HTML5, and more efficient data structures), and launched that as an HTML5 version of mapgen2. Then I put everything on hold.

Labels: , , ,