First, I want the learning experience of breaking down map compasses and figuring out how to generate them. This process helps me understand a lot about what makes something work and what doesn't, and hopefully also gives me insights into the creative process. Second, I want my compass generator to be based on a procedural grammar (as I did with map borders) so that it is easier to expand the generator to create new kinds of compasses. Third, I want to use this as an opportunity to share code and give some deeper insight into my development process.
As always when I'm tackling a new topic, I like to gather up some good examples from existing fantasy maps as a guide. I've collected the compasses from all my reference maps as well as from maps on the Cartographers' Guild and from Oleg's generator. (All of the examples are available in the code repository for you to peruse.) Like map borders, compasses are an artistic element and there are a wide variety of styles and approaches. I couldn't find any definitive guide to the parts of a compass rose, so I'll use my own (hopefully self-descriptive) terminology.
The simplest compasses are nothing more than an arrow and a letter:
The most complex are works of art:
Obviously these are beyond my capability to generate. However, there are a large number of compasses based upon “circles and arrows":
This style of compass has various sorts of arrows toward the different map directions (these are called compass points) and then various circular ornaments interleaved with the pointers. The parts of these style compasses are fairly simple, but can be combined in many ways to create a nice variety. For what I imagine are many of the same reasons, these are also the sorts of compasses Oleg's generator produces:
So let's talk about pointers.
The most common pointer by far is the kind of triangle/diamond shape seen above. It is often split into two halves with one half black and the other white, but entirely black and outlined white are common as well. Typically near the center of the compass it narrows back to a point to create a diamond shape, but this is often covered by a circle ornament, so it appears to be a triangle.
One variant of triangle style pointers is to make them wavy as in this example:
The arrangement of the pointers always includes the four cardinal directions (N/S/E/W). (Very occasionally a compass will have only a North pointer, but this is usually a very simple compass or a very artistic one.) The pointers for the cardinal directions are always the longest pointers in the compass. Other pointers are usually shorter than the cardinal pointers, but sometimes they're all the same length. Very occasionally the North pointer is longer than the other cardinal directions:
Or the North pointer may be distinguished with an ornament, such as a fleur de lis:
There can be many pointers between the cardinal pointers, but they're always symmetric. In some cases the finer pointers are just lines:
The pointers are often labeled with directions. Most commonly the cardinal directions are labeled, but sometimes the intercardinal directions (NE/SE/SW/NW) are labeled as well. Very occasionally even finer divisions are labeled:
There are a variety of different names for the compass points:
If the directions are labeled, they are (almost always) the outermost elements of the compass. They often stand alone, but are sometimes placed in a ring as in this example:
If a map contains windrose (or compass) lines, at least one set originates at the compass:
But these aren't properly part of the compass and I won't be concerned with generating them.
It's not unusual for a compass rose to be only pointers (as in the example immediately above) but they often include circular elements as well. So let's talk about circle elements.
One simple case is a circle or two set behind the pointers:
To start with, you should download the code repository by cloning the Git repository at “https://github.com/srt19170/Procedural-Map-Compasses.git" and selecting the “Part 1" branch. (Cloning a repository means making a new copy of the repository, usually on your own computer. The link above contains instructions if you don't know how to do this.) That should get you a folder that looks like approximately like this:
Also in the main folder I have included a simple Web server. I use Mongoose, and since that's a single file that doesn't require any installation, I will include it in the project code so that you don't have to download it separately. (I've included versions of Mongoose for Windows, MacOS and Linux, but as noted above, I've only tested these instructions on Windows. For Linux, you can also see this page for some alternate ways to run a web server. Remember that you need to run it in the directory with test.html!) Double-clicking on the Mongoose executable should open up a page in your Web browser that shows the current directory:
At this point, you can click on test.html to open that page, which should display a blank page with a Test button in the upper left:
Let's take a look at what is inside the test.html page:
<html lang="en"> <body> <div id="all" style="display: flex; flex-direction: row;"> <div id="controls" style="display: flex; flex-direction: column; flex: 0 0 30px"> <button id="testButton">Test</button> </div> <div id="map" style="margin-left:10px;"> <svg id="svg" width="500" height="500"> </svg> </div> </div> <script type="module"> import Compass from './compass.js'; var testButton = document.getElementById("testButton"); var svg = document.getElementById("svg"); testButton.onclick = function () { Compass.test(svg); }; </script> </body> </html>This is a stripped down vanilla web page. First it sets up some <div>s for controls and the map (really just a compass, but this is copied from Dragons Abound). The controls div contains a simple button labeled “Test." The map div contains an SVG element that will actually display the compass.
It also includes a <script> that does a couple of things. First the script loads the Compass module from the same folder as the web page. (Note that Dragons Abound uses ES6 module syntax; this should work in all modern browsers.) Second, the script attaches the “test" function from the Compass module to the onclick action of Test button. (This means that when you click the Test button, the “test" function will get executed. And eventually that function will draw a compass into the SVG element so that it will show up on the page.) The SVG element gets passed into the test function so that it will know where to draw the compass.
Now let's take a look inside the test.js file:
// // Top level file for Map Compass Procedural Generation // function test() { console.log('Well, at least we got this far.'); }; export default { test: test };There's not much here yet. The test() function is defined, but all it does is print a message to the console. Then test function is exported so that it can be used outside of the module.
To actually see the code work, you will have to open the browser console. To see the console in Chrome, you need to open the Developer Tools with CTRL + SHIFT + I or F12 and then hit the Escape key if the console is not showing. On Firefox you can open the console from the Web Developer sub-menu or by hitting CTRL + SHIFT + J. (Just different enough to be confusing!) On Chrome you'll see something like this on the left side of your browser window:
The console is the part at the bottom showing the two error messages. Your messages and layout might be different. There are many tutorials on the Web to help you understand and use the Web Developer tools in Chrome and Firefox, so please refer to those if you have further questions.
Meanwhile, try clicking on the Test button. The console should show the test message:
The “onclick()" function I attached to the test button in the HTML page is calling the test() function from the compass.js file. And that function is using console.log() to print a message to the console. The console is very handy for these sorts of debug messages and testing.
And as mentioned above, I'll also end each posting with “Suggestion to Explore" with some ideas on how you can expand or play with the ideas from the posting. (You'll see that below.) Next time I'll start on drawing a compass from a description.
Suggestions to Explore
- Test.html puts a 500x500 SVG element on the web page. How would you put a border around that element to make it easier to see?
- The test function prints a message to the console log. That requires having the console open. It would nice to be able to put a message on the web page. Modify the code so that test() returns a string and display that on the web page below the Test button.