@jfk,
Ok, I finished the 3d pathfinding editor,
but the code is certainly > dirty <
I'm starting to cleaning it up to adapt it to my game
but I don't know when I will finish or how much generic
it will be when I finish.
So I decided to post the code as it is now ...
The best I can tell you is to see the help with F1
good luck :)
Paolo.
AppTitle "3DPathfinding editor by Paolo Cosentino"
Graphics3D 800,600,16,2
Function interpolate#(v#,a#,b#,c#,d#)
Return c+(((v-a)*(d-c))/(b-a))
End Function
AmbientLight 255,255,255
Global cam_player=CreateCamera()
CameraRange cam_player,.01,200
RotateEntity cam_player,0,90,0
EntityRadius cam_player,.8,1.9
;----------------------------------------------
;--------- LOAD A LEVEL HERE --------------
;The 3D space is empty so is better if you load
;something to understand where you are.
;----------------------------------------------
;----------------------------------------------
font=LoadFont("arial",15,0,0,0)
SetFont font
;***************************************
;------- PATHFINDING --------
reset=True
Global node1=0
Global node2=0
Global path_picked=0
Global path_editing=1
Global path_nodeselected=-1
Global path_total$=""
Global path_maxnodes=50 ;999
Dim paths1(path_maxnodes,5)
;a,0 = Visual of NODE (it should contain a pivot to retreive POSITION of the NODE)
;a,1 = In Open or Closed list, =0 Default , =1 in Open , =2 in Closed
;a,2 = F (it is G+H)
;a,3 = G ,distance from actual node to before node
;a,4 = H ,distance from actual node to detination node
;a,5 = Parent of the node
Dim paths1b$(path_maxnodes)
;a = Contain a string with the nodes that are linked with the actual node (00102030 ...)
Function LOAD_NODESFILE(f$)
file=ReadFile(f)
If file
While Not Eof(file)
l1$=ReadLine(file)
l2$=ReadLine(file)
l3$=ReadLine(file)
l4$=ReadLine(file)
l5$=ReadLine(file)
paths1(l1,0)=CreateSphere(2);CreatePivot()
ScaleMesh paths1(l1,0),.2,.2,.2
EntityColor paths1(l1,0),0,150,0
EntityFX paths1(l1,0),1
;EntityAlpha paths1(l1,0),.5
PositionEntity paths1(l1,0),l2,l3,l4
EntityPickMode paths1(l1,0),2;???????????
paths1b(l1)=l5
Wend
EndIf
End Function
Function SAVE_NODESFILE(f$)
file=WriteFile(f)
If file
For p=0 To path_maxnodes ;999
If paths1(p,0)>0
WriteLine file,p
WriteLine file,EntityX(paths1(p,0))
WriteLine file,EntityY(paths1(p,0))
WriteLine file,EntityZ(paths1(p,0))
WriteLine file,paths1b(p)
EndIf
Next
CloseFile file
Delay 250
EndIf
End Function
LOAD_NODESFILE("nodes.txt")
Function ADD_NODE(x#,y#,z#)
For p=0 To path_maxnodes ;999
If paths1(p,0)=0
paths1(p,0)=CreateSphere(2) ;CreatePivot()
ScaleMesh paths1(p,0),.2,.2,.2
EntityColor paths1(p,0),0,150,0
EntityFX paths1(p,0),1
;EntityAlpha paths1(p,0),.5
PositionEntity paths1(p,0),x,y,z
EntityPickMode paths1(p,0),2 ;???????????
Exit
EndIf
Next
End Function
Function GET_NEARNODE(ele)
dist1#=100000
num=-1
For p=0 To path_maxnodes ;999
If paths1(p,0)>0
dist2#=EntityDistance(ele,paths1(p,0))
If dist2<dist1
dist1=dist2
num=p
EndIf
EndIf
Next
Return num
End Function
Function FIND_PATH(from_node,to_node)
If from_node+to_node>-1 And from_node<>to_node
;-------------------------
;--- Reset Path --------
path_total=""
For p=0 To path_maxnodes;999
paths1(p,1)=0
paths1(p,2)=0
paths1(p,3)=0
paths1(p,4)=0
paths1(p,5)=0
Next
For amark.paths_marks=Each paths_marks
FreeEntity amark\ele
Delete amark
Next
;-------------------------
dist#=0
;If parent=-1 Then parent=from_node
parent=from_node
.path_again
nodes_in_list=False
;For p=0 To path_maxnodes;999
; If p=parent ;If exists a node
;nodes$=paths1b(p)
nodes$=paths1b(parent)
For l=1 To Len(nodes)/2
num=Int(Mid(nodes,l*2-1,2))
If paths1(num,1)=0 ;if in Default
nodes_in_list=True
paths1(num,1)=1 ;add node to Open list
paths1(num,5)=parent ;-> set node parent
;Calc G:
dist=paths1(parent,3)+Int(EntityDistance(paths1(parent,0),paths1(num,0))*10)
paths1(num,3)=dist
;Calc H:
;dist=EntityDistance(paths1(num,0),paths1(to_node,0))*10
h=Abs(EntityX(paths1(num,0))-EntityX(paths1(to_node,0)))*10
paths1(num,4)=h
h=Abs(EntityY(paths1(num,0))-EntityY(paths1(to_node,0)))*10
paths1(num,4)=paths1(num,4)+h
h=Abs(EntityZ(paths1(num,0))-EntityZ(paths1(to_node,0)))*10
paths1(num,4)=paths1(num,4)+h
;Calc F: (G+H)
paths1(num,2)=paths1(num,3)+paths1(num,4)
ElseIf paths1(num,1)=1 ;if in Open list
nodes_in_list=True
For l2=1 To Len(paths1b(num))/2
num2=Int(Mid(paths1b(num),l2*2-1,2))
If paths1(num2,1)=2;if it is a parent
checkg=paths1(num2,3)+Int(EntityDistance(paths1(num2,0),paths1(num,0))*10)
If checkg<paths1(num,3)
paths1(num,3)=checkg
paths1(num,2)=paths1(num,3)+paths1(num,4)
paths1(num,5)=num2;-> set new parent
EndIf
EndIf
Next
EndIf
Next
paths1(parent,1)=2;add parent to Closed list
;Exit
;EndIf
;Next
;Stop
;Find lowest F and repeat the process:
dist=100000
For p=0 To path_maxnodes;999
If paths1(p,0)>0
If paths1(p,1)=1 ;if in Open list
If paths1(p,2)<dist
If nodes_in_list=False
dist=paths1(p,2)
newparent=p
Else
;For l=1 To Len(paths1b(parent))/2
;s$=Mid(paths1b(parent),l*2-1,2)
; If Int(s)=p
dist=paths1(p,2)
newparent=p
; Exit
; EndIf
;Next
EndIf
EndIf
EndIf
EndIf
Next
If parent=newparent ;-> indica que no hay solucion
Goto path_false
Else
parent=newparent
EndIf
If parent=to_node
If to_node=0
path_total="00"
ElseIf to_node<10
path_total="0"+Str(to_node)
Else
path_total=Str(to_node)
EndIf
If Len(paths1b(from_node))>0
Repeat
newparent=paths1(parent,5)
If newparent=0
path_total=path_total+"00"
ElseIf newparent<10
path_total=path_total+"0"+Str(newparent)
Else
path_total=path_total+Str(newparent)
EndIf
parent=paths1(parent,5)
Until newparent=from_node
EndIf
Else
Goto path_again
EndIf
.path_false
;-----------------------------------------
EndIf
End Function
Function CREATE_PATH()
;--------------------
;ADD a NODE
If KeyHit(49) ;N
ADD_NODE(EntityX(cam_player),EntityY(cam_player),EntityZ(cam_player))
EndIf
;--------------
;Pick a Node:
If MouseHit(1)
path_picked=CameraPick(cam_player,GraphicsWidth()/2,GraphicsHeight()/2)
EndIf
;----------------------------
;----- MOVE A NODE ------
If KeyDown(29);Left Ctrl
If path_picked>0
;Trasladar NODE
If KeyDown(23); i - Forward
TranslateEntity paths1(path_nodeselected,0),0,0,.05
ElseIf KeyDown(37); K - Backward
TranslateEntity paths1(path_nodeselected,0),0,0,-.05
ElseIf KeyDown(36); J - Left
TranslateEntity paths1(path_nodeselected,0),-.05,0,0
ElseIf KeyDown(38); L - Right
TranslateEntity paths1(path_nodeselected,0),.05,0,0
ElseIf KeyDown(22) ;U - Up
TranslateEntity paths1(path_nodeselected,0),0,.05,0
ElseIf KeyDown(24) ;O - Down
TranslateEntity paths1(path_nodeselected,0),0,-.05,0
EndIf
EndIf
EndIf
;----------------------------
;-------------------------------------------
;Asociate a NODE with the selected NODE
If KeyHit(46) ;key C
If path_picked>0
For p=0 To path_maxnodes ;999
If path_picked=paths1(p,0)
SetBuffer FrontBuffer()
Color 0,0,0
Rect 20,25,GraphicsWidth(),30
Color 255,255,255
Locate 30,30
FlushKeys
s$=Input("NODE number to connect: "+paths1b(p))
FlushKeys
If Len(s)>0
paths1b(p)=paths1b(p)+s
If p=0
s2$="00"
ElseIf p<10
s2$="0"+Str(p)
Else
s2$=p
EndIf
paths1b(s)=paths1b(s)+s2
EndIf
SetBuffer BackBuffer()
Exit
EndIf
Next
EndIf
EndIf
;---------------------------------------------------------
;------- DELETE A CONNECTION with a NODE ---------
If KeyHit(45) ;X
If path_picked>0
For p=0 To path_maxnodes ;999
If path_picked=paths1(p,0)
SetBuffer FrontBuffer()
Color 0,0,0
Rect 20,25,GraphicsWidth(),30
Color 255,255,255
Locate 30,30
FlushKeys
s$=Input("Delete Connection with NODE: ")
FlushKeys
If Len(s)>0
For l=1 To Len(paths1b(p))/2
s2$=Mid(paths1b(p),l*2-1,2)
If s2=s
paths1b(p)=Left(paths1b(p),Instr(paths1b(p),s2)-1)+Mid(paths1b(p),Instr(paths1b(p),s2)+2)
Exit
EndIf
Next
For l=1 To Len(paths1b(s))/2
s2$=Mid(paths1b(s),l*2-1,2)
p2=s2
If p2=p
paths1b(s)=Left(paths1b(s),Instr(paths1b(s),s2)-1)+Mid(paths1b(s),Instr(paths1b(s),s2)+2)
Exit
EndIf
Next
EndIf
SetBuffer BackBuffer()
Exit
EndIf
Next
EndIf
EndIf
;-------------------------------------------
;---- DELETE A NODE FROM SCENE ------
If KeyHit(32) ;key D
If path_picked>0
For p=0 To path_maxnodes ;999
If path_picked=paths1(p,0)
FreeEntity paths1(p,0)
paths1(p,0)=0
paths1(p,1)=0
paths1(p,2)=0
paths1(p,3)=0
paths1(p,4)=0
paths1(p,5)=0
paths1b(p)=""
For p2=0 To path_maxnodes ;999
s$=paths1b(p2)
If Len(s)>0
If p=0
checks$="00"
ElseIf p<10
checks$="0"+Str(p)
Else
checks$=Str(p)
EndIf
s2=""
For l=1 To Len(s)/2
s3$= Mid(s,l*2-1,2)
If Not s3=checks
s2=s2+s3
EndIf
Next
paths1b(p2)=s2
EndIf
Next
Exit
EndIf
Next
EndIf
EndIf
;-------
;Reset
If KeyHit(57) ;SPACE
path_total=""
;enem_path=""
parent=-1
For p=0 To path_maxnodes ;999
paths1(p,1)=0
paths1(p,2)=0
paths1(p,3)=0
paths1(p,4)=0
paths1(p,5)=0
Next
For amark.paths_marks=Each paths_marks
FreeEntity amark\ele
Delete amark
Next
reset=True
EndIf
;----------------------------------------------------
;Change de Nodes From/To for the Pathfinding:
If KeyHit(25) ;P
SetBuffer FrontBuffer()
Color 0,0,0
Rect 20,25,GraphicsWidth(),40
Color 255,255,255
Locate 30,30
FlushKeys
Print "Enter two digits per node, eg: 37-00 (means the path will be found from node 37 to node 0)
Locate 30,45
s$=Input("Enter new NODES: ")
FlushKeys
If Len(s)>0
node1=Int(Left(s,2))
node2=Int(Right(s,2))
EndIf
SetBuffer BackBuffer()
EndIf
;-------------------------------------------
;---- SAVE NODES & CONNECTIONS ----
If KeyHit(60) ;F2
SAVE_NODESFILE("nodes.txt")
EndIf
;----------------------------------------
;---------
;Help
If KeyHit(59) ;F1
FlushKeys
SetBuffer FrontBuffer()
Color 0,0,0
Rect 0,0,GraphicsWidth(),350
Color 255,255,255
Print:Print
Print " -Important:"
Print " -When you enter a node number anywhere in the editor you will have to do it with two digits."
Print " For example: if you want to point to the node number 5, you will write 05, if you"
Print " want the node 0, you write 00, if your node number is bigger than 9 then write it normally."
Print:Print
Print " Cursors + Mouse ------> Move"
Print
Print " Key N -----> add a node at the camera position"
Print " Key D -----> delete selected node"
Print " key LMB -----> pick a node"
Print " key C -----> enter a node number to connect the selected node to"
Print " key P -----> enter new "+Chr(34)+"from node"+Chr(34)+" -> "+Chr(34)+"to node"+Chr(34)+" numbers to use in the pathfinding"
Print " CTRL+[I,K,J,L,U,O] --> translate selected node"
Print " key X -----> delete a connection with a node"
Print
Print " key ENTER -----> Find path"
Print " Key SPACE -----> Reset pathfinding"
Print
Print " F2 -----> Save Nodes+Connections to a .txt file>"
Print " key M -----> Load a new Mesh (you must write the path to the mesh, eg: 3dmodel/mylevel.3ds)"
WaitKey()
FlushKeys
SetBuffer BackBuffer()
EndIf
;--------------
;Load a Mesh
If KeyHit(50);M
FlushKeys
SetBuffer FrontBuffer()
Color 0,0,0
Rect 0,0,500,350
Color 255,255,255
Print:Print
s$=Input(" Load new mesh, write path: ")
If Len(s)>0
If m Then FreeEntity m
m=LoadMesh(s)
EndIf
FlushKeys
SetBuffer BackBuffer()
EndIf
End Function
Function SHOW_NODES_STATS()
;EntityColor the Nodes, draw numbers, and draw connection lines:
For p=0 To path_maxnodes ;999
If paths1(p,0)>0
EntityColor paths1(p,0),0,150,0
CameraProject cam_player,EntityX(paths1(p,0)),EntityY(paths1(p,0)),EntityZ(paths1(p,0))
x1#=ProjectedX()
y1#=ProjectedY()
z1#=ProjectedZ()
If z1>0
Color 255,255,255
Text x1,y1,p
If EntityDistance(paths1(p,0),cam_player)<10
Text x1,y1+10,"F: "+paths1(p,2)
Text x1,y1+20,"G: "+paths1(p,3)
Text x1,y1+30,"H: "+paths1(p,4)
Text x1,y1+40,"Parent: "+paths1(p,5)
Text x1,y1+50,"OnList: "+paths1(p,1)
EndIf
EndIf
If path_picked>0
If path_picked=paths1(p,0)
EntityColor paths1(p,0),255,100,0
path_nodeselected=p
EndIf
Else
path_nodeselected=-1
EndIf
If paths1(p,1)=1
EntityColor paths1(p,0),0,255,255
EndIf
If paths1(p,1)=2
EntityColor paths1(p,0),255,0,0
EndIf
;Draw lines:
Color 0,255,0
If Len(paths1b(p))>0
s$=paths1b(p)
For l=1 To Len(s)/2
num$=Mid(s,l*2-1,2)
CameraProject cam_player,EntityX(paths1(num,0)),EntityY(paths1(num,0)),EntityZ(paths1(num,0))
x2#=ProjectedX()
y2#=ProjectedY()
z2#=ProjectedZ()
If z1>0 And z2>0
Line x1,y1,x2,y2
EndIf
Next
EndIf
Color 255,255,255
If path_picked=paths1(p,0)
printnodes$=""
s=paths1b(p)
For l=1 To Len(s)/2
printnodes=printnodes+Mid(s,l*2-1,2)+"-"
Next
Text 10,80,printnodes
EndIf
EndIf
Next
;------------------------------------
End Function
;***************************************
;Red cubes to show the found path:
Type paths_marks
Field ele
End Type
Function ADD_MARKER(node1,node2)
node1=paths1(node1,0)
node2=paths1(node2,0)
amark.paths_marks=New paths_marks
amark\ele=CreateCube()
EntityColor amark\ele,255,0,0
EntityFX amark\ele,1
PositionMesh amark\ele,0,0,1
ScaleMesh amark\ele,.1,.1,1
PositionEntity amark\ele,EntityX(node1),EntityY(node1),EntityZ(node1)
PointEntity amark\ele,node2
ScaleEntity amark\ele,1,1,interpolate(EntityDistance(amark\ele,node2),2,4,1,2)
End Function
While Not KeyDown(1)
If KeyDown(200) MoveEntity cam_player,0,0,.2
If KeyDown(208) MoveEntity cam_player,0,0,-.2
If KeyDown(203) MoveEntity cam_player,-.2,0,0
If KeyDown(205) MoveEntity cam_player,.2,0,0
TurnEntity cam_player,MouseYSpeed()/12.0,-MouseXSpeed()/12.0,0
RotateEntity cam_player,EntityPitch(cam_player),EntityYaw(cam_player),0
MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
;--------------
If KeyHit(28)
parent=-1
reset=True
FIND_PATH(node1,node2)
EndIf
UpdateWorld
;----------------
RenderWorld
;--------------------------------------------------
;-------------- NODES EDITING -----------------
If KeyHit(82) ;Numpad 0
path_editing=Not path_editing
If path_editing=1
FlushMouse:FlushKeys
For p=0 To path_maxnodes;999
If paths1(p,0)>0
ShowEntity paths1(p,0)
EndIf
Next
Else
For p=0 To path_maxnodes;999
If paths1(p,0)>0
HideEntity paths1(p,0)
EndIf
Next
EndIf
EndIf
If path_editing
CREATE_PATH()
SHOW_NODES_STATS()
;SHOW THE PATH
If reset=True
If Len(path_total)>0
reset=False
For l=1 To Len(path_total)/2
s1$=Mid(path_total,l*2-1,2)
s2$=Mid(path_total,l*2-1+2,2)
If Len(s1)>0 And Len(s2)>0
ADD_MARKER(s1,s2)
EndIf
Next
EndIf
EndIf
Text GraphicsWidth()/2,5,"NODES >ED<",1
Else
For amark.paths_marks=Each paths_marks
FreeEntity amark\ele
Delete amark
Next
EndIf
;--------------------------------------------------
;--------------------------------------------------
Color 255,0,0
Oval GraphicsWidth()/2-3,GraphicsHeight()/2-3,6,6,0
Color 255,255,255
Text 10,100,"Nearest node to camera: "+GET_NEARNODE(cam_player)
Text 10,120,"Selected node: "+path_nodeselected
Text 10,140,"path_total: "+path_total
Text 10,160,"Path: from <"+node1+"> to <"+node2+">"
Text 10,180,"Enem_Path: "+enem_path
Text 10,200,"Finding: "+finding
Text 10,5,"F1-Help | Use Numpad 0 to enable/disable NODES editing"
Text 10,20,"polys: "+TrisRendered()
If KeyHit(17) w=Not w WireFrame w
Flip
Wend
MoveMouse 400,300:End