---
title: Stop Coding and Start Drawing
teaser: When you're stuck, the best solution is often to represent the problem in
  a different medium.
tags: elm,gamedev,web
author: Joël Quenneville
published_on: 2018-04-04
---

The [Elm] `#gamedev` community on [Slack] has started having monthly [game
jams]. That sounded fun so I built a [pirate-themed tower defense game] for the
[February jam].

This being my first real foray into gamedev, I got stuck on multiple occasions.
Figuring out how to properly do the coordinate math was particularly
frustrating. Normally when I'm stuck on a big problem, I try to break it down
into smaller sub-problems. I was still stuck, so I stopped coding and tried to
represent my problems visually.

[Elm]: http://elm-lang.org/
[Slack]: https://elmlang.herokuapp.com/
[game jams]: http://elmgames.club/
[pirate-themed tower defense game]: https://github.com/JoelQ/safe-tea
[February jam]: https://itch.io/jam/elm-game-jam-feb-2018

## Coordinate systems and vector math

_A quick aside on vectors. Any point in a coordinate system can be described as
a combination of direction and distance from `(0,0)`. These "vectors" are
usually drawn as arrows on a graph. They can be added, and subtracted by drawing
them head to tail. Check out this [vector tutorial] to learn more._

![problem solving with vectors](https://images.thoughtbot.com/master/uspTrVMQdylbvb982vhZ_vectors.png)

I had some path-finding logic that generated a series of waypoints, giving me a
path that safely navigated around the islands to get from a pirates current
position to the target destination.

The hard work is done right? Now all I need to do is to keep moving the pirate
to the next point in the path. Turns out it isn't quite so simple. Consider the
following scenario:

1. I have a pirate at point `A`
2. The pirate is moving towards point `B`
3. The pirate is not moving fast enough to reach `B` in this tick
4. The pirate can only move `distance` _towards_ `B` this tick.

The question is "Where is the pirate at the end of the tick?".

After drawing out the initial two vectors `A` and `B`, I realized that
travelling the full distance between both points was equal to `A - B`. What I
really wanted was a vector `C` whose _direction_ was the same as `A - B`, but
whose _magnitude_ was `distance`.

Now I'd managed to calculate this value before. However once I drew it, I
realized that `C` alone pointed to an obviously wrong position. What I really
wanted was `A + C`. Problem solved!

## Neighboring tiles

Another problem I ran into was finding out which map tiles were adjacent to each
other. I allowed movement in 8 directions: up, down, right, left, and
diagonally. Thus, most tiles have 8 neighbors. However, edge and corner tiles
have fewer because the map does not wrap around. Which neighbors does each kind
of tile have?

Time to go to the drawing board!

![neighbors for each class of tile](https://images.thoughtbot.com/master/4UkbO1MDR8uNKabfXMYT_edge-neighbors-all.png)

Turns out there are 9 possible scenarios for neighbors:

* 4 corners, each with 3 different neighbors
* 4 non-corner edges, each with 5 different neighbors
* All other tiles who have the full 8 neighbors

Based on this information I was able to [naively calculate a tile's neighbors].

[vector tutorial]: https://mathinsight.org/vector_introduction
[naively calculate a tile's neighbors]: https://github.com/JoelQ/safe-tea/blob/c46e5547aa4a292f9f265211150b02236960c643/Map.elm#L173-L269

## Maps and tile systems

I used [Tiled] to turn [this image] into a tile set. I built a map out of those
tiles which Tiled exported as a list of tile ids. I modeled my `Map` type in a
similar fashion, each layer (water, land) was stored as a list of tiles.

```elm
type alias Map =
    { land : List Tile
    , sea : List Tile
    , width : Int
    , sheet : TileSheet
    }
```

As long as I know the width (in tiles) of the map, I can then use math to
position any tile. It turns out the math is really simple. Given a tiles
position in the list (`tileNumber`) and the `mapWidth` in tiles, X and Y
positions can be found via modulo (`%`) and integer division (`//`)
respectively.

* `x = tileNumber % mapWidth`
* `y = tileNumber // mapWidth`

To convert those numbers into pixels, just multiply by the side of a tile (in
pixels). In my case, 64.

However, my math wasn't _quite_ right. I was having to add or subtract 1,
seemingly arbitrarily, in various calculations to get things to show up in the
right place on the screen.

Again I was stuck. So I stopped coding and started drawing.

![one-based-map](https://images.thoughtbot.com/jq-building-a-game-in-elm/j5c5HFrRnCMWRYttaMNw_one-based-map-tiles.png)

Looking at the (X, Y) pairs, I noticed some weird patterns:

1. In each row, the X values went 1, 2, 0
2. In each column, the Y values went 0, 1, 2
3. In the last column, the Y values went 1, 2, 3

Something was off. I played around with the formula for finding X and Y and
eventually found that subtracting 1 from the initial tile number before doing
the divide or modulo operation gave me much more reasonable coordinates.
Hmmmm... 💡💡💡 then the lightbulbs turn on! My list of tile numbers starts at 1.
If I subtract 1 from all those numbers, I'd get a zero-based list. I start
drawing again

![zero-based-map](https://images.thoughtbot.com/jq-building-a-game-in-elm/LLmN225aTHVZ7BPt28Vo_zero-based-map-tiles.png)

Look at the symmetry! Now positions go from (0,0) to (2,2). X and Y values stay
consistent within a given row or column. I make a few changes in the game and
now the math works out perfectly without needing to mess around with offsets.
Zero-based indexing FTW!

[Tiled]: http://www.mapeditor.org/
[this image]: http://kenney.nl/assets/pirate-pack

## Conclusion

When you're stuck on a programming problem, the best way to get unstuck is often
to try to express the problem in a different medium. Even just switching from
coding a problem to verbally explaining can be a huge help, hence the imfamous
[rubber duck debugging] technique.

Using a visual medium can yield even better results. This can be via good
old-fashioned paper and pencil or in some digital drawing tool. I often use
[draw.io]. The key thing is that you are representing your problem visually
instead of in code structures.

So the next time you get stuck, move away from that editor, stop coding and
start drawing!

[rubber duck debugging]: https://rubberduckdebugging.com/
[draw.io]: https://www.draw.io/
