Wow loads of help. Thank you!

TLDR - I’ve solved it.

As @MarkusR suggested, I decided to try to use maths to solve the problem rather than relying on a special tile. The advantage is that I can change the tile dimensions in my graphics editor and don’t have to remember to create a new “mouse map” image.

I think the suggestion by @Eric_Williams would likely work and is smart. Thanks @JulianS for the explanation of what was going wrong.

For those that are interested in hex maps what I did, is as follows:

First the screen is internally carved up into `MouseCell`

s (drawn in red):

The coordinates in red at the top of the red cells are the “mouse map” (`row, column`

). The black coordinates in the centre of the hexes are actual in-world (`row, column`

) coordinates.

We can see from the picture that if we know the `row`

and `column`

of a `MouseCell`

we can compute the in-world tile index by adding a `delta`

value to the `MouseCell.Row`

and `MouseCell.Column`

. The delta to add depends which part of the `MouseCell`

the cursor is in:

First thing we need to do is convert the X,Y coordinates in the mouse map to local coordinates within a cell. We do this by using `Mod`

with either `column * cellWidth`

(for the `X`

) or `row * cellHeight`

(for `Y`

). Incidentally, `Mod`

is a great tool for wrapping a value into a range. Once we have X and Y for the cell (`localX`

and `localY`

) we can start determine which region of the cell that point is in.

Each `MouseCell`

can be thought of as a hexagon with four surrounding regions. We need to determine which area (1 to 4) each point in the cell is in. There are four triangles and two rectangles to check:

In order to check if our local point is within one of the triangles or lower rectangles, we need the vertices (points):

Fortunately the vertices are easy to compute:

```
Var v1 As New Point(cellWidth / 2, 0)
Var v2 As New Point(cellWidth, tileHeight * 0.25)
Var v3 As New Point(cellWidth, tileHeight * 0.75)
Var v4 As New Point(cellWidth / 2, tileHeight)
Var v5 As New Point(0, tileHeight * 0.75)
Var v6 As New Point(0, tileHeight * 0.25)
Var va As New Point(0, 0)
Var vb As New Point(cellWidth, 0)
Var vc As New Point(cellWidth, tileHeight)
Var vd As New Point(0, tileHeight)
```

Now we can loop through every point in the mouse cell and determine which region it is and, therefore, what the delta to apply is:

```
// Loop through every point within the mouse map cell and determine
// which region it's in.
For x As Integer = 0 To cellWidth - 1
For y As Integer = 0 To cellHeight - 1
Var p As New Point(x, y)
// We must check the triangles first, then the centre and then
// the rectangles.
If PointInTriangle(p, va, v1, v6) Then
// Top left triangle (4).
mMouseMap(x, y) = New Delta(-1, -1)
ElseIf PointInTriangle(p, v1, vb, v2) Then
// Top right triangle (1).
mMouseMap(x, y) = New Delta(-1, 0)
ElseIf PointInTriangle(p, v4, v3, vc) Then
// Bottom right triangle (2).
mMouseMap(x, y) = New Delta(1, 0)
ElseIf PointInTriangle(p, v4, v5, vd) Then
// Bottom left triangle (3).
mMouseMap(x, y) = New Delta(1, -1)
ElseIf y <= tileHeight Then
// Centre.
mMouseMap(x, y) = New Delta(0, 0)
ElseIf x <= cellWidth / 2 Then
// Bottom left rectangle (3).
mMouseMap(x, y) = New Delta(1, -1)
Else
// It's in the bottom right rectangle (2).
mMouseMap(x, y) = New Delta(1, 0)
End If
Next y
Next x
```

Before you ask, `mMouseMap()`

is a two dimensional array (`mMouseMap(localX, localY)`

) where the value of each element is the delta to apply for both the row and the column. This is stored in the class `Delta`

:

```
Class Delta
Property Row As Integer
Property Column As Integer
Sub Constructor(row As Integer, column As Integer)
Self.Row = row
Self.Column = column
End Sub
End Class
```

The `PointInTriangle`

method determines if a point is within a triangle by checking which side of the half-plane created by the edges the point is:

```
Function PointInTriangle() As Boolean
Var d1, d2, d3 As Double
Var has_neg, has_pos As Boolean
d1 = Sign(p, v1, v2)
d2 = Sign(p, v2, v3)
d3 = Sign(p, v3, v1)
has_neg = (d1 < 0) Or (d2 < 0) Or (d3 < 0)
has_pos = (d1 > 0) Or (d2 > 0) Or (d3 > 0)
Return Not (has_neg And has_pos)
End Function
```

The `Sign()`

function is a little helper:

```
Function Sign(p1 As Point, p2 As Point, p3 As Point) As Double
Return (p1.X - p3.X) * (p2.Y - p3.Y) - (p2.X - p3.X) * (p1.Y - p3.Y)
End Function
```

At this point, we now have an array that we can quickly look up a local mouse cell coordinate and get the delta to apply. I create the mouse map array once when the game loads and that saves loads of maths on every mouse move.