Generation One Pokémon Procedural Building Generation

Generate nearly every Gen One Pokémon building by picking the right settings and dragging to the right size.

Generation One Pokémon Procedural Building Generation
Different buildings generated by the tool!

Welcome to my fun little project I got into as a vehicle to learn modern JavaScript. Here you'll find my inspiration, what I used, how I did it, and lessons learned. But before getting into the post, try it out here by clicking below:

Procedural Pokémon Building Generation
Generation one style Pokémon buildings.
Link to the building page.

The building updates live as you go:

Live updates as you manipulate the building.

And you have all sorts of options to choose from, or if you're feeling daring, a random button.

ECMAScript x Pokémon

I had always wanted to properly catch up on the newest JavaScript offerings since ECMAScript 2016 but I had somewhat missed it. With legacy work products needing to support IE or using jQuery there was little appetite for bringing in the new. Personally I was way too interested at the time with the new changes in .NET to invest a lot into JS.

Come 2021 and React.js became something I needed to learn. This uses a lot of newer features in vanilla JavaScript and it was high time I learned properly about them. So I dove into what became my favourite resource for JavaScript:

The Modern JavaScript Tutorial
Modern JavaScript Tutorial: simple, but detailed explanations with examples and tasks, including: closures, document and events, object oriented programming and more.

While learning modern JavaScript was the goal, a sub goal was to play with the Canvas. It turns out the raw Canvas isn't fun to use, so fabric.js came in to ease some of the roughness.

I had what I wanted to learn, but I needed the extra motivation. Of course, coming off my 2021 Living Dex project, Pokémon was a great idea. Procedural work also fascinated me and I had already made some okay-ish attempts:

We can then mix in when I started to look at what made an early Pokémon game feel that way. Part 3 of that series, Looking At Pixels Part 3: Let's Look at Each Building Type in Gen 1 Pokémon, made me think I could merge all this together to make buildings. So that's what I did.

Development

The development itself was fun learning things like the spread syntax, proxy, private functions with #, but in terms of actual interesting parts, here's some quickfire points:

  • Originally I just wanted to generate a single building, but as I went on I realised I could probably write something that made each building. A lot of time was spent understanding the patterns of each building to extract some rules for the settings. All but a small few of the original Gen 1 buildings can be generated with this tool - and a whole lot of weird non-existing ones too.
  • Everything I searched in order to understand new JS, I had to set my search results to be from 2017 or later.
  • From start to "finish" it took around three months, with a couple of big development spurts but otherwise mostly trickling check ins just slightly chipping away.
  • Doing the maths for positioning things is fiddly.
  • I brought in FlexBoxGrid to handle the responsiveness.
  • Fabric.js was easily a better way to deal with the canvas except for when touch came into play. I really wanted this to work on touch devices but it turns out you have to compile the library with an outdated touch script that I didn't find very extensible and in the end made a change to.
  • I really enjoyed using a proxy to propagate state changes throughout the app. When a user picks a different setting, or resizes the building, the state changes and calls back anything that had subscribed to it.
  • Is there stuff I would've done differently? Lots. It's not pretty at all with dead code, needless if statements, untidy sprite code, and other points I'm sure you'd pick up on if you browsed the repo. The feeling I had was just to push it out there and deal with fixes later.
    However, I'm happy to have something that isn't perfect - either I can come back and have a fun refactoring session, or I can look back in the future to see how far I'd come.

The Building Code and Unicode Compression

With the points out of the way, I want to draw some attention to this neat little part:

The generated building code.

While debugging, I needed a way to get back to a specific building state quickly. I originally had a JSON object of all the state properties which worked fine, but what if I allowed the user to also save state? I couldn't have a long string because no normal user would want that for something so small.

{
	"settings": {
		"x": 192,
		"y": 96,
		"height": 12,
		"width": 13,
		"door": 1,
		"hasWindowGap": false,
		"cladding": 1,
		"decoration": 1,
		"roof": 0,
		"windows": 2,
		"bottomRowWindows": 1,
		"doorPosition": 0
	}
}
JSON representation of the state.

I could then mash those all as a single number with padded x/y values and bools as ints and run a some sort of compression over it (which I originally did) - however that wasn't short enough.

Ultimately the answer came in the form of Unicode. Short, fun enough to look at, and each (seemingly single width) character can encode a fair amount of data.

Here is the rough state encoder I used. Essentially reducing portions of the state to numbers, merging them together and using String.fromCharCode() to get a Unicode character. The offset at the top both puts us in the range of more fun Unicode characters and away from the many empty spaces in the character table.

#offset = 9728;

encode(state) {
	const encodedXY = `${String.fromCharCode(state.x + this.#offset)}${String.fromCharCode(state.y + this.#offset)}`
	const encodedSize = `${String.fromCharCode(state.width + this.#offset)}${String.fromCharCode(state.height + this.#offset)}`

	const windowSettings = `${+state.windows}${+state.hasWindowGap}${+state.bottomRowWindows}`;
	const encodedWindowSettings = String.fromCharCode(+windowSettings + this.#offset);

	const otherSettings = `${+state.door}${+state.cladding}${+state.decoration}${+state.roof}${+state.doorPosition}`
	const encodedSettings = String.fromCharCode(+otherSettings + this.#offset);

	const encodedState = `${encodedXY}${encodedSize}${encodedWindowSettings}${encodedSettings}`;

	return encodedState;
}

I thought this was a neat compression tactic!

Learnings

  • New ECMAScript features
  • GitHub Pages
  • GitHub Projects
  • Fabric.js
  • Spritesheets
  • Very simple state container
  • How to setup metadata images and text https://metatags.io/
  • VSCode settings.json
  • VSCode extension: Live Server
  • VSCode extension: Gitlens

To Conclude

The little project technically isn't finished yet. As of writing this there are still a couple of things to do on the to-do board, but it's functional enough to present. Getting it to that level of function was really fun and I really enjoyed using Pokémon as an excuse to learn something new. Perhaps I should do that more often...

If you made it this far, thank you and I hope you enjoyed this project of mine. Feel free to check it out, it's all on GitHub: https://github.com/nikouu/procedural-pokemon-buildings