ok so i am making going to try to make a kind of RTS / Tower defence where i would need to have fairly good pathfinding.
because the enemies are zombies, the pathfinding doesnt need to return the shortest possible path but it as long as the route is fairly fast it should do.
Also the map im going to use will only have fairly large and rectangular obstacles so the pathfinding system wont have to face extreme mazes.
so what i would like some kind soul to tell me is what problems are there in my code and what could i do to make it work better?
i have this code here :
Rem Project: zombie
Rem Created: Sunday, December 18, 2011
Rem ***** Main Source File *****
sync on : sync rate 60 : w = screen width() : h = screen height()
global node_dist = 10
node_dificulty = 5
node_xcount = w/node_dist : node_ycount = h/node_dist
dim n(node_xcount,node_ycount) as UDTnode
for i = 1 to node_xcount : for j = 1 to node_ycount
n(i,j).x# = i*node_dist : n(i,j).y# = j*node_dist
n(i,j).cost# = 1
if rnd(node_dificulty) > 1 then n(i,j).exist = 1
n(i,j).i = i : n(i,j).j = j
NEXT : next
for i = 2 to node_xcount-1 : for j = 2 to node_ycount-1
if n(i,j).exist = 0
accepted = 0
if n(i-1,j).exist = 0 then accepted = 1
if n(i+1,j).exist = 0 then accepted = 1
if n(i,j+1).exist = 0 then accepted = 1
if n(i,j-1).exist = 0 then accepted = 1
if accepted = 0 then n(i,j).exist = 1
ENDIF
NEXT : next
node_color1 = rgb(40,80,160)
node_color2 = rgb(160,80,40)
node_color3 = rgb(60,120,240)
node_color4 = rgb(255,40,10)
dim open(9) as UDTnode
dim path(100000) as UDTnode
do
mx# = mousex() : my# = mousey()
node_mx = getnode(mx#) : node_my = getnode(my#)
for i = 2 to node_xcount-1 : for j = 2 to node_ycount-1
if n(i,j).exist = 1 then a2dot n(i,j).x#,n(i,j).y#,node_color1
if n(i,j).exist = 0
a2dot n(i,j).x#,n(i,j).y#,node_color2
if n(i,j).status = 1 then a2circle n(i,j).x#,n(i,j).y#,5,rgb(255,0,0)
if n(i-1,j).exist = 0 then a2line n(i,j).x#,n(i,j).y#,n(i-1,j).x#,n(i-1,j).y#,node_color2
if n(i,j-1).exist = 0 then a2line n(i,j).x#,n(i,j).y#,n(i,j-1).x#,n(i,j-1).y#,node_color2
endif
NEXT : next
for i = 1 to pathlength
if i > 1 then a2line n(path(i).i,path(i).j).x#,n(path(i).i,path(i).j).y#,n(path(i-1).i,path(i-1).j).x#,n(path(i-1).i,path(i-1).j).y#,node_color4
NEXT
if mouseclick() = 1 and clicked = 0
if n(node_mx,node_my).exist = 1
zx# = n(node_mx,node_my).x# : zy# = n(node_mx,node_my).y#
node_zx = node_mx : node_zy = node_my
gosub _getpath:
clicked = 1
endif
else
if mouseclick() = 0 then clicked = 0
endif
if mouseclick() = 2
if n(node_mx,node_my).exist = 1 then targetx# = n(node_mx,node_my).x# : targety# = n(node_mx,node_my).y#
node_targetx = node_mx : node_targety = node_my
ENDIF
print A_closedcount
a2circle targetx#,targety#,node_dist,node_color3
a2circle targetx#,targety#,node_dist/2,node_color3
a2circle zx#,zy#,node_dist/2,node_color4
a2circle zx#,zy#,node_dist/4,node_color4
sync
cls
LOOP
_getpath:
for i = 1 to pathlength
n(path(i).i,path(i).j).status = 0
NEXT
A_closedcount = 0
repeat
n(node_zx,node_zy).status = 1
A_opencount = 0
for k = node_zx-1 to node_zx+1 : for o = node_zy-1 to node_zy+1
if k > 0 and k < node_xcount and o > 0 and o < node_ycount
if n(k,o).status = 0 and n(k,o).exist = 1
inc A_opencount : open(A_opencount).i = k : open(A_opencount).j = o
rem open(A_opencount).value = abs(k-node_targetx)+abs(o-node_targety)+abs(k-node_zx)*0.5+abs(o-node_zy)*0.5
open(A_opencount).value# = dist(k,o,node_targetx,node_targety)
endif
endif
NEXT : next
if A_opencount = 0
A_failcheck = 0
repeat
inc A_failcheck
node_zx = path(A_closedcount-A_failcheck).i : node_zy = path(A_closedcount-A_failcheck).j
for k = node_zx-1 to node_zx+1 : for o = node_zy-1 to node_zy+1
if k > 0 and k < node_xcount and o > 0 and o < node_ycount
if n(k,o).status = 0 and n(k,o).exist = 1
inc A_opencount : open(A_opencount).i = k : open(A_opencount).j = o
rem open(A_opencount).value = abs(k-node_targetx)+abs(o-node_targety)+abs(k-node_zx)+abs(o-node_zy)
open(A_opencount).value# = dist(k,o,node_targetx,node_targety)
endif
endif
NEXT : next
until A_opencount > 0
endif
if A_opencount > 0
A_openmin# = 100000 : A_openmini = 0
for i = 1 to A_opencount
if open(i).value# < A_openmin# then A_openmin# = open(i).value# : A_openmini = i
NEXT
inc A_closedcount
if A_closedcount < 10000
path(A_closedcount).i = open(A_openmini).i : path(A_closedcount).j = open(A_openmini).j
node_zx = path(A_closedcount).i : node_zy = path(A_closedcount).j
endif
endif
until path(A_closedcount).i = node_targetx and path(A_closedcount).j = node_targety or A_closedcount > 10000
pathlength = A_closedcount
return
type UDTnode
x# : y#
cost# : exist
i : j
px : py
status
value#
endtype
type UDTzombiedata
hp# : arm# : spd# : trn# : dmg# : ref#
img : sprt : snd
endtype
type UDTzombie
x# : y# : z#
vec
tx# : ty#
hp# : arm# : spd# : trn# : dmg# : ref#
img : sprt : snd
exist : dead
pathlength
dat as UDTzombiedata
endtype
function nodedot(x#,y#)
x = getnode(x#) : y = getnode(y#) : nx# = n(x,y).x# : ny# = n(x,y).y#
a2fillcircle nx#,ny#,2,rgb(255,255,255)
ENDFUNCTION
function getnode(x#)
c = int(x#/node_dist+0.5)
ENDFUNCTION c
function dist(x1#,y1#,x2#,y2#)
d# = sqrt((x1#-x2#)^2+(y1#-y2#)^2)
ENDFUNCTION d#
it is a working example wich i made, but it sometimes chooses quite odd paths and doesnt work 100% of the times.
change the variable node_difficulty to change obstacle count, dont try lower that four, wont give you good results
OH and it uses advanced 2d for drawing
below is the uglier slower and more booring (but working) code without advanced 2d
Rem Project: zombie
Rem Created: Sunday, December 18, 2011
Rem ***** Main Source File *****
sync on : sync rate 60 : w = screen width() : h = screen height()
global node_dist = 10
node_dificulty = 5
node_xcount = w/node_dist : node_ycount = h/node_dist
dim n(node_xcount,node_ycount) as UDTnode
for i = 1 to node_xcount : for j = 1 to node_ycount
n(i,j).x# = i*node_dist : n(i,j).y# = j*node_dist
n(i,j).cost# = 1
if rnd(node_dificulty) > 1 then n(i,j).exist = 1
n(i,j).i = i : n(i,j).j = j
NEXT : next
for i = 2 to node_xcount-1 : for j = 2 to node_ycount-1
if n(i,j).exist = 0
accepted = 0
if n(i-1,j).exist = 0 then accepted = 1
if n(i+1,j).exist = 0 then accepted = 1
if n(i,j+1).exist = 0 then accepted = 1
if n(i,j-1).exist = 0 then accepted = 1
if accepted = 0 then n(i,j).exist = 1
ENDIF
NEXT : next
node_color1 = rgb(40,80,160)
node_color2 = rgb(160,80,40)
node_color3 = rgb(60,120,240)
node_color4 = rgb(255,40,10)
dim open(9) as UDTnode
dim path(100000) as UDTnode
do
mx# = mousex() : my# = mousey()
node_mx = getnode(mx#) : node_my = getnode(my#)
for i = 2 to node_xcount-1 : for j = 2 to node_ycount-1
if n(i,j).exist = 1 then dot n(i,j).x#,n(i,j).y#,node_color1
if n(i,j).exist = 0
dot n(i,j).x#,n(i,j).y#,node_color2
if n(i,j).status = 1 then circle n(i,j).x#,n(i,j).y#,5
if n(i-1,j).exist = 0 then line n(i,j).x#,n(i,j).y#,n(i-1,j).x#,n(i-1,j).y#
if n(i,j-1).exist = 0 then line n(i,j).x#,n(i,j).y#,n(i,j-1).x#,n(i,j-1).y#
endif
NEXT : next
for i = 1 to pathlength
if i > 1 then line n(path(i).i,path(i).j).x#,n(path(i).i,path(i).j).y#,n(path(i-1).i,path(i-1).j).x#,n(path(i-1).i,path(i-1).j).y#
NEXT
if mouseclick() = 1 and clicked = 0
if n(node_mx,node_my).exist = 1
zx# = n(node_mx,node_my).x# : zy# = n(node_mx,node_my).y#
node_zx = node_mx : node_zy = node_my
gosub _getpath:
clicked = 1
endif
else
if mouseclick() = 0 then clicked = 0
endif
if mouseclick() = 2
if n(node_mx,node_my).exist = 1 then targetx# = n(node_mx,node_my).x# : targety# = n(node_mx,node_my).y#
node_targetx = node_mx : node_targety = node_my
ENDIF
print A_closedcount
circle targetx#,targety#,node_dist
circle targetx#,targety#,node_dist/2
circle zx#,zy#,node_dist/2
circle zx#,zy#,node_dist/4
sync
cls
LOOP
_getpath:
for i = 1 to pathlength
n(path(i).i,path(i).j).status = 0
NEXT
A_closedcount = 0
repeat
n(node_zx,node_zy).status = 1
A_opencount = 0
for k = node_zx-1 to node_zx+1 : for o = node_zy-1 to node_zy+1
if k > 0 and k < node_xcount and o > 0 and o < node_ycount
if n(k,o).status = 0 and n(k,o).exist = 1
inc A_opencount : open(A_opencount).i = k : open(A_opencount).j = o
rem open(A_opencount).value = abs(k-node_targetx)+abs(o-node_targety)+abs(k-node_zx)*0.5+abs(o-node_zy)*0.5
open(A_opencount).value# = dist(k,o,node_targetx,node_targety)
endif
endif
NEXT : next
if A_opencount = 0
A_failcheck = 0
repeat
inc A_failcheck
node_zx = path(A_closedcount-A_failcheck).i : node_zy = path(A_closedcount-A_failcheck).j
for k = node_zx-1 to node_zx+1 : for o = node_zy-1 to node_zy+1
if k > 0 and k < node_xcount and o > 0 and o < node_ycount
if n(k,o).status = 0 and n(k,o).exist = 1
inc A_opencount : open(A_opencount).i = k : open(A_opencount).j = o
rem open(A_opencount).value = abs(k-node_targetx)+abs(o-node_targety)+abs(k-node_zx)+abs(o-node_zy)
open(A_opencount).value# = dist(k,o,node_targetx,node_targety)
endif
endif
NEXT : next
until A_opencount > 0
endif
if A_opencount > 0
A_openmin# = 100000 : A_openmini = 0
for i = 1 to A_opencount
if open(i).value# < A_openmin# then A_openmin# = open(i).value# : A_openmini = i
NEXT
inc A_closedcount
if A_closedcount < 10000
path(A_closedcount).i = open(A_openmini).i : path(A_closedcount).j = open(A_openmini).j
node_zx = path(A_closedcount).i : node_zy = path(A_closedcount).j
endif
endif
until path(A_closedcount).i = node_targetx and path(A_closedcount).j = node_targety or A_closedcount > 10000
pathlength = A_closedcount
return
type UDTnode
x# : y#
cost# : exist
i : j
px : py
status
value#
endtype
type UDTzombiedata
hp# : arm# : spd# : trn# : dmg# : ref#
img : sprt : snd
endtype
type UDTzombie
x# : y# : z#
vec
tx# : ty#
hp# : arm# : spd# : trn# : dmg# : ref#
img : sprt : snd
exist : dead
pathlength
dat as UDTzombiedata
endtype
function getnode(x#)
c = int(x#/node_dist+0.5)
ENDFUNCTION c
function sqaredist(x1#,y1#,x2#,y2#)
d# = (x1#-x2#)^2+(y1#-y2#)^2
ENDFUNCTION d#
function dist(x1#,y1#,x2#,y2#)
d# = sqrt((x1#-x2#)^2+(y1#-y2#)^2)
ENDFUNCTION d#
oh and here is am image that demonstrates the weaknesses of my code