• Dear Cerberus X User!

    As we prepare to transition the forum ownership from Mike to Phil (TripleHead GmbH), we need your explicit consent to transfer your user data in accordance with our amended Terms and Rules in order to be compliant with data protection laws.

    Important: If you accept the amended Terms and Rules, you agree to the transfer of your user data to the future forum owner!

    Please read the new Terms and Rules below, check the box to agree, and click "Accept" to continue enjoying your Cerberus X Forum experience. The deadline for consent is April 5, 2024.

    Do not accept the amended Terms and Rules if you do not wish your personal data to be transferred to the future forum owner!

    Accepting ensures:

    - Continued access to your account with a short break for the actual transfer.

    - Retention of your data under the same terms.

    Without consent:

    - You don't have further access to your forum user account.

    - Your account and personal data will be deleted after April 5, 2024.

    - Public posts remain, but usernames indicating real identity will be anonymized. If you disagree with a fictitious name you have the option to contact us so we can find a name that is acceptable to you.

    We hope to keep you in our community and see you on the forum soon!

    All the best

    Your Cerberus X Team

Snippet Hexagonal cell drawing

Ryan2003

New member
Tutorial Author
Joined
Jul 12, 2020
Messages
28
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:
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

1596299608666.png
 
Nice!!! I will definitely have some use for this. Thank you!
 
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:
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 answer:Vec2 = New Vec2
        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
        
        Return answer
    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
 
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.
hex.gif
 

Attachments

  • hexagonal_pathfinding.zip
    6.3 KB · Views: 136
Last edited:
Pathfinding now works for both flat top and pointy top hexagons.

You can draw filled or outlined hexagons.
Or not draw anything at all.

Prior release had only two types of cells.
They were either walkable or non-walkable.
In this release, a cell can have any value assigned to it.
This allows for different cells to have different 'costs' to travel on them.
For example, you might assign increasing travel cost to cells like so,
stone = 0
grass = 1
water = 100
snow = 200
mountains = 1000

So, all cells are walkable, the A* (star) pathfinding routine will
find the route from the starting point to the destination point
with the lowest travel 'cost'.

Added more comments.
Organized the code better.
 

Attachments

  • hexagonal_pathfinding_v2.zip
    8.2 KB · Views: 100
Added the ability to find a hexes neighbors at a given range.
Might be good for Fog of War (FoW).
hex_neighbors.gif
 

Attachments

  • hex_neighbors.zip
    10.9 KB · Views: 96
Back
Top Bottom