<aside> 💡 js13k is 30-day competition to create a browser game in 13kb of code or less. I am documenting my project here and on twitter.

</aside>

Related Posts

Pt 1: Theme Announcement & Project Setup

Pt 2: Writing a 3D Engine (after trying not to)

Pt 3: Using Bitmap Caching to Unlock 60fps in 3 Dimensions

As a challenge to myself this year, I wanted to make a game that uses an axonometric projection to achieve an engaging top-down effect. As a consolation for making this reckless decision, I convinced myself that if I did it right, I could make simple conversions from "map space" to "screen space", and just run each point through a formula or two, switching back from a true top-down view, to an angled one, with ease.

Nine Parchments has a great top-down game style that works wonders for its combat and immersive environment

Nine Parchments has a great top-down game style that works wonders for its combat and immersive environment

The Shortcut

This works pretty well up to a point. I started off by converting my square tiles to an axonometric projection and was indeed deceived by how simple it was. I could avoid 3D entirely and simply use these formulas to achieve the effect below:

// <http://clintbellanger.net/articles/isometric_math/>
map.x = screen.x / TILE_WIDTH + screen.y / TILE_HEIGHT;
map.y = screen.y / TILE_HEIGHT - screen.x / TILE_WIDTH;

http://clintbellanger.net/articles/isometric_math/

http://clintbellanger.net/articles/isometric_math/

The issue is that I don't just want to make a map. I want put stuff on it. And that stuff has a 3rd dimension. So when I started trying to place cubes on my map I got frustrated when they wouldn't abide by the simple math I had been using to place tiles.

Of course, the math was only simple because I was using a single rotation of a 2d object, and then approximating a second rotation by using a shortcut that states that the width of a square becomes twice the height of a square in certain axonometric projections.

// drawing a square isn't so hard
drawLines([
  new Vector3(0, 0),
  new Vector3(500, 0),
  new Vector3(500, 500),
  new Vector3(0, 500),
  new Vector3(0, 0)
]);
/*
thinking I'm a genius because 
I found a isometric projection 
shortcut and these numbers made 
sense in my head
*/ 
drawLines([
  new Vector3(0, 250),
  new Vector3(500, 0),
  new Vector3(1000, 250),
  new Vector3(500, 500),
  new Vector3(0, 250)
]);

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f7d31434-7abd-4b2b-b4a9-bbcee1e550ed/Untitled.png

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c0e77d56-8787-4b5b-b1e4-03b8ab0cda7f/Untitled.png

But what about a cube? Would I be able to find a simple conversion to account for the z coordinate as well? What about the character I wanted to draw? And the environment and game objects?

The short story is no, there's a reason we use proper math to describe rotations, and it took me a while to figure that out. If I had the space I could draw and pre-render all of my art and assets to fit the isometric style, but I don't have the space given that the game must be done in 13k. As such, it seemed that counter-intuitively, the most concise way to achieve was I was after was to build a basic camera and 3D renderer from scratch.

Proper Projections