## AI TANKS first draft

Game development specific discussions.
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

### Re: AI TANKS first draft

dafhi wrote:took a while
still won't be that fast b/c of point and pset.

Taking the trig computations out of the loop is a good start.
Maybe pointers to the source and destination bitmap to read and write the pixel values?
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

### Re: AI TANKS first draft

paul doe wrote:
BasicCoder2 wrote:The next step should I bother to expand the demo is to make some AI so each team of tanks can seek out the other team and fight it out.

Do you have an idea as to how you're going to tackle this one?

Yes I have worked on simple agent AI before but like those efforts I will probably not end up not finishing any Tank AI simulation beyond a demo.
viewtopic.php?f=8&t=24615
Path finding, which is essentially a GPS system, may well be part of a game. For example if low on fuel or ammunition use GPS to find fuel or ammunition depot. I did look at "heat maps" but settled for the Dijkstra's algorithm in past AI implementations.
Say, you'll be better off in the end using vectors and vector arithmetic.

In the past I just found giving an agent a direction and a speed more intuitive than giving them vector numbers for direction and speed.
dafhi
Posts: 1220
Joined: Jun 04, 2005 9:51

### Re: AI TANKS first draft

BasicCoder2 wrote:Taking the trig computations out of the loop is a good start.
Maybe pointers to the source and destination bitmap to read and write the pixel values?

update 3
Last edited by dafhi on Sep 16, 2018 19:03, edited 1 time in total.
dodicat
Posts: 5225
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: AI TANKS first draft

Basiccoder's tank:
Here is the trig out and a scaler in.
Also direct pixels drawing.
(scaled by 4 here in the parameter sc)

Code: Select all

`  'some useful definesConst Pi = 4 * Atn(1)Dim Shared As single TwoPi = 8 * Atn(1)Dim Shared As single RtoD = 180 / Pi   ' radians * RtoD = degreesDim Shared As single DtoR = Pi / 180   ' degrees * DtoR = radiansconst SCRW = 640const SCRH = 480screenres SCRW,SCRH,32'bitmaps useddim shared as any ptr TB,TTTB = imagecreate(35,35)'  bload "tankBody.bmp",TBTT = imagecreate(35,35)'  bload "tankTurret.bmp",TTdim shared as any ptr backGroundbackGround = imagecreate(1024,480)' bload "backGround2.bmp",backGround    dim shared as integer imgW,imgH    imgW = 35    imgH = 35    dim as ulong colors( 6)colors(0)=RGB(255,0,255)colors(1)=RGB(0,0,0)colors(2)=RGB(166,202,240)colors(3)=RGB(0,160,192)colors(4)=RGB(192,192,192)colors(5)=RGB(128,128,128)dim as integer nfor j as integer = 0 to  34    for i as integer = 0 to  34        read n        pset TT,(i,j),colors(n)    next inext jfor j as integer = 0 to  34    for i as integer = 0 to  34        read n        pset TB,(i,j),colors(n)    next inext jSub rotateimage(im As Any Ptr,angle As single,shiftx As long=0,shifty As long=0,sc As Single=4,miss as ulong=rgb(255,0,255))    static As Integer pitch,pitchs,xres,yres,runflag    static As Any Ptr row    static As integer ddx,ddy,resultx,resulty    Imageinfo im,ddx,ddy,,pitch,row   if runflag=0 then Screeninfo xres,yres,,,pitchS:runflag=1    Dim As Any Ptr rowS=Screenptr    Dim As long centreX=ddx\2,centreY=ddy\2    Dim As Single sx=Sin(angle)    Dim As Single cx=Cos(angle)    Dim As long mx=Iif(ddx>=ddy,ddx,ddy),shftx,shfty    Var fx=sc*.7071067811865476,sc2=1/sc     shiftx+=centreX*sc-centrex     shiftY+=centrey*sc-centrey    For y As long=centrey-fx*mx+1 To centrey+ fx*mx         dim as single sxcy=Sx*(y-centrey),cxcy=Cx*(y-centrey)        shfty=y+shifty        For x As long=centrex-mx*fx To centrex+mx*fx                  if x+shiftx >=0 then 'on the screen                    if x+shiftx <xres then                        if shfty >=0 then                            if shfty<yres then            resultx=sc2*(Cx*(x-centrex)-Sxcy) +centrex:resulty=sc2*(Sx*(x-centrex)+Cxcy) +centrey                if resultx >=0 then 'on the image                    if resultx<ddx then                        if resulty>=0 then                            if resulty<ddy then    dim as ulong u=*cast(ulong ptr,row+pitch*((resultY))+((resultX)) Shl 2 ) 'point(image)   if u<>miss then *cast(ulong ptr,rowS+pitchS*(y+shifty)+(x+shiftx) Shl 2)= u 'pset (screen)                End If:end if:end if:end if                End If:end if:end if:end if        Next x    Next yEnd Subsub rotateImage2(img as any ptr, angle as single, x as integer, y as integer)    dim as double tx,ty,nx,ny,vx,vy    angle = angle*DtoR       dim as ulong c    for yp as single = 0 to imgH-1 step .5        for xp as single = 0 to imgW-1 step .5                         c = point(xp,yp,img):'get color            if c<>rgb(255,0,255) then                'select centre of image as centre of rotation                vx = xp-(imgW\2)                vy = yp-(imgH\2)                     'equations to compute new x,y coordinates for rotation of ww degrees                tx = cos(angle) * vx - sin(angle) * vy                ty = cos(angle) * vy + sin(angle) * vx                      nx = tx+(imgW\2)                ny = ty+(imgH\2)                pset (nx+x,ny+y),c                end if         next xp    next ypend subput (100,100),TB,transprint "press a key"dim as single angle1,angle2sleepdo    screenlock    cls    rotateImage(TB,angle1,320,240)    rotateImage(TT,angle2,320,240)    screenunlock    angle2 = angle2 + 1/10    sleep 20loop until multikey(&H01)DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,0,0,0,0,0,1,1,0,0,0DATA  0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,2,1,3,3,1,1,1,1,1,1,3,3,1,0,0DATA  0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,1,1,1,2,2,2,1,3,3,3,3,3,3,3,3,3,3,1,0,0DATA  0,0,0,0,0,0,0,0,0,1,2,2,2,2,1,1,1,1,1,2,2,1,3,3,1,1,1,1,1,1,3,3,1,0,0DATA  0,0,0,0,0,0,0,0,0,1,2,2,2,2,1,1,1,1,1,2,2,1,1,1,1,0,0,0,0,0,1,1,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,1,1,1,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0DATA  0,0,0,0,1,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,1,0,0,0,0DATA  0,0,0,0,1,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,1,0,0,0,0DATA  0,0,0,0,1,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,1,0,0,0,0DATA  0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0DATA  0,0,0,0,0,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,1,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,0,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,0,0,0,0,0,0DATA  0,0,0,0,0,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,1,0,0,0,0,0DATA  0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0DATA  0,0,0,0,1,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,1,0,0,0,0DATA  0,0,0,0,1,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,1,0,0,0,0DATA  0,0,0,0,1,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,1,0,0,0,0DATA  0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  `
Posts: 1003
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: AI TANKS first draft

dafhi wrote:BasicCoder2's rotate blit optimized and using ptrs
[update 2] - source read needed to not go past src_w (and h) - 0.5, so i made the limit src_ - .501

Code: Select all

`sub rotateImage(img as any ptr, angle as single, x as single, y as single)        '' trying to be more accommodating to bit depths    static as integer des_w, des_h, pitch_des, bpp, rate, num_pages    dim as any ptr  p_des = screenptr    static as string  driver_name    ScreenInfo des_w,des_h, bpp, num_pages, pitch_des, rate, driver_name        static as integer  src_w, src_h, bypp, pitch_src    static as any ptr  p_src    ImageInfo img, src_w, src_h, bypp, pitch_src, p_src        dim as integer  pitch_des_by = pitch_des \ bypp      ''    dim as single tx,ty,vx '' changed from double    dim as single cosa = cos(angle*DtoR), wh = imgW/2    dim as single sina = sin(angle*DtoR), hh = imgH/2    y += hh    x += wh        var _step = .9    var cosa_vx = cosa * _step    var sina_vx = sina * _step      '' 2018 Sep 15    var x_des_limit = des_w - .5    var y_des_limit = des_h - .5        for yp as single = .499 to imgH - .501 step _step ''2018 Sep 16 .. (.499 to avoid banker's round)                var cosa_vy = cosa * (yp-hh) + y        var sina_vy = sina * (yp-hh) - x        var x_des = cosa_vx * (.5 - wh) - sina_vy        var y_des = sina_vx * (.5 - wh) + cosa_vy                select case as const bypp        case 4                    dim as integer  y_pitch_src = int(yp) * pitch_src          dim as ulong ptr  psrc = p_src + y_pitch_src          dim as ulong ptr  pdes = p_des              for xp as single = .499 to imgW - .501 step _step '' 2018 Sep 16              if x_des >=0 andalso x_des < x_des_limit then                if y_des >=0 andalso y_des < y_des_limit then                                    'dim as ulong c = point(xp,yp,img):'get color                                    if psrc[xp]<>rgb(255,0,255) then                      'pset (x_des,y_des),psrc[xp]                      pdes[ int(y_des + .5) * pitch_des_by + x_des ] = psrc[xp]                  end if                                endif              endif              x_des += cosa_vx              y_des += sina_vx           next xp                End Select            next ypend sub`

[previous post] - took a while
still won't be that fast b/c of point and pset

Code: Select all

`sub rotateImage(img as any ptr, angle as single, x as single, y as single)    dim as single tx,ty,vx '' changed from double    dim as single cosa = cos(angle*DtoR), wh = imgW/2    dim as single sina = sin(angle*DtoR), hh = imgH/2    y += hh    x += wh    var _step = .9    var cosa_vx = cosa * _step    var sina_vx = sina * _step    for yp as single = .5 to imgH-.5 step _step        dim as single cosa_vy = cosa * (yp-hh) + y        dim as single sina_vy = sina * (yp-hh) - x        var x_dest = cosa_vx * (.5 - wh) - sina_vy        var y_dest = sina_vx * (.5 - wh) + cosa_vy        for xp as single = .5 to imgW-.5 step _step            dim as ulong c = point(xp,yp,img):'get color            if c<>rgb(255,0,255) then                pset (x_dest,y_dest),c            end if            x_dest += cosa_vx            y_dest += sina_vx         next xp    next ypend sub`

I used this code in 2012, also to rotate a tank image:

Code: Select all

`sub sprite_rotate(srcImg as any ptr, dstImg as any ptr, rotation as single, defaultColour as integer)  'replace point & pset with direct memory access  dim as integer srcWidth, srcHeight, srcPitch, dstPitch  dim as single xctr, yctr  dim as integer xdst, ydst  dim as integer xsrc, ysrc  dim as ulong colour 'was integer  dim as single ySin, yCos  dim as single sinRot = sin(rotation)  dim as single cosRot = cos(rotation)    dim as ulong ptr scrPixels, dstPixels 'was integer  imageInfo srcImg, srcWidth, srcHeight, , srcPitch, scrPixels  imageInfo dstImg,         ,          , , dstPitch, dstPixels  dstPitch shr= 2  srcPitch shr= 2      xctr = srcWidth / 2  yctr = srcHeight / 2  screenlock  for ydst = 0 to srcHeight-1    ySin = (yctr - ydst) * sinRot + xctr + 0.5    yCos = (ydst - yctr) * cosRot + yctr + 0.5    for xdst = 0 to srcWidth-1      xsrc = int((xdst - xctr) * cosRot + ySin)      ysrc = int((xdst - xctr) * sinRot + yCos)      if (xsrc >= 0) and (xsrc < srcWidth) and (ysrc >= 0) and (ysrc < srcHeight) then        'colour = point(xsrc, ysrc, srcImg)        colour = scrPixels[ysrc * srcPitch + xsrc]      else        colour = defaultColour      end if      'pset dstImg, (xdst, ydst), colour      dstPixels[ydst * dstPitch + xdst] = colour    next  next  screenunlockend sub`

Old image, the most right tank is an rotation with an image-editor using anti-aliasing, that was a problem with transparency:

For performance reasons I rendered a bunch of rotated tank images in advance.
Last edited by badidea on Sep 24, 2018 21:50, edited 1 time in total.
paul doe
Posts: 803
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: AI TANKS first draft

BasicCoder2 wrote:Yes I have worked on simple agent AI before but like those efforts I will probably not end up not finishing any Tank AI simulation beyond a demo.

Doesn't matter. Learning is what really counts =D
BasicCoder2 wrote:Path finding, which is essentially a GPS system, may well be part of a game. For example if low on fuel or ammunition use GPS to find fuel or ammunition depot. I did look at "heat maps" but settled for the Dijkstra's algorithm in past AI implementations.

Indeed. But you should really switch to a Flow Field implementation. They have many advantages over traditional Dijkstra's or A* (even though they use Dijkstra's algorithm to calculate the distance for the paths):

You see, they efficiently support huge number of agents, can efficiently handle different terrain costs, and are simpler to conceptualize and work with that just plain A*. They're also more efficient to compute, handle dynamic terrain easily, and you can pre-compute as many of them as you wish (for example, to mark 'goal' nodes for ammunition and fuel depots, using your example), and they will give agents very intelligent behaviors with little computational cost. And, they lend themselves well for parallelization.

In the image, you can see the debug info of a cost-efficient path query. There's multiple goals (the green circles), and the blue arrows show the path an agent will take to reach the closest goal node should they start in that square. The pale green squares are traversable but costly terrain (think swamps or forests), the grey squares represent easily traversable terrain (think roads and such) and the orange squares are traversable but very penalized terrain (think lava pools and such). The black squares are impassable terrain, and the red squares are unreachable locations (yes, these are also quite easily identified by the algorithm). The number on the top left of the square is the distance that Dijkstra's algorithm calculates, and there's also the traversal cost (not shown here), so you can query a path either using the distance (I-don't-care-just-go-there type query) or the cost (which you can use to give agents quite intelligent behaviors, such as using bridges, roads and such), using the same map.

All in all, you can't lose by using them =D
BasicCoder2 wrote:In the past I just found giving an agent a direction and a speed more intuitive than giving them vector numbers for direction and speed.

Hard to see the advantages for me, but to each its own =D
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

### Re: AI TANKS first draft

BasicCoder2 wrote:
In the past I just found giving an agent a direction and a speed more intuitive than giving them vector numbers for direction and speed.

paul doe replied:
Hard to see the advantages for me, but to each its own =D

Computationally there is no advantage. I have to translate the direction,speed into a change in the x and y coordinates.
However in everyday life we talk about travelling in a particular direction (degrees) at a particular speed.

With path finding a game programmer just wants to get a path (a list of positions) between two points.

Take this example:
The blue agents start off in the "wander" state until they by chance collide with a mushroom. They "have mushroom" state (red), and then compute a path to their home base. They are then in the "follow path" state until they arrive at their home base and store the mushroom at which point they change back to the "wander" state (blue).

So you would be suggesting a flow field implementation replacement for the path acquisition function.
agents(i).path = makePath(agents(i).target.x,agents(i).target.y,(agents(i).x\16),(agents(i).y\16))

Code: Select all

`' uses a modified version of Patrick Lester's example as modified by coderJeff.' http://www.execulink.com/~coder/freebasic/astar.html#include once "fbgfx.bi"const NULL = 0type v2D    as integer x    as integer yend typetype APATH    as v2D p(1000)  'need to make this variable    as integer pCount   'length of pathend typeconst MAPW = 40const MAPH = 30const CELL_COUNT = MAPW * MAPH#define CELLINDEX(x,y) ((MAPW*(y))+(x))const STATE_NONE = 0const STATE_OPEN = 1const STATE_CLOSED = 2type Cell   x as integer   y as integer   IsSolid as integer   parent as Cell Ptr   state as integer     'open or closed   f as integer   g as integer   h as integerend typedim shared Map( 0 to CELL_COUNT - 1 ) as CELLdim shared StartIndex  as integerdim shared pStartCell  as Cell ptrdim shared EndIndex    as integerdim shared pEndCell    as Cell ptrsub CellClearAll()   for y as integer = 0 to MAPH - 1      for x as integer = 0 to MAPW - 1         with Map( CELLINDEX(x,y) )            .x = x            .y = y            .IsSolid  = FALSE         end with      next   nextend subsub CellSetSolid( byval x as integer, byval y as integer, byval flag as integer )   dim n as integer = CELLINDEX(x,y)   Map( n ). IsSolid = flagend subsub CellSetStart( byval x as integer, byval y as integer )   StartIndex = CELLINDEX(x,y)   pStartCell = @Map( StartIndex )end subsub CellSetEnd( byval x as integer, byval y as integer )   EndIndex = CELLINDEX(x,y)   pEndCell = @Map( EndIndex )end subsub CellToggleSolid( byval x as integer, byval y as integer )   with Map( CELLINDEX(x,y) )      if( .IsSolid ) then         .IsSolid = FALSE      else         .IsSolid = TRUE      end if   end withend sub'' ------------------------------------------------------------------'' A* Computations'' ------------------------------------------------------------------''function ASTAR_GetLowestF( ) as CELL ptr   dim c as CELL ptr = NULL   for i as integer = 0 to CELL_COUNT - 1      if( Map( i ).State = STATE_OPEN ) then         if( c = NULL ) then            c = @Map(i)         else            if( Map(i).f < c->f ) then               c = @Map(i)            end if         end if      end if   next   function = cend function''function ASTAR_CheckNeighbour( byval parent as CELL ptr, byval x as integer, byval y as integer, cost as integer ) as integer   function = FALSE   if( x < 0 or x >= MAPW ) then      exit function   end if   if( y < 0 or y >= MAPH ) then      exit function   end if   dim c as CELL ptr = @Map( CELLINDEX(x, y) )   if( c->IsSolid ) then      exit function   end if   if( c->state = STATE_OPEN ) then      if( parent->g + cost < c->g ) then         c->state = STATE_NONE      end if   elseif( c->state = STATE_CLOSED ) then      if( parent->g + cost < c->g ) then         c->state = STATE_NONE      end if   end if   if( c->state = STATE_NONE ) then      c->state = STATE_OPEN      c->g = parent->g + cost      '' This is the Manhattan Distance Heuristic      c->h = abs( c->x - pEndCell->x ) * 10 + abs( c->y - pEndCell->y ) * 10      c->f = c->g + c->h      c->parent = parent   end if   function = TRUEend function''function ASTAR_CheckNeighbours( byval parent as CELL Ptr, byval x as integer, byval y as integer ) as integer   const DIR_N = 1   const DIR_S = 2   const DIR_W = 4   const DIR_E = 8   dim flag as integer   '' Check all orthogonal directions first N S E W   if( ASTAR_CheckNeighbour( parent, x - 1, y    , 10 ) ) then      flag or= DIR_W   end if   if( ASTAR_CheckNeighbour( parent, x    , y - 1, 10 ) ) then      flag or= DIR_N   end if   if( ASTAR_CheckNeighbour( parent, x    , y + 1, 10 ) ) then      flag or= DIR_S   end if   if( ASTAR_CheckNeighbour( parent, x + 1, y    , 10 ) ) then      flag or= DIR_E   end if   '' Only allow a diagonal movement if both orthogonal   '' directions are also allowed    if( ( flag and ( DIR_N or DIR_W )) = ( DIR_N or DIR_W ) ) then      ASTAR_CheckNeighbour( parent, x - 1, y - 1, 14 )   end if   if( ( flag and ( DIR_S or DIR_W )) = ( DIR_S or DIR_W ) ) then      ASTAR_CheckNeighbour( parent, x - 1, y + 1, 14 )   end if   if( ( flag and ( DIR_N or DIR_E )) = ( DIR_N or DIR_E ) ) then      ASTAR_CheckNeighbour( parent, x + 1, y - 1, 14 )   end if   if( ( flag and ( DIR_S or DIR_E )) = ( DIR_S or DIR_E ) ) then      ASTAR_CheckNeighbour( parent, x + 1, y + 1, 14 )   end if   function = 0end function''sub ASTAR_Compute()   dim c as CELL ptr   for i as integer = 0 to CELL_COUNT - 1      Map(i).parent = NULL      Map(i).state = STATE_NONE      Map(i).f = 0      Map(i).g = 0      Map(i).h = 0   next   c = pStartCell   c->State = STATE_OPEN   do      c = ASTAR_GetLowestF()      if( c = NULL ) then         exit do      elseif( c = pEndCell ) then         exit do      end if      c->state = STATE_CLOSED      ASTAR_CheckNeighbours( c, c->x, c->y )   loopend subfunction makePath(x2 as integer,y2 as integer,x1 as integer,y1 as integer) as APATH    dim as APATH path    dim as integer count    CellSetStart(x2,y2)  'target    CellSetEnd(x1,y1)    ASTAR_Compute()    dim c as CELL ptr = pEndCell        path.pCount = 0    while( c->parent )        path.p(count).x = c->x        path.p(count).y = c->y        count = count + 1        c = c->parent    wend    path.pCount = count    return pathend function'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'   MAIN PROGRAM'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~const WORLDW = 40       'must be same as MAPW and MAPH in ASTAR ROUTINE HEADERconst WORLDH = 30type AGENT    as integer x         'current position    as integer y    as integer dx        'velocity between -1 and +1    as integer dy    as integer item      'item held by agent    as integer itemCount 'count items collected        'required for astar routine    as APATH    path'path list    as integer counter   'position so far    as integer onThePath 'moving along path    as v2D     target    'desired targetend typedim shared as integer agentCountagentCount = 4dim shared as AGENT agents(0 to agentCount)'===========================const SCRW = 900const SCRH = 480const TILEW = 16const TILEH = 16screenres SCRW, SCRH, 32color rgb(0,0,0),rgb(255,255,255):cls'=============================================='create image blockdim shared as any ptr imageimage = imagecreate(16,96)dim as ulong colors(9)colors(0)=RGB(255,0,255)colors(1)=RGB(255,0,0)colors(2)=RGB(255,255,255)colors(3)=RGB(0,0,255)colors(4)=RGB(0,0,0)colors(5)=RGB(0,255,0)colors(6)=RGB(136,0,21)colors(7)=RGB(127,127,127)colors(8)=RGB(195,195,195)dim as integer nfor j as integer = 0 to  95    for i as integer = 0 to  15        read n        pset image,(i,j),colors(n)    next inext j'==============================================dim shared as integer sx,sy,ex,ey'dim shared as any ptr worldBlock16'worldBlock16 = imagecreate(16*16,16*16)'bload "tileBlock16A.bmp",worldBlock16    'load bitmap tile blockdim shared as integer world(WORLDW,WORLDH)sub drawWorld()    dim as integer x,y,n    screenlock        cls    for j as integer = 0 to  WORLDH-1        for i as integer = 0 to WORLDW-1            if world(i,j)<>0 then                n = world(i,j)  'get tile id                y = n                x = 0                'line (i*TILEW,j*TILEh)-(i*TILEW+TILEW-1,j*TILEH+TILEH-1),rgb(200,100,0),bf  'floor tile color                put (i*TILEW,j*TILEH),image,(x*TILEW,y*TILEH)-(x*TILEW+TILEW-1,y*TILEH+TILEH-1),trans                line (i*TILEW,j*TILEH)-(i*TILEW+TILEW,j*TILEH+TILEH),rgb(0,0,200),b            end if            line (i*TILEW,j*TILEH)-(i*TILEW+TILEH,j*TILEW+TILEH),rgb(100,100,100),b        next i    next j        'draw agents    for i as integer = 0 to agentCount                if agents(i).item = 0 then            put (agents(i).x,agents(i).y),image,(0,32)-(16,48),trans        else            put (agents(i).x,agents(i).y),image,(0,16)-(15,31),trans        end if                'draw homes        put (agents(i).target.x*TILEW,agents(i).target.y*TILEH),image,(0,80)-(15,95),trans                draw string (agents(i).x-8,agents(i).y),str(i)        locate (i+1)*2,82        print "agent";i;        for j as integer = 0 to agents(i).itemCount-1            put (716+j*16,i*16),image,(0,64)-(15,79),trans  'draw mushroom count        next j                'if agents(i).onThePath then        '    print "agent";i;" going home"        'end if    next i        screenunlockend subsub fillWorld()    for y as integer = 3 to MAPH-5        for x as integer = 0 to MAPW-1'            floor(x,y)=int(rnd(1)*2)+1            if int(rnd(1)*8)=0 then                CellSetSolid(x,y, TRUE )                if int(rnd(1)*4)=0 then                    world(x,y)=4  'mushroom                else                    world(x,y)=3  'tree                end if            end if        next x    next yend subsub followPath(ag as AGENT)    if ag.counter < ag.path.pCount then        ag.dx = ag.path.p(ag.counter).x - (ag.x\16)    'get direction to move        ag.dy = ag.path.p(ag.counter).y - (ag.y\16)        ag.counter = ag.counter + 1        'bump counter    else        ag.onThePath = 0        ag.item = 0       'drop item        ag.itemCount = ag.itemCount + 1  'count items dropped        ag.dx = 0        ag.dy = 0    end if    end subsub moveAgents(ag as AGENT)        dim as integer hit        dim as integer TILEX,TILEY                hit = 0        ag.x = ag.x + ag.dx        ag.y = ag.y + ag.dy                'out of bounds        if ag.x < 0 or ag.x > 640-16 or ag.y < 0 or ag.y > 480-16 then hit = 1        'test overlap of another tile        TILEX = int(ag.x/16)        TILEY = int(ag.y/16)        if world(TILEX,TILEY)<>0 then hit = 1        TILEX = int((ag.x+15)/16)        TILEY = int((ag.y)/16)        if world(TILEX,TILEY)<>0 then hit = 1        TILEX = int((ag.x)/16)        TILEY = int((ag.y+15)/16)        if world(TILEX,TILEY)<>0 then hit = 1        TILEX = int((ag.x+15)/16)        TILEY = int((ag.y+15)/16)        if world(TILEX,TILEY)<>0 then hit = 1        if hit = 1 then            ag.x = ag.x - ag.dx 'undo move            ag.y = ag.y - ag.dy             'new trial            ag.dx = int(rnd(1)*3)-1            ag.dy = int(rnd(1)*3)-1            while ag.dx = 0 and ag.dy = 0                ag.dx = int(rnd(1)*3)-1                ag.dy = int(rnd(1)*3)-1              wend        end if        end subsub update()        dim as integer hitTile        for i as integer = 0 to agentCount                hitTile = 0        if agents(i).x = int(agents(i).x\16)*16 and agents(i).y = int(agents(i).y\16)*16 then            hitTile = 1        end if                if hitTile = 1 then            if agents(i).onThePath = 1 then                followPath(agents(i))            end if        end if        if hitTile = 1 and agents(i).onThePath = 0 and int(rnd(1)*20)=0 then            agents(i).dx = int(rnd(1)*3)-1            agents(i).dy = int(Rnd(1)*3)-1            while agents(i).dx = 0 and agents(i).dy = 0                agents(i).dx = int(rnd(1)*3)-1                agents(i).dy = int(Rnd(1)*3)-1             wend        end if                dim as integer p,q                if hitTile = 1 and agents(i).onThePath = 0  then            for jj as integer = -1 to 1                for ii as integer = -1 to 1                    p = agents(i).x\16+ii                    q = agents(i).y\16+jj                    if p>0 and p<640 and q>0 and q<480 and agents(i).onThePath = 0 then                        if world(p,q) = 4 then 'FOUND MUSHROOM                            world(p,q) = 0           'remove from world                            CellSetSolid(p,q,FALSE)  'remove from ASTAR MAP                            agents(i).item = 1   'holding an item                            agents(i).path = makePath(agents(i).target.x,agents(i).target.y,(agents(i).x\16),(agents(i).y\16))                            agents(i).onThePath = 1                            agents(i).counter = 0    'zero agent current index position on path                        end if                    end if                                    next ii            next jj        end if                moveAgents(agents(i))            next i    drawWorld()    end sub'dim as integer x,yCellClearAll()'fill world with rocks and treesfillWorld()for i as integer = 0 to agentCount    agents(i).x = i*8*16    agents(i).y = 2*16    agents(i).target.x = i*8    agents(i).target.y = 28    agents(i).dx = int(rnd(1)*3)-1    agents(i).dy = int(Rnd(1)*3)-1    while agents(i).dx = 0 and agents(i).dy = 0        agents(i).dx = int(rnd(1)*3)-1        agents(i).dy = int(Rnd(1)*3)-1     wendnext idim as double now1now1 = timerdo        if timer > now1 + 0.01 then        now1 = timer        update()    end if        sleep 2loop until multikey(&H01)DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0DATA  0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0DATA  0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0DATA  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1DATA  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1DATA  1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1DATA  1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1DATA  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1DATA  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1DATA  1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1DATA  1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1DATA  1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1DATA  1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1DATA  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1DATA  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1DATA  0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0DATA  0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0DATA  0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0DATA  0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0DATA  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3DATA  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3DATA  3,3,3,3,2,2,3,3,3,3,2,2,3,3,3,3DATA  3,3,3,3,2,2,3,3,3,3,2,2,3,3,3,3DATA  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3DATA  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3DATA  3,3,3,3,2,2,2,2,2,2,2,2,3,3,3,3DATA  3,3,3,3,2,2,2,2,2,2,2,2,3,3,3,3DATA  3,3,3,3,3,3,2,2,2,2,3,3,3,3,3,3DATA  3,3,3,3,3,3,2,2,2,2,3,3,3,3,3,3DATA  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3DATA  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3DATA  0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0DATA  0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0DATA  0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0DATA  0,0,0,0,0,4,4,5,5,4,4,0,0,0,0,0DATA  0,0,0,0,0,4,4,5,5,4,4,0,0,0,0,0DATA  0,0,0,4,4,5,5,5,5,5,5,4,4,0,0,0DATA  0,0,0,4,4,5,5,5,5,5,5,4,4,0,0,0DATA  0,4,4,5,5,5,5,5,5,5,5,5,5,4,4,0DATA  0,4,4,5,5,5,5,5,5,5,5,5,5,4,4,0DATA  0,4,4,5,5,5,5,5,5,5,5,5,5,4,4,0DATA  0,4,4,5,5,5,5,5,5,5,5,5,5,4,4,0DATA  0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0DATA  0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0DATA  0,0,0,0,0,4,4,6,6,4,4,0,0,0,0,0DATA  0,0,0,0,0,4,4,6,6,4,4,0,0,0,0,0DATA  0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0DATA  0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0DATA  0,0,0,0,4,4,4,4,4,4,4,4,0,0,0,0DATA  0,0,4,4,4,4,7,4,4,8,8,8,4,4,0,0DATA  0,4,4,4,8,7,8,8,8,8,8,8,8,8,4,0DATA  0,4,4,8,4,8,8,8,8,8,8,8,8,8,8,4DATA  0,4,8,4,7,8,8,8,8,8,8,8,8,8,8,4DATA  0,4,7,8,7,8,7,7,7,7,8,8,8,8,8,4DATA  0,4,4,4,8,8,8,8,8,8,8,8,8,8,8,4DATA  0,4,4,4,4,4,4,4,7,7,7,8,8,4,4,0DATA  0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0DATA  0,0,0,4,4,4,4,4,4,4,4,0,0,0,0,0DATA  0,0,0,0,0,4,4,7,7,8,4,0,0,0,0,0DATA  0,0,0,0,0,4,4,7,7,7,4,0,0,0,0,0DATA  0,0,0,0,4,4,4,8,7,7,4,0,0,0,0,0DATA  0,0,0,0,4,4,4,8,8,4,4,0,0,0,0,0DATA  0,0,0,4,4,4,4,4,4,4,4,0,0,0,0,0DATA  0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0DATA  0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0DATA  0,0,0,0,0,0,4,1,1,4,0,0,0,0,0,0DATA  0,0,0,0,0,4,1,1,1,1,4,0,0,0,0,0DATA  0,0,0,0,4,1,1,1,1,1,1,4,0,0,0,0DATA  0,0,0,4,1,1,1,1,1,1,1,1,4,0,0,0DATA  0,0,4,1,1,1,1,1,1,1,1,1,1,4,0,0DATA  0,4,1,1,1,1,1,1,1,1,1,1,1,1,4,0DATA  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4DATA  4,7,7,7,7,7,7,7,7,7,7,7,7,7,7,4DATA  4,7,4,4,4,7,4,4,4,4,7,4,4,4,7,4DATA  4,7,4,3,4,7,4,5,5,4,7,4,3,4,7,4DATA  4,7,4,3,4,7,4,5,5,4,7,4,3,4,7,4DATA  4,7,4,4,4,7,4,5,5,4,7,4,4,4,7,4DATA  4,7,7,7,7,7,4,5,5,4,7,7,7,7,7,4DATA  4,7,7,7,7,7,4,5,5,4,7,7,7,7,7,4DATA  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4`
paul doe
Posts: 803
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: AI TANKS first draft

BasicCoder2 wrote:Computationally there is no advantage. I have to translate the direction,speed into a change in the x and y coordinates.

There IS a computational advantage. Which only gets greater the more points you need to transform.
BasicCoder2 wrote:However in everyday life we talk about travelling in a particular direction (degrees) at a particular speed.

Yes, indeed. It's more a question of mathematical reasoning. You seem to prefer the body syntonic type of reasoning. It's quite cool and probably you should implement the interface of the agents like that (so you can program the agents in a high-level fashion, giving them commands like 'rotate 90 left fire cannon'), but at the low level, vector math provides several advantages that you should consider.
BasicCoder2 wrote:With path finding a game programmer just wants to get a path (a list of positions) between two points.

Not always. How would you handle colliding agents?
BasicCoder2 wrote:So you would be suggesting a flow field implementation replacement for the path acquisition function.

Yes, exactly. With Flow Field, there's no 'path aquisition', the path is already calculated for all agents that share the same goal(s). The agents only have to follow it (see the picture that I posted before). It's like calculating A* once and then use it for all agents. This is why it can handle thousands of pathing agents at the same time, with minimal cost. Supreme Commander is a game that uses FFPF, as is Planetary Anihilation -these are RTS that have a massive scale. But besides scalability, it provides several advantages that I already mentioned.
Last edited by paul doe on Sep 17, 2018 2:16, edited 1 time in total.
dafhi
Posts: 1220
Joined: Jun 04, 2005 9:51

### Re: AI TANKS first draft

BasicCoder2 wrote:Computationally there is no advantage. I have to translate the direction,speed into a change in the x and y coordinates.

he was saying there's no computational advantage with his current system
paul doe
Posts: 803
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: AI TANKS first draft

dafhi wrote:he was saying there's no computational advantage with his current system

No, indeed. If he's to use vector math, he'll need to lay out things differently. We are discussing if the approach is worthwhile or not =D
dafhi
Posts: 1220
Joined: Jun 04, 2005 9:51

### Re: AI TANKS first draft

actually i take it back. maybe BC2 no likely the idea of a flow field for "all the vector calcs"

*yawn*

i need a new project
paul doe
Posts: 803
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: AI TANKS first draft

dafhi wrote:actually i take it back. maybe BC2 no likely the idea of a flow field for "all the vector calcs"

Perhaps, perhaps not. On any case, he's entitled to do whatever he thinks it's best for him. I suggested Flow Field Pathfinding because it's trivial to code, easy to use, and fits nicely with the concept he's developing =D
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

### Re: AI TANKS first draft

paul doe wrote:
BasicCoder2 wrote:With path finding a game programmer just wants to get a path (a list of positions) between two points.

Not always. How would you handle colliding agents?

Deal with the collision and then recompute the path.
the path is already calculated for all agents that share the same goal(s).

In the mushroom collector example they all have different homes to go to?

I am not fixed on any given solution for anything. I gave the mushroom example so you could demonstrate an alternative function to ASTAR. The bottom line is a game programmer figures out at a high level what to do and then has to have or write a set of functions to achieve that outcome. The direction, speed is how I think we think about it at a high level even if implementing it in code means converting it to a change in position along the x axis and the y axis. Think of how we might give a verbal description of how to get to some location. Agents could implement the same thing. Follow a road. Turn left at the intersection. Follow the river until you reach a bridge and cross over it. And so on ... Generating a path is really just implementing a GPS for the agent to make use of.

This doesn't have to be about tanks, it can be players in a soccer game, Vikings on a mission, Settlers building their village or the FB Community Game suggestion of players programming space ships in a shoot em up match.
Last edited by BasicCoder2 on Sep 17, 2018 6:17, edited 1 time in total.
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

### Re: AI TANKS first draft

Dafhi and dodicat,
Thanks for the code examples. I found dafhi's easier to understand :) Of course you don't have to understand how a function works, you only have to know how to use it. Writing a game is made much easier when you have a set of useful functions such as those to manipulate the sprite images. Any serious game library I would suggest would make use of SDL2.
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

### Re: AI TANKS first draft

BasicCoder2 wrote:
paul doe wrote:
BasicCoder2 wrote:With path finding a game programmer just wants to get a path (a list of positions) between two points.

Not always. How would you handle colliding agents?

Deal with the collision and then recompute the path.
Essentially push the goto X goal on a goal stack and pop it off after the current new goal (deal with collision) is complete.
the path is already calculated for all agents that share the same goal(s).

In the mushroom collector example they all have different homes to go to?

I am not fixed on any given solution for anything. I gave the mushroom example so you could demonstrate an alternative function to ASTAR. A game programmer figures out at a high level what to do and then has to have or write a set of functions to achieve that outcome. The direction, speed is how I think we think about it at a high level even if implementing it in code means converting it to a change in position along the x axis and the y axis. Think of how we might give a verbal description of how to get to some location. Agents could implement the same thing. Follow a road. Turn left at the intersection. Follow the river until you reach a bridge and cross over it. And so on ... Generating a path is really just implementing a GPS for the agent to make use of.

This doesn't have to be about tanks, it can be players in a soccer game, Vikings on a mission, Settlers building their village or the FB Community Game suggestion of players programming space ships in a shoot em up match.
Last edited by BasicCoder2 on Sep 17, 2018 9:43, edited 1 time in total.