waypoint help

Blitz3D Forums/Blitz3D Programming/waypoint help

vibe37(Posted 2004) [#1]
Hey guys,
I need a simple waypoint system to make patrol paths for the enemies in my next project, similar to the one in the fps example provided with Blitz 3d (\samples\si\fps\fps.bb). Only thing is, I don't understand the waypoint code :( Can somebody explain it to me?
In case you're to lazy to look it up ;) I pasted the relevant part of the code. Perhaps you can just comment the code so that it is easier to understand?

Thanks in advance,
Kungfista

P.S.: Other waypoint examples are also welcome!

 
; Gargoyle speed, yaw values
Global garg_speed#=0.2,garg_yaw#

Global node=2	; Node gargoyle aims for	

Dim node_x(10)
Dim node_y(10)
Dim node_z(10)
Dim node_n(10,3)
Dim node_v(10)

node_x(1)=390	; x position of first node
node_y(1)=160	; y position of first node
node_z(1)=50	; z position of first node
node_n(1,0)=1	; no of connected nodes
node_n(1,1)=2	; no of the first connected node
node_v(1)=1		; visits to first node by gargoyle

node_x(2)=390	; x position of second node
node_y(2)=160	; y position of second node
node_z(2)=190	; z position of second node
node_n(2,0)=2	; no of connected nodes
node_n(2,1)=3	; no of the first connected node
node_n(2,2)=1	; no of the second connected node

node_x(3)=210	; etc
node_y(3)=120	; etc
node_z(3)=190	; etc
node_n(3,0)=2	; etc
node_n(3,1)=4	; etc
node_n(3,2)=2	; etc

;[...]

Function GargPath()

	PointEntity gargoyle,target_piv

	dest_garg_yaw=EntityYaw(gargoyle)

	If dest_garg_yaw-garg_yaw>180 Then garg_yaw=garg_yaw+360
	If dest_garg_yaw-garg_yaw<-180 Then garg_yaw=garg_yaw-360

	garg_yaw=garg_yaw+((dest_garg_yaw-garg_yaw)/(5/garg_speed))

	MoveEntity gargoyle,0,0,garg_speed
	RotateEntity gargoyle,0,garg_yaw,0

	garg_x=EntityX(gargoyle)
	garg_y=EntityY(gargoyle)
	garg_z=EntityZ(gargoyle)

	If garg_x=node_x(node)
		If garg_y=node_y(node)
			If garg_z=node_z(node)
	
				least=1000000
				node_v(node)=(MilliSecs()-old_time)/1000
				For i=1 To node_n(node,0)
					nv=node_v(node_n(node,i))
					If nv<least Then least=nv : lnode=i
				Next
				node=node_n(node,lnode)

				PositionEntity target_piv,node_x(node),node_y(node),node_z(node)
				
			EndIf
		EndIf
	EndIf

End Function



Ross C(Posted 2004) [#2]
Hey man. I did this for 2d. dunno if it's any use to you :)

Graphics 800,600
SetBuffer BackBuffer()

Global max_path_points=100

Dim pathx#(max_path_points-1); set up 101 path points
Dim pathy#(max_path_points-1); -1 because arrays start at zero

Global path_counter=-1
Global current_path=0
Global cx#=0
Global cy#=0
Global movement_started=0


While Not KeyHit(1)
	Cls
	
	If MouseHit(1) Then
			setpath(MouseX(),MouseY()); set path point with the mouses current coords
	End If
	
	If KeyHit(57) And movement_started=0 And path_counter>0 Then; if spacebar pressed then move rectangle
		current_path=0; reset the current path to 0
		cx=pathx(0); set the rectangles coords to the first path point
		cy=pathy(0)
		movement_started=1; set flag for movement started
	End If
	If KeyHit(28) Then; if the enter key is pressed then stop movement
		movement_started=0; clear flag for movement
		cx=pathx(0); set rectangle coords to the first path point
		cy=pathy(0)
		current_path=-1; set current path to none exsistant
	End If

	
	
	
	draw_path_points(); function for drawing the pathpoints
	If movement_started=1 Then move(); draw the moving rectangle and move it
	Color 200,200,200; set drawing color
	Rect MouseX()-1,MouseY()-1,2,2; draw mouse location with a rectangle
	Text 0,0,"Click mouse to set path point. Press spacebar to start animation. Press enter to stop."
	Text 0,10,"movement started="+movement_started
	Flip
Wend
End

Function move()
	ang#=0
	If current_path<path_counter Then; make sure the current path point is less than the highest
		ang=ATan2(pathy(current_path+1)-pathy(current_path),pathx(current_path+1)-pathx(current_path))
		;/\ basically means find the angle between the current path point and the next one /\
		cx=cx+Cos(ang); increase the x coord of the rect following the path points based on the angle
		cy=cy+Sin(ang); increase the y coord of the rect following the path points based on the angle
		Color 100,200,100; change drawing color
		Rect cx-3,cy-3,6,6; draw the rectangle central to it's coords
		If Abs(cx-pathx(current_path+1))<1 And Abs(cy-pathy(current_path+1))<1 Then
			; /\ if the rects coords are with a 1 pixel distance of the path point then /\
			current_path=current_path+1; increase the current path point number
			cx=pathx(current_path); set the rectangles coords to that of the next path point
			cy=pathy(current_path)
		End If
	End If
End Function

Function setpath(x,y)
	path_counter=path_counter+1; increase counter
        If path_counter>max_path_points-1 Then; if counter is higher than the available number of path points then set it back
               path_counter=max_path_points-1
        Else; else 
	       pathx(path_counter)=x; record the x and y positions
	       pathy(path_counter)=y
        End If
End Function

Function draw_path_points()
	For loop=0 To path_counter; loop through all the path points
		Color 100,100,200
		Rect pathx(loop),pathy(loop),2,2
		If loop<path_counter Then; do this loop while the loop value is less than the highest path value
			Rect pathx(loop+1)-1,pathy(loop+1)-1,2,2; draw a rectangle at the path point so its central
			Color 50,50,150; change drawing color
			Line pathx(loop),pathy(loop),pathx(loop+1),pathy(loop+1); draw a line between the current point and the next one
		End If
	Next
End Function




puki(Posted 2004) [#3]
Add the following before the main loop:

visible_node=CreateSphere()
For a=1 To 10
CopyEntity visible_node()
PositionEntity visible_node, node_x(a), node_y(a), node_z(a)
Next

Now you will see the waypoints as little domes on the walkways.

The gargoyle is walking towards the 'target_piv'. 'target_piv' is updated and moved on to the next node based on that nodes coordinates in 3D space.


puki(Posted 2004) [#4]
Woops - with regard to 'CopyEntity visible_node()' - just use CopyEntity visible_node - without the '()' on the end.


Also, in the main loop - just under the ';FPS' section, but before the 'Flip' command, add:

Text 0,10,"The gargoyle is walking towards node: "+node

Now you will know which node the gargoyle is heading to - as well as being able to see them.


jfk EO-11110(Posted 2004) [#5]
To create waypoints you would maybe best write a waypoint recorder. So YOU walk trough the level, in first person perspective, and your way is recorded and then used for the patrols.

you can use timebased recording or distancebased recording, it doesn't matter that much.

Try something like:
dim wp#(2,100000)
while not keydown(1)
 ; here would be player controls
 if millisecs()>tt
  tt=millisecs()+200 ; record a point every 200ms
  wp(0,count)=entityx(player)
  wp(1,count)=entityy(player)
  wp(2,count)=entityz(player)
  count=count+1
 endif
 renderworld()
 flip
wend

wr=writefile("waypoint.dta")
for i=0 to count-1
writefloat wr,wp(0,i)
writefloat wr,wp(1,i)
writefloat wr,wp(2,i)
next
closefile wr


and to load the waypoints you would hen have to:

;first check how many waypoint must be reserved
;(maybe this could be done more clever, eg. by filesize/12)
count=0
re=readfile("waypoint.dta")
while eof(re)=0
 dummy#=readfloat(re)
 dummy#=readfloat(re)
 dummy#=readfloat(re)
 count=count+1
wend
closefile re

dim wp#(2,count-1)

re=readfile("waypoint.dta")
for i=0 to count-1
 wp(0,i)=readfloat(re)
 wp(1,i)=readfloat(re)
 wp(2,i)=readfloat(re)
next
closefile re



vibe37(Posted 2004) [#6]
Thanks for your help!
@puki: Visual waypoints are a good idea, perhaps they give me some hints on how the whole thing works

@ross c: Nice little wp system you got there but I think 3d is another story... but your code will definitely be useful for my current 2d project!

@jfk: Wow, that's an elegant way to place waypoints - definitely cooler than placing the nasty things manually

I really have to take a VERY close look at that gargoyle example...

Regards,
Kungfista