3d walkpath

Blitz3D Forums/Blitz3D Beginners Area/3d walkpath

nibby(Posted 2003) [#1]
hi guys.
I'm having alot of trouble with creating a walkpath for one of my little gamedudes. my plan is to have a "gaurd" on a set patrol path walking round and round then if he spots the player he will give chase and eventually try to kill the player.

I've been advised before to use nodes types and arrays (which i'm not sure how to do) i've looked at some of the pathfinding stuff in the code archives and worklogs and it all looks a little over complecated for what i'm trying to do.

any example code you can donate would be appreciated.

heres what i've done so far:
http://homepage.ntlworld.com/maxhyper/maxhyperv2.6.zip

thanks
nibby


semar(Posted 2003) [#2]
[EDITED - See bottom of message]
Hi nibby,
I just want to give you some advice about a 3d walkpath.

For example:
- put some waypoint in the 3d world that should be reached by your character;

- each waypoint has a flag that indicates if it has been already reached or not (I reccomend to use types here for waypoints, because the structure can hold several fields and flags you may need)

- start to patrol your character in this way:
-- search for the nearest waypoint (scan the whole waypoints list and use entitydistance to calculate the distance, then consider the nearest waypoint. If a waypoint has been already reached (flag reached = true) then discard it from the search)

-- turn the character toward the choosen waypoint

-- move the character until it reaches the waypoint (use collision, or use entitydistance again: move the character until its distance from the waypoint is less than 1, for example

-- once the waypoint has been reached, set the flag 'reached' of the waypoint to true, and search for another nearest waypoint

-- once all the waypoints are reached, reset all the waypoint flag, and start again with the first step.

-- during the patrol, check for the player; if it is on the view range of the character, then... attack ! ;-)

Hope this has sense for you,
Sergio.

P.S.
To put waypoints on a map, you can use also the brilliant Dropper program - search on the forum or at blitzcoder.
[EDIT] That program is known as DROPLET [/EDIT]


EOF(Posted 2003) [#3]
Something I knocked up a while ago:

FlightPath Recorder



It may help you with your problem.
The example has a ship entity which you move/rotate around.
Pressing SPACE records its position/orientation.
Your can save [F4] and reload [F8] the recorded path.

The best part is, on playback you don't have to worry about updating or keeping tabs on your entity.
You just call

Animate myentity

Then, during you main loop the UpdateWorld does the business.

To use the saved 'flightpath.dat' in your game just pop the LoadFlightPath() function in there. Then do:
success=LoadFlightPath("flightpath.dat",entity,speed#)
If success then Animate entity


Here is the FlightPath recording source code ....


; FlightPath - record/save example
; By Syntax Error

Const sw=640,sh=480

Type flightpath
	Field ent
	Field x#,y#,z#
	Field pitch#,yaw#,roll#
End Type
Global pathnode.flightpath

Type markertype
	Field ent
End Type
Global marker.markertype

; ***********************************************************

Graphics3D sw,sh,0,2
SetBuffer BackBuffer()
SetFont LoadFont("Tahoma.ttf",17,1)
HidePointer
SeedRnd 27128

; ~~~~~~ for FreeLook function
Global FL_Pitch#,FL_Yaw#,FL_Roll#,FL_XSpeed#,FL_YSpeed#,FL_ZSpeed#
; ~~~~~~

; ***********************************************************

; camera
cam=CreateCamera() : PositionEntity cam,0,12,-11
CameraClsColor cam,50,80,120
RotateEntity cam,8,0,0

; light
light=CreateLight() : PositionEntity light,4,4,-6
RotateEntity light,7,-2,0

; plane
plane=CreatePlane(8) : EntityColor plane,0,100,0

; some random buildings
For d=1 To 70
	building=CreateCube()
	ScaleEntity building,0.6,5,1.2
	EntityColor building,Rand(80),Rand(80),Rand(80)
	PositionEntity building,Rnd(-90,90),5,Rnd(-90,90)
Next

; create a ship
ship=CreateCube()
MoveEntity ship,0,5,0
ScaleEntity ship,0.7,0.2,2.7
EntityColor ship,100,200,250
wing=CreateCube(ship)
MoveEntity wing,0,0,-0.6
ScaleEntity wing,2.3,0.2,0.2
tip=CreateCube(ship)
MoveEntity tip,0,2,-0.6
ScaleEntity tip,0.1,1,0.2


; ***********************************************************

; game loop
Repeat

	If testmode=True
		Gosub 	ShowAnimation
	Else
		Gosub ControlShip
	EndIf	

	Flip
Until KeyHit(1)
End

; ***********************************************************

; manipulate ship with mouse
; record / save / test
.ControlShip
	; controls
	dx#=KeyDown(205)-KeyDown(203) ; cursor left/right
	dz#=KeyDown(208)-KeyDown(200) ; cursor up/down
	dy#=KeyDown(209)-KeyDown(201) ; Page Up/Down
	MoveEntity  ship,dx/7,-dy/7,-dz/7
	mb=MouseDown(1)+MouseDown(2)*2
	If mb<>0
		mx#=MouseXSpeed() : my#=MouseYSpeed()
		MoveMouse sw/2,sh/2
		If mb=2	TurnEntity ship,0,0,-mx/15
		If mb=1	TurnEntity ship,my/15,-mx/15,0
	Else
		Freelook cam
	EndIf
	
	RenderWorld
	
	If KeyHit(57) ; [SPACEBAR] record ships position/rotation
		RecordPosition ship,True
		Message "* Position recorded *"
	EndIf

	If KeyHit(62)	 ; [F4] save flightpath
		SaveFlightPath "flightpath.dat"
		Message "FlightPath SAVED"
	EndIf

	If KeyHit(46) ; [C] clears flightpath
		Delete Each flightpath
		For marker=Each markertype
			FreeEntity marker\ent
			Delete marker
		Next
		Message "Current path CLEARED"
	EndIf
	
	If KeyHit(66) ; [F8] for test
		ship2=CopyEntity(ship)
		EntityColor ship2,200,150,250
		success=LoadFlightPath("flightpath.dat",ship2,30)
		If success
			testmode=True
			Message "Testing ..."
			Animate ship2
			HideEntity ship
			For marker=Each markertype
				HideEntity marker\ent
			Next
		Else
			Message "NO 'flightpath.dat' file found"
			FreeEntity ship2
		EndIf
	EndIf

	; info
	Color 200,200,200
	Text 10,10,"Move ship with Cursors and PageUp/Down"
	Text 10,30,"Rotate ship with mouse and LMB/RMB"
	Text 30,65,"Record position with [SPACEBAR]"
	Text 30,85,"Save 'flightpath.dat' with [F4]"
	Text 20,115,"Test with [F8]"
	Text sw/2,sh-50,"Move camera with [W] [S] [A] [D] [R] [F] ... mouse to look around",True
	countnodes=0
	For pathnode=Each flightpath
		countnodes=countnodes+1
	Next	
	Color 100,250,100
	Text 20,sh-20,"Total path nodes = "+countnodes+"       [C] to clear path"
Return


; ***********************************************************

; show the flightpath animation in action
.ShowAnimation
	UpdateWorld
	RenderWorld
	PointEntity cam,ship2
	Color 200,200,40
	Text 20,20,"FlightPath test.       Press [Q] to exit ..."
	If KeyHit(16) ; [Q]
		testmode=False
		FreeEntity ship2
		ShowEntity ship
		For marker=Each markertype
			ShowEntity marker\ent
		Next
	EndIf
Return


; ***********************************************************

Function Message(t$)
	Color 250,0,0 : Cls
	Text sw/2,sh*0.6,t$,True
	Flip : Delay 450
End Function

; free look with mouse & keys
Function FreeLook(FL_Cam)
	FL_Pitch#=FL_Pitch#-(MouseYSpeed()*0.02) : FL_Pitch#=FL_Pitch#/1.2
	FL_Yaw#=FL_Yaw#+-(MouseXSpeed()*0.02) : FL_Yaw#=FL_Yaw#/1.2
	MoveMouse (GraphicsWidth()/2,GraphicsHeight()/2)
	FL_ZSpeed#=FL_ZSpeed#+Float(KeyDown(17)-KeyDown(31))*0.12 : FL_ZSpeed#=FL_ZSpeed#/1.14;  [w] & [s]
	FL_XSpeed#=FL_XSpeed#+Float(KeyDown(32)-KeyDown(30))*0.12 : FL_XSpeed#=FL_XSpeed#/1.14 ; [a] & [d]
	FL_YSpeed#=FL_YSpeed#+Float(KeyDown(19)-KeyDown(33))*0.12 : FL_YSpeed#=FL_YSpeed#/1.14 ; [r] & [f]
	FL_Roll#=(FL_Yaw#*1.1)-(FL_XSpeed#*2.3)
	MoveEntity FL_Cam,FL_XSpeed#,FL_YSpeed#+Abs(FL_Roll#*FL_XSpeed#)/50,FL_ZSpeed#
	Local cp#=EntityPitch(FL_Cam,True)+FL_Pitch#
	If Abs(cp)>89 Then cp=Sgn(cp)*89
	RotateEntity FL_Cam,cp,EntityYaw(FL_Cam)+FL_Yaw#,FL_Roll#
End Function




; ***********************************************************
; Flightpath functions
; ***********************************************************

; records entity position/rotation to flight path
Function RecordPosition(entity,markerflag=False)
	pathnode=New flightpath
	pathnode\x=EntityX(entity)
	pathnode\y=EntityY(entity)
	pathnode\z=EntityZ(entity)
	pathnode\pitch=EntityPitch(entity)
	pathnode\yaw=EntityYaw(entity)
	pathnode\roll=EntityRoll(entity)
	If markerflag
		marker=New markertype
		marker\ent=CopyEntity(entity)
		PositionEntity marker\ent,pathnode\x,pathnode\y,pathnode\z
		RotateEntity marker\ent,pathnode\pitch,pathnode\yaw,pathnode\roll
		EntityColor marker\ent,140,60,60
	EndIf
End Function

Function SaveFlightPath(filename$)
	file=WriteFile(filename$)
	If file>0
		; count nodes in flight path
		numpathnodes=0
		For pathnode=Each flightpath
			numpathnodes=numpathnodes+1
		Next
		; record to file
		WriteInt file,numpathnodes
		; record postion/rotation of each path node
		For pathnode=Each flightpath
			WriteFloat file,pathnode\x
			WriteFloat file,pathnode\y
			WriteFloat file,pathnode\z
			WriteFloat file,pathnode\pitch
			WriteFloat file,pathnode\yaw
			WriteFloat file,pathnode\roll
		Next
		CloseFile file
	EndIf
End Function

; load flight path and attach entity
; keyframespacing determines speed/smoothness of path
Function LoadFlightPath(filename$,entity,keyframespacing=10)
	file=ReadFile(filename$)
	If file>0
		numpathnodes=ReadInt(file)
		Local keypos=0
		; record entity in its current starting position
		SetAnimKey entity,0
		; set postion/rotation of each path node and record
		For d=1 To numpathnodes
			x#=ReadFloat(file) : y#=ReadFloat(file) :	z#=ReadFloat(file)
			pitch#=ReadFloat(file) : yaw#=ReadFloat(file) :	roll#=ReadFloat(file)
			keypos=keypos+1
			PositionEntity entity,x,y,z
			RotateEntity entity,pitch,yaw,roll
			SetAnimKey entity,keypos*keyframespacing
		Next
	EndIf
	AddAnimSeq entity,keypos*keyframespacing
	Return file>0
End Function



Gauge(Posted 2003) [#4]
I'm not sure if this would be a waste of memory or any thing. But you could attach a camera to the guards view(maybe even pivot with his head,etc). And then just check if the camera can see the the character?


Murphy(Posted 2003) [#5]
@Gauge
=======

well - think about it... if you see the enemy, then the enemy sees you ;)
so.... entityinview
;)
P.S.: don't even think about 'on-sided-mirrors' *lol*


Binary_Moon(Posted 2003) [#6]
"well - think about it... if you see the enemy, then the enemy sees you ;)"

Not if they are looking the other way they can't

try this

http://www.blitzbasic.com/codearcs/codearcs.php?code=532

This works out the angle from one object to the other. If the objetc being looked at is within the required view 'zone' then it is checked to see if the object doing th elooking can actually see the other objetc (a wall might be in the way)


nibby(Posted 2003) [#7]
[Edit]----Problem solved now guys thank you ;0)



thanks for your efforts guys.
i think i still got some work to do before i get this thing down but i appriciate you trying to help ;0)

semar: i think i need to improve my coding abilities abit to figure out how to do what you said. i'm getting there slowly tho.

Syntax Error: i got all that working but when i play back the recorded animation i cant seem to get my chatacter to look at a node ie. with Pointentity. also i'm not sure wether i will be able to break out of the animation to have him chase my character.

Gauge & binary moon: that idea looks as tho it will work but i gotta get the dude moving before i can really try it... but thanks for the example it will come in handy later.

thanks again dudes. and if anyone has any other ideas, feel free to give me a shout

Nibby