I've been looking all over the web to find a way to create a line between two hexes in an hex grid. The only working implementations i found are unpracticale for me giving the coordinate system they use.
I work with a 2d array, and i offset every Odd column by half my hex's height.
So my array looks like this:

Now i've tried several approaches and all of them fail at some point.
here are the approaches i tried:
1) Shortest distance
Start from Source Hex.
Compare the graphical distance between each of the adjacent hex and the Destination Hex.
Move to the Hex with the smallest distance.
Loop until i reach Destination Hex.
This works in a way that it will find the shortest path between both hexs (in terms of number of hexes), but it doesnt give a nice 'straight' line.
An example of a bad result it gives is this:
(Green = Start, Blue = End, Red = Path)

but this is what i want (a straighter looking line)

2) Moving along a line
I use the X,Y coords of my Array (not the graphical representation)
I change Y so Y = Y * 2 + (X mod 2)
so basicaly, it means that my Y value is in steps of 2, and every odd column is shifted by one
So Hex(2,2) is in fact (2,4)
and hex (3,1) is in fact (3,3)
This way i take into account the shifting on the graphical representation of the array
Now, i find out which is bigger: The differencebetween Source X and Destination X or Source Y and Dest Y.
So lets say i want to go from (2,2) to (7,6) (which translates to 7,13)
DistX = 7-2 = 5
DistY = 13-2 = 11
So DistY > DistX
Now, i move along my X axies by increments of DistX/DistY and on Y axies by increments of 1
For i = 1 to DistY
NewX = SourceX + (i*5/11)
NewY = SourceY + i
Next i
So then i have the coords of the hexs that cross the line
But it gives weird results like:
a gap:

too much hexes:

**** Right now my test project is in VB as it was faster/easier for me to test the algorithm. I'll translate it to blitzmax and post it later on.
This has been bugging and blocking me for a while now any help will be extremely appreciated, be sure of that.
Smurftra
Well, i'm gonna try that, but curiously enough, i ported my code to bmax and now the Line algorithm works. The Nearest one doesnt tho.
I dont know what caused the breaks in the lines in VB, but i think it has to do with the Round function.
Im not sure how you guys post code so it appears in a nice box, so i'm gonna post it straight as:
How to use: Hit Keys:
A = Switch to nearest hex graphically algorithm
B = Switch to hexes along a line algorithm
0-9 = Set SourceX, SourceY, DestX, DestY
(It will set the values in that order, meaning if you press 4,5,6,7, it will set SourceX to 4, SourceY to 5, DestX to 6, DestY to 7. When it sets DestY it calls the pathfinding algorithm selected via A or B)
Btw, i appreciate any comments on code structure, optimisation, other ways to implement this, etc...
I was also wondering if we can change KeyHit(Key) by something like Key = TheKeyThatWasHit()
So i could do If Key >= 0 and Key <=9
known issue: In the line algorithm, if you make a line alongside the edges, it might put every 2 hexs outside the limits therefor not drawing them. Fortunatly for my usage its a case that wont happen.
Strict
Global Hexs:THex[10,10]
Global HexSize:Int = 17
Global HexOffset:Int = 20
Global MovX:Int[6] 'How to find the adjacent hexs, 0 = North, 1 = North East, 2 = South East, 3 = South, 4 = South West, 5 = North West
Global MovY:Int[6,2]
Global Algorithm:Int = 0
Global NextInput:Int = 0
Global SourceX:Int, SourceY:Int, DestX:Int, DestY:Int
Local i:Int, j:Int
MovX[0] = 0
MovX[1] = 1
MovX[2] = 1
MovX[3] = 0
MovX[4] = -1
MovX[5] = -1
MovY[0, 0] = -1
MovY[0, 1] = -1
MovY[1, 0] = -1
MovY[1, 1] = 0
MovY[2, 0] = 0
MovY[2, 1] = 1
MovY[3, 0] = 1
MovY[3, 1] = 1
MovY[4, 0] = 0
MovY[4, 1] = 1
MovY[5, 0] = -1
MovY[5, 1] = 0
For i = 0 To 9
For j = 0 To 9
Hexs[j,i] = New THex
Hexs[j,i].x = HexOffset + j * HexSize
Hexs[j,i].y =( HexOffset + i * HexSize) + ((HexSize / 2) * (j mod 2))
Next
Next
'Runs the example by nearest graphical position
'FindPath_ByNearest 1, 1, 7, 7, 1, 1
'FindPath_AlongLine 2, 4, 6, 7
FindPath_AlongLine 2, 7, 5, 3
graphics 640,480,0
SetColor 255,255,255
While not KeyHit(KEY_ESCAPE)
Cls
CheckKeys
DrawHexs
DrawText "SourceX = " + SourceX, 400,20
DrawText "SourceY = " + SourceY, 400,30
DrawText "DestX = " + DestX, 400,40
DrawText "DestY = " + DestY, 400,50
Flip
Wend
Private Function CheckKeys()
Local KeyNb:Int = -1
If KeyHit(KEY_A) Then
Algorithm = 0
ClearHexs
FindPath_ByNearest SourceX, SourceY, DestX, DestY, SourceX, SourceY
End If
If KeyHit(KEY_B) Then
Algorithm = 1
ClearHexs
FindPath_AlongLine SourceX, SourceY, DestX, DestY
End If
If KeyHit(KEY_0) Then
KeyNb = 0
End If
If KeyHit(KEY_1) Then
KeyNb = 1
End If
If KeyHit(KEY_2) Then
KeyNb = 2
End If
If KeyHit(KEY_3) Then
KeyNb = 3
End If
If KeyHit(KEY_4) Then
KeyNb = 4
End If
If KeyHit(KEY_5) Then
KeyNb = 5
End If
If KeyHit(KEY_6) Then
KeyNb = 6
End If
If KeyHit(KEY_7) Then
KeyNb = 7
End If
If KeyHit(KEY_8) Then
KeyNb = 8
End If
If KeyHit(KEY_9) Then
KeyNb = 9
End If
If KeyNb> 0 Then
Select NextInput
Case 0
SourceX = KeyNb
Case 1
SourceY = KeyNb
Case 2
DestX = KeyNb
Case 3
DestY = KeyNb
ClearHexs
If Algorithm = 0 Then
FindPath_ByNearest SourceX, SourceY, DestX, DestY, SourceX, SourceY
Else
FindPath_AlongLine SourceX, SourceY, DestX, DestY
End If
End Select
NextInput:+1
NextInput = NextInput Mod 4
End If
End Function
Private Function FindPath_ByNearest(X1, Y1, X2, Y2, OX, OY)
Local i:Int
Local x:Int
Local y:Int
Local ClosestDist:Int
Local TmpDist:Int
Local TmpDist2:Int
Local ClosestHex:Int
Local ClosestX:Int
Local ClosestY:Int
Hexs[OX,OY].Selected = 1 'Set as source
'See the ID of the closest hex to -1 (Not found
ClosestHex = -1
'Make sure the starting ClosestDist is big enough that any distances between two hexes is smaller
ClosestDist = 2000000000
'Loop All hexs around current hex
For i = 0 To 5
x = X1 + MovX[i]
y = Y1 + MovY[i, X1 Mod 2]
'if its within range of the grid
If x > -1 and x < 10 and y > -1 and y < 10 Then
'Check the distance between our hex and the destination hex
TmpDist = (Hexs[x2,y2].x - Hexs[x,y].x) ^ 2 + (Hexs[x2,y2].y - Hexs[x,y].y) ^ 2
If TmpDist = ClosestDist Then
'if its equal to another hex, check the distance between our hex and source hex)
'Distance of current hex to source hex
TmpDist = (Hexs[OX,OY].x - Hexs[x,y].x) ^ 2 + (Hexs[OX,OY].y - Hexs[x,y].y) ^ 2
'Distance of the closest x to source hex
TmpDist2 = (Hexs[OX,OY].x - Hexs[ClosestX,ClosestY].x) ^ 2 + (Hexs[OX,OY].y - Hexs[ClosestX,ClosestY].y) ^ 2
'If the new hex distance its smaller we use the new hex
If TmpDist < TmpDist2 Then
ClosestDist = TmpDist
ClosestHex = i
ClosestX = x
ClosestY = y
End If
Else
'if its not equal we check if its smaller
If TmpDist < ClosestDist Then
ClosestDist = TmpDist
ClosestHex = i
ClosestX = x
ClosestY = y
End If
End If
End If
Next
'if we found one
If ClosestHex <> -1 Then
'If its the destination
If ClosestX = X2 and ClosestY = Y2 Then
Hexs[ClosestX,ClosestY].Selected = 3 'Set as destination
Else
Hexs[ClosestX,ClosestY].Selected = 2 'Set as path
'Recursive FindNext
FindPath_ByNearest ClosestX, ClosestY, X2, Y2, OX, OY
End If
End If
End Function
Private Function FindPath_AlongLine(X1, Y1, X2, Y2)
Local DistanceX:Double
Local DistanceY:Double
Local NbSteps:Double
Local AdjustedY1:Int
Local AdjustedY2:Int
Local AdjustedDistanceY:Int
Local IncrementX:Double
Local IncrementY:Double
Local NewX:Int
Local NewY:Int
Local i:Int
AdjustedY1 = Y1 * 2 + (X1 Mod 2)
AdjustedY2 = Y2 * 2 + (X2 Mod 2)
DistanceX = X2 - X1
DistanceY = AdjustedY2 - AdjustedY1
'Find the increments and nbsteps to do lines
'DebugStop
If Abs(DistanceX) > Abs(DistanceY) Then
NbSteps = Abs(DistanceX)
AdjustedDistanceY = AdjustedY2 - AdjustedY1
IncrementY = AdjustedDistanceY / NbSteps
IncrementX = DistanceX / Abs(DistanceX)
Else
NbSteps = Abs(DistanceY)
AdjustedY1 = Y1 * 2 + (X1 Mod 2)
AdjustedY2 = Y2 * 2 + (X2 Mod 2)
AdjustedDistanceY = AdjustedY2 - AdjustedY1
IncrementY = AdjustedDistanceY / Abs(AdjustedDistanceY)
IncrementX = DistanceX / NbSteps
End If
For i = 1 To NbSteps
NewX = X1 + Round((i * IncrementX))
NewY = AdjustedY1 + Round((i * IncrementY))
'change frmo adjusted to real Y
NewY = Round((NewY - (NewX Mod 2)) / 2)
If NewX > -1 and NewX < 10 and NewY > -1 and NewY < 10 Then
Hexs[NewX,NewY].Selected = 2
End If
Next
Hexs[X1,Y1].Selected = 1 'set source
Hexs[X2,Y2].Selected = 3 'set dest
End Function
Function DrawHexs()
Local i:Int
Local j:Int
For i = 0 To 9
For j = 0 To 9
Select Hexs[i,j].Selected
Case 1
SetColor 0,255,0
DrawRect Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
SetColor 255,255,255
Case 2
SetColor 255,0,0
DrawRect Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
SetColor 255,255,255
Case 3
SetColor 0,0,255
DrawRect Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
SetColor 255,255,255
End Select
DrawRectOutline Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
Next
Next
End Function
Function ClearHexs()
Local i:Int
Local j:Int
For i = 0 To 9
For j = 0 To 9
Hexs[i,j].Selected = 0
Next
Next
End Function
Function DrawRectOutline(x,y,w,h)
'trim
w = w-1
h = h-1
DrawLine(x,y,x+w,y,0)
DrawLine(x+w,y,x+w,y+h,0)
DrawLine(x+w,y+h,x,y+h,0)
DrawLine(x,y+h,x,y,0)
End Function
Function Round:Double(x:Double)
Return Int(x + (Sgn(x) * 0.5))
End Function
Type THex
Field x:Int
Field y:Int
Field Selected:Int
End Type
anyways, heres the code:
heres the modified line algorithm to work with the link you given me. It does give a good looking line but still has some exceptions (some lines that go from bottom left to upper right start by going down before going up. I've tried working around it using Floor/Ceil but it doesnt always work).
try (7,5) - (0,7) to see what i mean
Function FindPath_AlongLine(X1:Int,Y1:Int,X2:Int,Y2:Int)
'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
Local OldX1:Int = X1
Local OldX2:Int = X2
Local AdjY1:Int = Y1 * 2 + (X1 Mod 2)
Local AdjY2:Int = Y2 * 2 + (X2 Mod 2)
Local Steep:Int=Abs(AdjY2-AdjY1) > Abs(X2-X1) 'Boolean
If Steep
Local Temp:Int=X1; X1=AdjY1; AdjY1=Temp 'Swap X1,Y1
Temp=X2; X2=AdjY2; AdjY2=Temp 'Swap X2,Y2
EndIf
Local DeltaX:Int=Abs(X2-X1) 'X Difference
Local DeltaY:Int=Abs(AdjY2-AdjY1) 'Y Difference
Local error:Int=0 'Overflow counter
Local DeltaError:Int=DeltaY 'Counter adder
Local x:Int=X1 'Start at X1,Y1
Local y:Int=AdjY1
Local XStep:Int
Local YStep:Int
Local RY:Int
If X1<X2 Then XStep=1 Else XStep=-1 'Direction
If AdjY1<AdjY2 Then YStep=1 Else YStep=-1 'Direction
If Steep Then
If x > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
End If
Hexs[y,RY].Selected = 2
Else
'Draw
If y > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
End If
Hexs[x,ry].Selected = 2
End If
While x<>X2
x:+XStep 'Move in X
error:+DeltaError 'Add to counter
If (error Shl 1)>DeltaX 'Would it overflow?
y:+YStep 'Move in Y
error=error-DeltaX 'Overflow/wrap the counter
EndIf
If Steep Then
If x > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
End If
Hexs[y,ry].Selected = 2
Else
If y > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
End If
Hexs[x,ry].Selected = 2
End If
Wend
Hexs[oldX1,Y1].Selected = 1 'set source
Hexs[oldX2,Y2].Selected = 3 'set dest
End Function
just reposting the full source in a better format
now pressing A = Nearest Algorithm, B = my line algorthm, C = Bresenham's line algorithm
Strict
Global Hexs:THex[10,10]
Global HexSize:Int = 20
Global HexOffset:Int = 20
Global MovX:Int[6] 'How to find the adjacent hexs, 0 = North, 1 = North East, 2 = South East, 3 = South, 4 = South West, 5 = North West
Global MovY:Int[6,2]
Global Algorithm:Int = 0
Global NextInput:Int = 0
Global SourceX:Int, SourceY:Int, DestX:Int, DestY:Int
Local i:Int, j:Int
MovX[0] = 0
MovX[1] = 1
MovX[2] = 1
MovX[3] = 0
MovX[4] = -1
MovX[5] = -1
MovY[0, 0] = -1
MovY[0, 1] = -1
MovY[1, 0] = -1
MovY[1, 1] = 0
MovY[2, 0] = 0
MovY[2, 1] = 1
MovY[3, 0] = 1
MovY[3, 1] = 1
MovY[4, 0] = 0
MovY[4, 1] = 1
MovY[5, 0] = -1
MovY[5, 1] = 0
For i = 0 To 9
For j = 0 To 9
Hexs[j,i] = New THex
Hexs[j,i].x = HexOffset + j * HexSize
Hexs[j,i].y =( HexOffset + i * HexSize) + ((HexSize / 2) * (j Mod 2))
Next
Next
'Runs the example by nearest graphical position
'FindPath_ByNearest 1, 1, 7, 7, 1, 1
'FindPath_AlongLine 2, 4, 6, 7
FindPath_AlongLine 2, 7, 5, 3
graphics 360,250,0
SetColor 255,255,255
While not KeyHit(KEY_ESCAPE)
Cls
CheckKeys
DrawHexs
DrawText "SourceX = " + SourceX, 250,20
DrawText "SourceY = " + SourceY, 250,30
DrawText "DestX = " + DestX, 250,40
DrawText "DestY = " + DestY, 250,50
Flip
Wend
Private Function CheckKeys()
Local KeyNb:Int = -1
If KeyHit(KEY_A) Then
Algorithm = 0
ClearHexs
FindPath_ByNearest SourceX, SourceY, DestX, DestY, SourceX, SourceY
End If
If KeyHit(KEY_B) Then
Algorithm = 1
ClearHexs
FindPath_AlongLine SourceX, SourceY, DestX, DestY
End If
If KeyHit(KEY_C) Then
Algorithm = 2
ClearHexs
FindPath_AlongLine2 SourceX, SourceY, DestX, DestY
End If
If KeyHit(KEY_SPACE) Then
SourceX = Rnd(10)
SourceY = Rnd(10)
DestX = Rnd(10)
DestY = Rnd(10)
ClearHexs
Select Algorithm
Case 0
FindPath_ByNearest SourceX, SourceY, DestX, DestY, SourceX, SourceY
Case 1
FindPath_AlongLine SourceX, SourceY, DestX, DestY
Case 2
FindPath_AlongLine2 SourceX, SourceY, DestX, DestY
End Select
End If
If KeyHit(KEY_0) Then
KeyNb = 0
End If
If KeyHit(KEY_1) Then
KeyNb = 1
End If
If KeyHit(KEY_2) Then
KeyNb = 2
End If
If KeyHit(KEY_3) Then
KeyNb = 3
End If
If KeyHit(KEY_4) Then
KeyNb = 4
End If
If KeyHit(KEY_5) Then
KeyNb = 5
End If
If KeyHit(KEY_6) Then
KeyNb = 6
End If
If KeyHit(KEY_7) Then
KeyNb = 7
End If
If KeyHit(KEY_8) Then
KeyNb = 8
End If
If KeyHit(KEY_9) Then
KeyNb = 9
End If
If KeyNb> -1 Then
Select NextInput
Case 0
SourceX = KeyNb
Case 1
SourceY = KeyNb
Case 2
DestX = KeyNb
Case 3
DestY = KeyNb
ClearHexs
Select Algorithm
Case 0
FindPath_ByNearest SourceX, SourceY, DestX, DestY, SourceX, SourceY
Case 1
FindPath_AlongLine SourceX, SourceY, DestX, DestY
Case 2
FindPath_AlongLine2 SourceX, SourceY, DestX, DestY
End Select
End Select
NextInput:+1
NextInput = NextInput Mod 4
End If
End Function
Private Function FindPath_ByNearest(X1, Y1, X2, Y2, OX, OY)
Local i:Int
Local x:Int
Local y:Int
Local ClosestDist:Int
Local TmpDist:Int
Local TmpDist2:Int
Local ClosestHex:Int
Local ClosestX:Int
Local ClosestY:Int
Hexs[OX,OY].Selected = 1 'Set as source
'See the ID of the closest hex to -1 (Not found
ClosestHex = -1
'Make sure the starting ClosestDist is big enough that any distances between two hexes is smaller
ClosestDist = 2000000000
'Loop All hexs around current hex
For i = 0 To 5
x = X1 + MovX[i]
y = Y1 + MovY[i, X1 Mod 2]
'if its within range of the grid
If x > -1 and x < 10 and y > -1 and y < 10 Then
'Check the distance between our hex and the destination hex
TmpDist = (Hexs[x2,y2].x - Hexs[x,y].x) ^ 2 + (Hexs[x2,y2].y - Hexs[x,y].y) ^ 2
If TmpDist = ClosestDist Then
'if its equal to another hex, check the distance between our hex and source hex)
'Distance of current hex to source hex
TmpDist = (Hexs[OX,OY].x - Hexs[x,y].x) ^ 2 + (Hexs[OX,OY].y - Hexs[x,y].y) ^ 2
'Distance of the closest x to source hex
TmpDist2 = (Hexs[OX,OY].x - Hexs[ClosestX,ClosestY].x) ^ 2 + (Hexs[OX,OY].y - Hexs[ClosestX,ClosestY].y) ^ 2
'If the new hex distance its smaller we use the new hex
If TmpDist < TmpDist2 Then
ClosestDist = TmpDist
ClosestHex = i
ClosestX = x
ClosestY = y
End If
Else
'if its not equal we check if its smaller
If TmpDist < ClosestDist Then
ClosestDist = TmpDist
ClosestHex = i
ClosestX = x
ClosestY = y
End If
End If
End If
Next
'if we found one
If ClosestHex <> -1 Then
'If its the destination
If ClosestX = X2 and ClosestY = Y2 Then
Hexs[ClosestX,ClosestY].Selected = 3 'Set as destination
Else
Hexs[ClosestX,ClosestY].Selected = 2 'Set as path
'Recursive FindNext
FindPath_ByNearest ClosestX, ClosestY, X2, Y2, OX, OY
End If
End If
End Function
Private Function FindPath_AlongLine(X1, Y1, X2, Y2)
Local DistanceX:Double
Local DistanceY:Double
Local NbSteps:Double
Local AdjustedY1:Int
Local AdjustedY2:Int
Local AdjustedDistanceY:Int
Local IncrementX:Double
Local IncrementY:Double
Local NewX:Int
Local NewY:Int
Local i:Int
AdjustedY1 = Y1 * 2 + (X1 Mod 2)
AdjustedY2 = Y2 * 2 + (X2 Mod 2)
DistanceX = X2 - X1
DistanceY = AdjustedY2 - AdjustedY1
'Find the increments and nbsteps to do lines
'DebugStop
If Abs(DistanceX) > Abs(DistanceY) Then
NbSteps = Abs(DistanceX)
AdjustedDistanceY = AdjustedY2 - AdjustedY1
IncrementY = AdjustedDistanceY / NbSteps
IncrementX = DistanceX / Abs(DistanceX)
Else
NbSteps = Abs(DistanceY)
AdjustedY1 = Y1 * 2 + (X1 Mod 2)
AdjustedY2 = Y2 * 2 + (X2 Mod 2)
AdjustedDistanceY = AdjustedY2 - AdjustedY1
IncrementY = AdjustedDistanceY / Abs(AdjustedDistanceY)
IncrementX = DistanceX / NbSteps
End If
For i = 1 To NbSteps
NewX = X1 + Round((i * IncrementX))
NewY = AdjustedY1 + Round((i * IncrementY))
'change frmo adjusted to real Y
NewY = Round((NewY - (NewX Mod 2)) / 2)
If NewX > -1 and NewX < 10 and NewY > -1 and NewY < 10 Then
Hexs[NewX,NewY].Selected = 2
End If
Next
Hexs[X1,Y1].Selected = 1 'set source
Hexs[X2,Y2].Selected = 3 'set dest
End Function
Function FindPath_AlongLine2(X1:Int,Y1:Int,X2:Int,Y2:Int)
'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
Local OldX1:Int = X1
Local OldX2:Int = X2
Local AdjY1:Int = Y1 * 2 + (X1 Mod 2)
Local AdjY2:Int = Y2 * 2 + (X2 Mod 2)
Local Steep:Int=Abs(AdjY2-AdjY1) > Abs(X2-X1) 'Boolean
If Steep
Local Temp:Int=X1; X1=AdjY1; AdjY1=Temp 'Swap X1,Y1
Temp=X2; X2=AdjY2; AdjY2=Temp 'Swap X2,Y2
EndIf
Local DeltaX:Int=Abs(X2-X1) 'X Difference
Local DeltaY:Int=Abs(AdjY2-AdjY1) 'Y Difference
Local error:Int=0 'Overflow counter
Local DeltaError:Int=DeltaY 'Counter adder
Local x:Int=X1 'Start at X1,Y1
Local y:Int=AdjY1
Local XStep:Int
Local YStep:Int
Local RY:Int
If X1<X2 Then XStep=1 Else XStep=-1 'Direction
If AdjY1<AdjY2 Then YStep=1 Else YStep=-1 'Direction
If Steep Then
If x > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
End If
Hexs[y,RY].Selected = 2
Else
'Draw
If y > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
End If
Hexs[x,ry].Selected = 2
End If
While x<>X2
DebugStop
x:+XStep 'Move in X
error:+DeltaError 'Add to counter
If (error Shl 1)>DeltaX 'Would it overflow?
y:+YStep 'Move in Y
error=error-DeltaX 'Overflow/wrap the counter
EndIf
If Steep Then
If x > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
End If
Hexs[y,ry].Selected = 2
Else
If y > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
End If
Hexs[x,ry].Selected = 2
End If
Wend
Hexs[oldX1,Y1].Selected = 1 'set source
Hexs[oldX2,Y2].Selected = 3 'set dest
End Function
Function DrawHexs()
Local i:Int
Local j:Int
For i = 0 To 9
For j = 0 To 9
Select Hexs[i,j].Selected
Case 1
SetColor 0,255,0
DrawRect Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
SetColor 255,255,255
Case 2
SetColor 255,0,0
DrawRect Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
SetColor 255,255,255
Case 3
SetColor 0,0,255
DrawRect Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
SetColor 255,255,255
End Select
DrawRectOutline Hexs[i,j].x, Hexs[i,j].y, HexSize, HexSize
Next
Next
End Function
Function ClearHexs()
Local i:Int
Local j:Int
For i = 0 To 9
For j = 0 To 9
Hexs[i,j].Selected = 0
Next
Next
End Function
Function DrawRectOutline(x,y,w,h)
'trim
w = w-1
h = h-1
DrawLine(x,y,x+w,y,0)
DrawLine(x+w,y,x+w,y+h,0)
DrawLine(x+w,y+h,x,y+h,0)
DrawLine(x,y+h,x,y,0)
End Function
Function Round:Double(x:Double)
Return Int(x + (Sgn(x) * 0.5))
End Function
Type THex
Field x:Int
Field y:Int
Field Selected:Int
End Type
I pursued the Breseham algorithm and figured i had just to 'fix' the part where i need to chose between CEIL Or FLOOR depending on the slope.
here's the fixed algorithm that works (needs the full source that s 2 posts above, remember to press C to be using the correct algorithm):
(Side note: I just made it work, didnt optimize it or clean up the code)
[CodeBox]
Function FindPath_AlongLine2(X1:Int,Y1:Int,X2:Int,Y2:Int)
'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
Local OldX1:Int = X1
Local OldX2:Int = X2
Local AdjY1:Int = Y1 * 2 + (X1 Mod 2)
Local AdjY2:Int = Y2 * 2 + (X2 Mod 2)
Local Steep:Int=Abs(AdjY2-AdjY1) > Abs(X2-X1) 'Boolean
If Steep
Local Temp:Int=X1; X1=AdjY1; AdjY1=Temp 'Swap X1,Y1
Temp=X2; X2=AdjY2; AdjY2=Temp 'Swap X2,Y2
EndIf
Local DeltaX:Int=Abs(X2-X1) 'X Difference
Local DeltaY:Int=Abs(AdjY2-AdjY1) 'Y Difference
Local error:Int=0 'Overflow counter
Local DeltaError:Int=DeltaY 'Counter adder
Local x:Int=X1 'Start at X1,Y1
Local y:Int=AdjY1
Local XStep:Int
Local YStep:Int
Local RY:Int
If X1<X2 Then XStep=1 Else XStep=-1 'Direction
If AdjY1<AdjY2 Then YStep=1 Else YStep=-1 'Direction
If Steep Then
If x > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
End If
Hexs[y,RY].Selected = 2
Else
'Draw
If y > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
End If
Hexs[x,ry].Selected = 2
End If
While x<>X2
'DebugStop
x:+XStep 'Move in X
error:+DeltaError 'Add to counter
If (error Shl 1)>DeltaX 'Would it overflow?
y:+YStep 'Move in Y
error=error-DeltaX 'Overflow/wrap the counter
EndIf
If Steep Then
If x = (Y2* 2 + (x2 Mod 2)) Then
If XStep < 0 Then
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
End If
Else
If x > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(x) - (Double(y) Mod 2)) / 2)
Else
RY = Ceil((Double(x) - (Double(y) Mod 2)) / 2)
End If
End If
If ry>9 Then ry=9
If ry<0 Then ry=0
Hexs[y,ry].Selected = 2
Else
If y = (Y2* 2 + (x2 Mod 2)) Then
If YStep < 0 Then
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
End If
Else
If y > (Y2* 2 + (x2 Mod 2)) Then
RY = Floor((Double(y) - (Double(x) Mod 2)) / 2)
Else
RY = Ceil((Double(y) - (Double(x) Mod 2)) / 2)
End If
End If
If ry>9 Then ry=9
If ry<0 Then ry=0
Hexs[x,ry].Selected = 2
End If
Wend
Hexs[oldX1,Y1].Selected = 1 'set source
Hexs[oldX2,Y2].Selected = 3 'set dest
End Function
[/CodeBox]