rem #################### Pathfinding System #####################
rem Originally coded by JessTicular
rem Modified by Sjakie
rem This is a complete pathfinding system. the unit cant go into the holes,
rem because they're filled with "invisible water"... Lol :) ...
sync on
set camera range 10,10000
rem ************** 3d mouse objects ***********
rem make 3d mouse
make object sphere 9999,170
hide object 9999
rem make a 2d mouse (in 3d :) )
make object sphere 10000,10
position object 10000,0,0,100
lock object on 10000
hide object 10000
make object cube 1,20
make matrix 1,1000,1000,30,30
color object 1,rgb(255,0,0)
rem *******************************************
rem Build Test Landscape
set matrix 1,1,1,1,1,1,1,1
for x=0 to 30
for z=0 to 30
set matrix height 1,x,z,-70
next z
next x
for x=10 to 20
for z=0 to 12
set matrix height 1,x,z,-140
next z
next x
for x=10 to 14
for z=20 to 24
set matrix height 1,x,z,-140
next z
next x
for x=19 to 23
for z=15 to 19
set matrix height 1,x,z,-140
next z
next x
for x=19 to 23
for z=22 to 26
set matrix height 1,x,z,-140
next z
next x
update matrix 1
rem Matrix shading----------------------------------------
rem Use matrix normals to make it smooth
for z=1 to 30
for x=1 to 30
rem Get matrix heights
h8#=get matrix height(1,x,z-1)
h4#=get matrix height(1,x-1,z)
h#=get matrix height(1,x,z)
h2#=get matrix height(1,x,z)
rem Calculate projected angle X using heights
x1#=(x-1)*25.0 : y1#=h#
x2#=(x+0)*25.0 : y2#=h4#
dx#=x2#-x1#
dy#=y2#-y1#
ax#=atanfull(dx#,dy#)
ax#=wrapvalue(90-ax#)
rem Calculate projected angle Z using heights
z1#=(z-1)*25.0 : y1#=h2#
z2#=(z+0)*25.0 : y2#=h8#
dz#=z2#-z1#
dy#=y2#-y1#
az#=atanfull(dz#,dy#)
az#=wrapvalue(90-az#)
rem Make normal from projected angle
nx#=sin(ax#)
ny#=cos(ax#)
nz#=sin(az#)
rem Setting matrix normal for smoothness
set matrix normal 1,x,z,nx#,ny#,nz#
next x
next z
update matrix 1
rem camera settings
position camera 500,300,-300
pitch camera down 25
rem if unit moves or not
dim movestatus(1)
rem Posi are the positions - i divided the old pos(...) array into 2 arrays
rem 1 for Current positions (and 0 for direction -1 or 1), and Lastposi for
rem the last x and y position
dim Posi(2,1)
dim Lastposi(2,1)
rem This one is just for printing to the screen
dim PathLength(2)
rem ################## main loop #######################
do
rem If rightclick, go to that spot
if mouseclick()=2
Posi(1,1)=object position x(9999)
Posi(2,1)=object position z(9999)
Movestatus(1)=1
Posi(0,1)=0
endif
rem MOVEMENT
if Movestatus(1)=1
rem Point object, save old positions, move
Point object 1,Posi(1,1),object position y(1),Posi(2,1)
LastPosi(1,1)=object position x(1)
LastPosi(2,1)=object position z(1)
move object 1,3
rem check for path
UnitH=get ground height(1,object position x(1),object position z(1))
set cursor 5,70
print UnitH
position object 1,object position x(1),UnitH,object position z(1)
rem if unit needs a path
if UnitH<-90
_pathfind(1)
endif
rem if unit is away from the river (the height increases) reset direction
if UnitH>-80
posi(0,1)=0
endif
endif
rem if target reached, stop unit
if object position x(1)>Posi(1,1)-10
if object position x(1)<Posi(1,1)+10
if object position z(1)>Posi(2,1)-10
if object position z(1)<Posi(2,1)+10
Movestatus(1)=0
endif
endif
endif
endif
rem ************************** mouse code **********************
rem this code positions a 3d mouse object on the mouse coordinates
rem calculate angle from cam to mouse
SCH=screen height()/2
SCW=screen width()/2
move# =(mousex()-SCW)/4
move2# =(mousey()-SCH)/4
rem turn object and move mouse
turn object right 10000,90
move object 10000,move#
pitch object down 10000,90
move object 10000,move2#
rem synchronize
sync
rem place mouse back
move object 10000,move2#-move2#-move2#
pitch object up 10000,90
move object 10000,move#-move#-move#
turn object left 10000,90
depth=100
width=move#
LRang=atanfull(width,depth)
depth=100
width=move2#
UDang=atanfull(width,depth)
position object 9999,camera position x(),camera position y(),camera position z()
set object to camera orientation 9999
turn object right 9999,LRang
pitch object down 9999,UDang
for ScanH=0 to 1000
move object 9999,5
3dMH=get ground height(1,object position x(9999),object position z(9999))
rem if the 3dmouse hits the ground, it stays there
if object position y(9999)<3dMH
goto _Endloop
endif
next ScanH
_Endloop:
rem *********************************************************
rem print data
set cursor 5,5
print PathLength(1)
set cursor 5,15
print PathLength(2)
set cursor 5,30
print Posi(1,1)
set cursor 5,40
print Posi(2,1)
set cursor 5,60
print Posi(0,1)
rem Print Instuctions
set cursor 150,5
print "Rightclick to move unit"
rem FPS
set cursor 580,5
print Screen FPS()
loop
rem #################### FUNCTIONS #########################
function _pathfind(unitPF)
rem First, the best way needs to be calculated
if posi(0,unitPF)=0
posi(0,unitPF)=_find_dir(unitPF)
endif
rem And move the unit along its path
dist=3
temp2 = 0
While get ground height(1,object position x(UnitPF),object position z(UnitPF))<-90
`moves the object back to it's last posision as the Move Object command made it collide.
Position Object UnitPF,Lastposi(1,UnitPF),get ground height(1,Lastposi(1,UnitPF),Lastposi(2,UnitPF)),Lastposi(2,UnitPF)
`yrotates it slightly ( 6 degree's ) toward the "bridge"
YRotate Object UnitPF,WrapValue(Object Angle Y(UnitPF) + (6 * posi(0,unitPF)))
`moves the object forward again.
Move Object UnitPF,dist
`just a check that it doesn't get stuck in an endless loop
Inc temp2
If temp2 >= 30 Then Exit
EndWhile
endfunction
rem This function tests out BOTH paths and chooses the good one (or the shortest)
function _find_dir(unitPF)
rem Define checking distance (the smaller it is, the more precise
rem it is, but also slower...)
CHKDis=30
NCHKDis=-30
rem old values
OldX=object position x(unitPF)
OldY=object position y(unitPF)
OldZ=object position z(unitPF)
Path1LNG=0
Path2LNG=0
rem #################### Path 1 ###################
For move=1 to 100
inc Path1LNG
rem point object at target
point object UnitPF,Posi(1,UnitPF),object position y(UnitPF),Posi(2,UnitPF)
rem move object
move object UnitPF,CHKDis
rem check if object collides
temp2=0
While get ground height(1,object position x(UnitPF),object position z(UnitPF))<-90
move object UnitPF,NCHKDis
`yrotates it slightly ( 6 degree's ) toward the "bridge"
YRotate Object UnitPF,WrapValue(Object Angle Y(UnitPF) + (6 * 1))
`moves the object forward again
Move Object UnitPF,CHKDis
`just a check that it doesn't get stuck in an endless loop
Inc temp2
If temp2 >= 30 Then Exit
EndWhile
rem Check if unit is still in the landscape
if _inMatrix(UnitPF)=0
Path1LNG=10000
Exit
endif
rem if target reached, stop unit
if object position x(UnitPF)>Posi(1,UnitPF)-10
if object position x(UnitPF)<Posi(1,UnitPF)+10
if object position z(UnitPF)>Posi(2,UnitPF)-10
if object position z(UnitPF)<Posi(2,UnitPF)+10
Exit
endif
endif
endif
endif
next move
rem reset positions
position object UnitPF,oldx,oldy,oldz
rem #################### Path 2 ###################
For move=1 to 100
inc Path2LNG
rem point object at target
point object UnitPF,Posi(1,UnitPF),object position y(UnitPF),Posi(2,UnitPF)
rem move object
move object UnitPF,CHKDis
rem check if object collides
temp2=0
While get ground height(1,object position x(UnitPF),object position z(UnitPF))<-90
move object UnitPF,NCHKDis
`yrotates it slightly ( 6 degree's ) toward the "bridge"
YRotate Object UnitPF,WrapValue(Object Angle Y(UnitPF) + (6 * -1))
`moves the object forward again.
Move Object UnitPF,CHKDis
`just a check that it doesn't get stuck in an endless loop
Inc temp2
If temp2 >= 30 Then Exit
EndWhile
rem Check if unit is still in the landscape
if _inMatrix(UnitPF)=0
Path2LNG=10000
Exit
endif
rem if target reached, stop unit
if object position x(UnitPF)>Posi(1,UnitPF)-10
if object position x(UnitPF)<Posi(1,UnitPF)+10
if object position z(UnitPF)>Posi(2,UnitPF)-10
if object position z(UnitPF)<Posi(2,UnitPF)+10
Exit
endif
endif
endif
endif
next move
rem calculate the shortest path (a bad path is always 10000 so way too long)
Pathlength(1,1)=Path1LNG
Pathlength(2,1)=Path2LNG
Calcdir=-1
if Path1LNG<path2LNG then Calcdir=1
rem reset positions of unit
position object UnitPF,oldx,oldy,oldz
endfunction CalcDir
rem this function checks if the unit stays within the landscape
Function _inMatrix(unitNumber)
MatrixResult=1
if object position x(unitNumber)<10 then MatrixResult=0
if object position z(unitNumber)<10 then MatrixResult=0
if object position x(unitNumber)>990 then MatrixResult=0
if object position z(unitNumber)>990 then MatrixResult=0
endfunction MatrixResult
some changes are made... if you need help, just ask
Juzt a dude who likez progging