REmapper

Initial development post for remapper, my RedEclipse Map generation algorithm

Date
Repo hexylena/remapper
Post as of github.com/hexylena/remapper@182257f6cb5916b02c60
Tags gamedev,mapgen

Redeclipse has a nice octree based world and it’s an alright FPS platform. The F/OSS nature and octree world makes it ideal for hacking and experiments.

Initial Hacks

It took a long time to reverse engineer the format. I am not good with C.

Perlin Noise

Some initial experiments here started with very minecraft-y worlds. These were easy to create.

minecraft themed map

As coverage of the map formant increased and I gained the ability to spawn entities into the game, more exciting maps developed:

snowy forest

This had the unfortunate problem that since it was a voxel world you made quantized changes in height that were very visually unpleasant. Unable to create slopes, continual changes in height were impossible.

Daggerfall

Plenty of reading on r/proceduralgeneration led to finding this blog post and then this one The first blog post had accompanying source code and a really awesome demo (youtube) but I did not spend much time investigating this.

Eventually I built a map using the same principles. It was incredibly basic, lacking even stairs. Hackily implemented pushers were the only way to change elevation (the red blocks could be jumped up if you missed the pusher)

Lighting

Shortly thereafter I experimented with lighting. The original impetus for developing redeclipse maps was playing sniper-counter-sniper in old halo 2 maps, but wanting to play a similar game mode online. Our favourite map was Halo 2’s Colossus. This head the nice aspect for colour that changes across the map. Note the green in the center, yellow on right, blue on left.

Naturally I implemented this abomination.

And eventually tempered my excitement into something less excessive

This was getting to the point of mostly playable.

Three Dimensions

Most of the maps up until here were relatively flat. Once lighting was done, I tried to add verticality since that was an aspect that was particularly enjoyable in sniper-counter-sniper.

I also produced “night” versions of a map without the sunlight

After Effects

I built a number of new pieces and experimented with different probabilities of spawning various rooms.

This included some “digital” rooms which featured a function/position based “decay”

Additionally I included some “after effects”, i.e. functions run on a map after it was otherwise completely baked. One of these was to apply a simple grid outline effect which proved to be visually quite nice and gave the option of hopping around even where one wasn’t supposed to go.

A better view of the grid

Texturing

Around this time I decided I needed better texturing than the default ones I’d been using. I was quite fond of the stairs.

And the digital rooms now looked extremely nice.

The digital room was 2x the usual height because I implemented “random options” for each room, random flags that could be toggled in different instances of a single room. They had the additional restriction that only one of the random flags could change for two rooms that were connected.

Some more new rooms were added as well, all aimed at giving the competitors more cover during combat but still leaving them exposed enough for excitement.

There was even a short-lived experiment on railings along walkways using trigonometric functions.

Texturing, Again

Next, a configurable texturing engine was implemented allowing for easily applying different “themes”, e.g. a “default” theme or a “paper” theme. The default theme is pictured in all of the pervious images. The paper theme:

A not-so-easy to see “minecraft” theme

The somewhat visually painful “primary” theme with RGB/White/Black. It actually looks quite good with shades of grey and red, but no screenshots exist of that.

This was pretty cool but never fully utilized. It was nice to be able to say “these textures can be used for walls” and “these for accent colours”. It really simplified the texturing process. Sometimes there were fun mistakes with the texturing process / generation of the configuration files:

Vectors

At this point in time, the largest pain point was that defining rooms was horribly unpleasant. Every room had to be defined four times, one for each and every possible orientation of the pre-fabricated room. A large rewrite occurred to replace the original “construction kit” with one that was aware of the parent room’s orientation and could reproduce it correctly in any orientation. This provided the impetus for the primary colour theme in order to visualise the output maps easily.

Many tests were conducted with a tool to write out a simple map and a single room facing in each direction.

But map baking has always been incredibly slow and unpleasant. It’s bearable if you know you’ll like the outcome or are young and naïve and excited about possibilities. But if you’re doing rigorous testing, it’s miserable. So I switched to writing unit tests. Vectors and vector math was implemented to simplify all of the horrible bugs that were in my hacks and math. This basically fixed all of the bugs and progress could go on again.

MagicaVoxel

I decided that the map output was painfully slow and that running redeclipse was making my lap too hot. I searched out other voxel viewers and found that magicavoxel had an incredibly simple binary format that I could write. This was really super cool and cut down on compile times immensely. I could serialize the test formats essentially instananeously

This led to much, much faster iteration times and let me finish up the vector feature quickly.

Naturally, realising how simple it was to write the format, I set out to read the format. I wrote a Kaitai struct definition for the format to easily parse it. It only handles relatively simple .vox files which are output by my tool of choice, goxel, but it works well enough.

This meant that I could convert magicavoxel definitions essentially directly into remapper library calls. This wasn’t a great implementation, but hey, it was cool! I could draw a room in goxel, and turn it into a redeclipse room. The approach used literally wrote out python code and I manually merged it into my library. Horrifying.

If you checked out the goxel project, you may have seen a city on their home page. I realised I could use their city generator, write it to a file, and then convert it into a pretty unpleasant-to-play redeclipse map.

The next extension was to go back to the daggerfall room generation, and start loading magicavoxel rooms into the map