# Hexagonal cell drawing

#### Ryan2003

##### New Member
Tutorial Author
Hi,

Here is code which will draw hexagonal cells and report which cell the mouse cursor is hovering over.
(ported from some FreeBasic code)

Cerberus X:
``````Import mojo

Class cHex    ' Class for one hexagonal cell

' pre-calc these recurring values
Field cos000:float = Cos(0)
Field sin000:float = Sin(0)
Field cos060:float = Cos(60)
Field sin060:float = Sin(60)
Field cos120:float = Cos(120)
Field sin120:float = Sin(120)
Field cos180:float = Cos(180)
Field sin180:float = Sin(180)
Field cos240:float = Cos(240)
Field sin240:float = Sin(240)
Field cos300:float = Cos(300)
Field sin300:float = Sin(300)
Field cos030:float = Cos(30)

Field size:Int

Method New(_size:Int)
Self.size = _size
End

Method GetSize:Int()
Return Self.size
End

Method DrawHex(x:Int, y:Int)    ' draw the hex cell at cell location x,y

Local h2:float = size / 2
Local s:float = size / cos030 / 2
Local tx:float = x * s * 1.5
Local ty:float = y * size + (x Mod 2) * h2

h2 = h2 * 1.16

DrawLine(tx + cos000 * h2, ty + sin000 * h2, tx + cos060 * h2, ty + sin060 * h2)
DrawLine(tx + cos060 * h2, ty + sin060 * h2, tx + cos120 * h2, ty + sin120 * h2)
DrawLine(tx + cos120 * h2, ty + sin120 * h2, tx + cos180 * h2, ty + sin180 * h2)
DrawLine(tx + cos180 * h2, ty + sin180 * h2, tx + cos240 * h2, ty + sin240 * h2)
DrawLine(tx + cos240 * h2, ty + sin240 * h2, tx + cos300 * h2, ty + sin300 * h2)
DrawLine(tx + cos300 * h2, ty + sin300 * h2, tx + cos000 * h2, ty + sin000 * h2)

End Method

End ' Class cHex

Global myHex:cHex

Class MyGame Extends App

Method OnCreate()
SetUpdateRate(60)
myHex = New cHex(64)    ' create a new hex cell of size 64
End Method
Method OnUpdate()

End Method
Method OnRender()
Cls 0,0,0
SetColor 255, 255, 255

' draw a hex map of x by y cells
For Local x:Int = 0 To 6
For Local y:Int = 0 To 6
myHex.DrawHex(x, y)
Next
Next

' Below determines which hex cell the mouse cursor is over
Local mx:Int = MouseX()
Local my:Int = MouseY()

Local s:Float = myHex.GetSize() / Cos(30) / 2
Local arrayx:float = Round(mx / s / 1.5)
Local arrayy:float = Round( (my - (arrayx Mod 2) * myHex.GetSize() / 2) / myHex.GetSize())

SetColor 255, 0, 0
myHex.DrawHex(arrayx, arrayy)

Print(string(arrayx) + "  " + string(arrayy))

'    DrawText("Move the mouse across the window.", 10, 10)

End Method
End Class

Function Main()
New MyGame()
End Function

Function Round:Int(value:Float)
Return (value + 0.5)
End``````

#### MikeHart

Nice!!! I will definitely have some use for this. Thank you!

#### Ryan2003

##### New Member
Tutorial Author
The code has been updated to be more OOP-like.
And now you have the choice of either Flat-top hexagons (like above) or Pointy top hexagons.
(Mods, sorry if this should have been in the Snippets area, please move if it is better there)
Cerberus X:
``````Import mojo

Class Vec2
Field x:Float
Field y:Float
End Class

Class cHexcell    ' Class for one hexagonal cell

' pre-calc these recurring values
Field cos000:float = Cos(0)
Field sin000:float = Sin(0)
Field cos060:float = Cos(60)
Field sin060:float = Sin(60)
Field cos120:float = Cos(120)
Field sin120:float = Sin(120)
Field cos180:float = Cos(180)
Field sin180:float = Sin(180)
Field cos240:float = Cos(240)
Field sin240:float = Sin(240)
Field cos300:float = Cos(300)
Field sin300:float = Sin(300)
Field cos030:float = Cos(30)

Field size:Int

Method New(_size:Int)
Self.size = _size
End
' a hex cell can have a pointy top
Method DrawPointy(x:Int, y:Int)    ' draw the hex cell at cell location x,y

Local h2:float = size / 2
Local s:float = size / cos030 / 2
Local ty:float = x * s * 1.5
Local tx:float = y * size + (x Mod 2) * h2

h2 = h2 * 1.15

DrawLine(tx + sin000 * h2, ty + cos000 * h2, tx + sin060 * h2, ty + cos060 * h2)
DrawLine(tx + sin060 * h2, ty + cos060 * h2, tx + sin120 * h2, ty + cos120 * h2)
DrawLine(tx + sin120 * h2, ty + cos120 * h2, tx + sin180 * h2, ty + cos180 * h2)
DrawLine(tx + sin180 * h2, ty + cos180 * h2, tx + sin240 * h2, ty + cos240 * h2)
DrawLine(tx + sin240 * h2, ty + cos240 * h2, tx + sin300 * h2, ty + cos300 * h2)
DrawLine(tx + sin300 * h2, ty + cos300 * h2, tx + sin000 * h2, ty + cos000 * h2)

End Method

' a hex cell can have a flat top
Method DrawFlat(x:Int, y:Int)    ' draw the hex cell at cell location x,y

Local h2:float = size / 2
Local s:float = size / cos030 / 2
Local tx:float = x * s * 1.5
Local ty:float = y * size + (x Mod 2) * h2

h2 = h2 * 1.15

DrawLine(tx + cos000 * h2, ty + sin000 * h2, tx + cos060 * h2, ty + sin060 * h2)
DrawLine(tx + cos060 * h2, ty + sin060 * h2, tx + cos120 * h2, ty + sin120 * h2)
DrawLine(tx + cos120 * h2, ty + sin120 * h2, tx + cos180 * h2, ty + sin180 * h2)
DrawLine(tx + cos180 * h2, ty + sin180 * h2, tx + cos240 * h2, ty + sin240 * h2)
DrawLine(tx + cos240 * h2, ty + sin240 * h2, tx + cos300 * h2, ty + sin300 * h2)
DrawLine(tx + cos300 * h2, ty + sin300 * h2, tx + cos000 * h2, ty + sin000 * h2)

End Method

End Class    'cHexcell

Class cHexmap

Field sizex:Int
Field sizey:Int
Field cellsize:Int
Field cellstyle:Int

Field myHexcell:cHexcell

Method New(sizex:Int, sizey:Int, style:Int = 0)
Self.sizex = sizex
Self.sizey = sizey
Self.cellstyle = style
End Method

Method Draw()
' draw a hex map of x by y cells
myHexcell = New cHexcell(cellsize)    ' create a new hex cell of size cellsize
For Local x:Int = 0 To sizex
For Local y:Int = 0 To sizey
If cellstyle = 0 Then
myHexcell.DrawPointy(y, x)
Else
myHexcell.DrawFlat(x, y)
End If
Next
Next

End

' converts a screen point x,y in pixels to a hexcell x,y location
Method Pointtocell:Vec2(mx:Int, my:Int)

Local s:Float = myHexcell.size / myHexcell.cos030 / 2

If cellstyle = 0 Then
'Pointy top hexcell
answer.y = Round(my / s / 1.5)
answer.x = Round( (mx - (answer.y Mod 2) * myHexcell.size / 2) / myHexcell.size)

Else
'Flat top hexcell
answer.x = Round(mx / s / 1.5)
answer.y = Round( (my - (answer.x Mod 2) * myHexcell.size / 2) / myHexcell.size)
End If

End

Method Drawcell(x:Int, y:Int)
If cellstyle = 0 Then
myHexcell.DrawPointy(y, x)
Else
myHexcell.DrawFlat(x, y)
End If
End

End Class    ' cHexmap

' Test program
Class MyGame Extends App

Field ptc:Vec2
Field myHexmap:cHexmap

Method OnCreate()
SetUpdateRate(60)
myHexmap = New cHexmap(6, 3)    ' set the size of the map(rows, columns)
myHexmap.cellsize = 64            ' set the size of each hex cell
'uncomment below for flat top hex cells
'myHexmap.cellstyle = 1
End Method
Method OnUpdate()

End Method
Method OnRender()
Cls 0,0,0
SetColor 255, 255, 255

myHexmap.Draw()

' determine which hex cell the mouse cursor is over
ptc = myHexmap.Pointtocell(MouseX(), MouseY())

' Highlight the hexcell that then mouse is over
SetColor 255, 0, 0
myHexmap.Drawcell(ptc.x, ptc.y)

DrawText(string(ptc.x) + "  " + string(ptc.y), 10, 10)

End Method
End Class    'app

Function Main()
New MyGame()
End Function

Function Round:Int(value:Float)
Return (value + 0.5)
End``````

#### Ryan2003

##### New Member
Tutorial Author
Here I have added Astar pathfinding.
I re-used the hexagonal Astar code that Xaron had posted in the Monkey forums.
The pathfinding seems to work fine.
I am not happy with the look of the code.
I ended up using a global variable and the findPath function really should be part of the Path class.
Maybe some kind soul here could clean up the code for me.
Code is in the attached .zip file.
Note: Pathfinding only works with the pointy top hexes right now.

#### Attachments

• 6.3 KB Views: 7
Last edited: