Obstical Avoidance
Blitz3D Forums/Blitz3D Programming/Obstical Avoidance
| ||
I seem to be unable to get my brain around the method to make a character walk/move around objects to a target on the screen. Can anyone suggest a method. It's not like I am asking for the code ( which would be nice ) but an approach to the problem. Dicon |
| ||
You're referring to 'AI', entity movement and control. I suggest using nodes that can be followed in a path. Perhaps create an Array of nodes per object that can function as pivots, once the 'character' has reached the desired position it simply switches to the next node in the array in which to travel to. Now, positioning those nodes in order to navigate complex obstacles is really the issue. Mainly id recommend doing some sort of 'pick' to figure out the obstacle or issue to the character's path and then position the nodes accordingly in real time and once the player reaches a new node it does yet another 'pick'. Hope it helps. There's A LOT of ways to do this, this method may not be the fastest nor have i tested it. I use more 'freeworld' types of AI. Whereas the only obstacles may be a tree or rock or water. Rather than many walls or buildings. Concept Displayed here: ![]() But it really depends on what kind of effect you're looking for, if you're looking for a more like 'if i click here, i wanna move there' kinda deal and still do those things, that's probably much easier. As it involves less math. |
| ||
Here, i put this together to perhaps assist you in your understanding, this is FAR from perfect but it works about 70% of the time. It's accuracy is slightly off but it still works. Being that i spent about 15mins making it. Free to use, its whatever you make of it. The funny part is, is that i completely misunderstood the usage of 'linepicks' and yet it still created this result. Graphics3D 800,600,32,2 SetBuffer BackBuffer() Global AI_METHOD=1,PICK=0 Type Character Field Entity,X,Y,Z,Node[99],Modulus Field Target,Status$,Destination,CurrentNode,CurrentNodesNeeded End Type Type Obstacle Field Entity,x,y,z End Type Global Plane=CreatePlane() EntityPickMode Plane,2 MoveEntity Plane,0,-1,0 Global Light=CreateLight() RotateEntity Light ,45,45,0 Global Camera=CreateCamera() Global C.Character=New Character C\Entity=CreateCube() C\Target=CreateSphere() C\CurrentNode=1 ScaleEntity C\Target,2,2,2 EntityColor C\Target,10,10,10 HideEntity C\Target EntityColor C\Entity,255,0,0 ScaleEntity C\Entity,1,2,1 MoveEntity C\Entity,0,1,0 PositionEntity Camera,0,60,27.5 RotateEntity Camera,90,0,0 For obx=1 To 10 For oby=1 To 10 Obs.Obstacle=New Obstacle obs\entity=CreateCube() EntityColor obs\entity,Rand(255),Rand(255),Rand(255) ScaleEntity obs\entity,1,5,1 PositionEntity obs\entity,obx*10-(27.5*Rnd(1,3)),0,oby*Rnd(1,25) Obs\x=EntityX#(Obs\entity) Obs\y=EntityY#(Obs\entity) Obs\z=EntityZ#(Obs\Entity) EntityPickMode Obs\Entity,1 EntityRadius Obs\Entity,2 Next Next For nodes=1 To 99 C\Node[nodes]=CreateCube() EntityColor C\Node[nodes],255,0,255 HideEntity C\Node[nodes] Next UpdateWorld While Not KeyDown(1) Cls TranslateEntity Camera,0,-MouseZSpeed()*2,0 If MouseHit(1)=True If CameraPick(Camera,MouseX(),MouseY())<>0 ShowEntity C\Target PositionEntity C\Target,PickedX(),PickedY(),PickedZ() C\Destination=C\Target For nodes=1 To 99 PositionEntity C\Node[nodes],0,0,0 HideEntity C\Node[nodes] Next EntityPickMode C\Target,2 C\CurrentNode=1 C\CurrentNodesNeeded=1 EntityPickMode Plane,0 OBSTACLE=LinePick(EntityX(C\Entity),EntityY(C\Entity)+1,EntityZ(C\Entity),EntityX(C\Target),EntityY(C\Entity)+1,EntityZ(C\Target),2) If OBSTACLE<>0 And OBSTACLE<>C\Destination AI_METHOD=2 C\CurrentNodesNeeded=NodesNeeded(C\Entity,C\Target) PositionEntity C\Node[C\CurrentNodesNeeded+1],EntityX(C\Target),EntityY(C\Entity),EntityZ(C\Target) Else AI_METHOD=1 EndIf EntityPickMode Plane,2 EndIf EndIf If KeyHit(205)=True Then AI_METHOD=AI_METHOD+1 If KeyHit(203)=True Then AI_METHOD=AI_METHOD-1 If AI_METHOD<1 Then AI_METHOD=1 If AI_METHOD>2 Then AI_METHOD=2 For nodes=1 To C\CurrentNodesNeeded+1 ShowEntity C\Node[nodes] Next If C\Destination<>0 Select AI_METHOD Case 1 If EntityDistance(C\Destination,C\Entity)>2 PointEntity C\Entity,C\Destination RotateEntity C\Entity,0,EntityYaw(C\Entity),0 MoveEntity C\Entity,0,0,2 Else RotateEntity C\Entity,0,EntityYaw(C\Entity),0 C\Destination=0 EndIf Case 2 If EntityDistance(C\Destination,C\Entity)>2 If C\CurrentNode<1 Then C\CurrentNode=1 If C\CurrentNode<=99 If EntityDistance(C\Entity,C\Node[C\CurrentNode])<2 C\CurrentNode=C\CurrentNode+1 If C\CurrentNode>C\CurrentNodesNeeded+1 Then C\CurrentNode=C\CurrentNodesNeeded+1 Else PointEntity C\Entity,C\Node[C\CurrentNode] TurnEntity C\Entity,0,DeltaYaw#(C\Entity,C\Node[C\CurrentNode]),0 MoveEntity C\Entity,0,0,.2 EndIf EndIf Else RotateEntity C\Entity,0,EntityYaw(C\Entity),0 C\Destination=0 EndIf End Select EndIf UpdateWorld RenderWorld Color 0,0,0 CameraProject Camera,EntityX(C\Entity),EntityY(C\Entity),EntityZ(C\Entity) Text ProjectedX(),ProjectedY(),"Player" Text 0,0,"USING METHOD:"+AI_METHOD+" Nodes:"+C\CurrentNode+"/"+C\CurrentNodesNeeded For Nodes=1 To C\CurrentNodesNeeded CameraProject Camera,EntityX(C\Node[nodes]),EntityY(C\Node[nodes]),EntityZ(C\Node[nodes]) Local X1#=ProjectedX() : Local Y1#=ProjectedY() CameraProject Camera,EntityX(C\Node[nodes+1]),EntityY(C\Node[nodes+1]),EntityZ(C\Node[nodes+1]) Local X2#=ProjectedX() : Local Y2#=ProjectedY() Line X1#,Y1#,X2#,Y2# Next Flip 0 Wend End Function NodesNeeded(obs,dest) Local NodeUsed=1,NodePick EntityPickMode Plane,0 obs=LinePick(EntityX(C\Entity),EntityY(C\Entity)+1,EntityZ(C\Entity),EntityX(dest),EntityY(dest),EntityZ(dest),5) If obs If obs=dest EntityPickMode Plane,2 UpdateWorld 0 Return 1 EndIf PositionEntity C\Node[NodeUsed],EntityX(obs),EntityY(obs),EntityX(obs) Else PositionEntity C\Node[NodeUsed],EntityX(C\Entity),EntityY(C\Entity),EntityX(C\Entity) EndIf EntityPickMode Plane,0 Repeat NodePick=LinePick(EntityX(C\Node[NodeUsed]),EntityY(C\Node[NodeUsed]),EntityZ(C\Node[NodeUsed]),EntityX(dest),EntityY(dest),EntityZ(dest),1) If NodePick If NodeUsed+1<100 Local NX#=EntityX(NodePick) Local DX#=EntityX(dest) Local DELX#=(DX#-NX#) Local NZ#=EntityZ(NodePick) Local DZ#=EntityZ(dest) Local DELZ#=(DZ#-NZ#) PositionEntity C\Node[NodeUsed+1],EntityX(NodePick),EntityY(NodePick),EntityZ(NodePick) If DELX#>0 MoveEntity C\Node[NodeUsed+1],-3,0,0 Else MoveEntity C\Node[NodeUsed+1],3,0,0 EndIf If DELZ#>0 MoveEntity C\Node[NodeUsed+1],0,0,-3 Else MoveEntity C\Node[NodeUsed+1],0,0,3 EndIf NodeUsed=NodeUsed+1 EndIf Else EntityPickMode Plane,2 Return NodeUsed EndIf Until NodeUsed>=99 EntityPickMode Plane,2 Return 0 ;Can't resolve it. End Function |
| ||
Hi, here's a greater version of this earlier code. Now Works much faster and works about 99% of the time.Graphics3D 800,600,32,2 SetBuffer BackBuffer() Global AI_METHOD=1,PICK=0 Type Character Field Entity,X,Y,Z,Node[99],Modulus Field Target,Status$,Destination,CurrentNode,CurrentNodesNeeded End Type Type Obstacle Field Entity,x,y,z End Type Global Plane=CreatePlane() EntityPickMode Plane,2 MoveEntity Plane,0,-1,0 Global Light=CreateLight() RotateEntity Light ,45,45,0 Global Camera=CreateCamera() Global C.Character=New Character C\Entity=CreateCube() C\Target=CreateSphere() C\CurrentNode=1 ScaleEntity C\Target,.5,.5,.5 EntityColor C\Target,10,10,10 HideEntity C\Target EntityColor C\Entity,255,0,0 ScaleEntity C\Entity,1,2,1 MoveEntity C\Entity,0,1,0 RotateEntity Camera,90,0,0 For obx=1 To 10 For oby=1 To 10 Obs.Obstacle=New Obstacle obs\entity=CreateCube() EntityColor obs\entity,Rand(255),Rand(255),Rand(255) ScaleEntity obs\entity,1,5,1 PositionEntity obs\entity,obx*10-(27.5),0,oby*10 Obs\x=EntityX#(Obs\entity) Obs\y=EntityY#(Obs\entity) Obs\z=EntityZ#(Obs\Entity) EntityPickMode Obs\Entity,1 EntityRadius Obs\Entity,2 Next Next For nodes=1 To 99 C\Node[nodes]=CreateCube() EntityColor C\Node[nodes],0,128,255 ScaleEntity C\Node[nodes],.5,.5,.5 HideEntity C\Node[nodes] Next UpdateWorld While Not KeyDown(1) Cls TranslateEntity Camera,0,-MouseZSpeed()*2,0 PositionEntity Camera,EntityX(C\Entity),120,EntityZ(C\Entity) If MouseDown(1)=True If CameraPick(Camera,MouseX(),MouseY())<>0 ShowEntity C\Target PositionEntity C\Target,Ceil(PickedX()),EntityY(C\Entity),Ceil(PickedZ()) C\Destination=C\Target For nodes=1 To 99 HideEntity C\Node[nodes] Next EntityPickMode C\Target,0 C\CurrentNode=1 C\CurrentNodesNeeded=0 EntityPickMode Plane,0 OBSTACLE=LinePick(EntityX(C\Entity),EntityY(C\Entity),EntityZ(C\Entity),EntityX(C\Target)-EntityX(C\Entity),EntityY(C\Entity),EntityZ(C\Target)-EntityZ(C\Entity),1) If OBSTACLE<>0 AI_METHOD=2 C\CurrentNodesNeeded=NodesNeeded(C\Entity,C\Target) PositionEntity C\Node[1],EntityX(C\Entity),EntityY(C\Entity),EntityZ(C\Entity) PositionEntity C\Node[C\CurrentNodesNeeded+1],EntityX(C\Target),EntityY(C\Entity),EntityZ(C\Target) Else AI_METHOD=1 EndIf EntityPickMode Plane,2 EndIf EndIf If KeyHit(205)=True Then AI_METHOD=AI_METHOD+1 If KeyHit(203)=True Then AI_METHOD=AI_METHOD-1 If AI_METHOD<1 Then AI_METHOD=1 If AI_METHOD>2 Then AI_METHOD=2 If C\Destination<>0 Select AI_METHOD Case 1 If EntityDistance(C\Destination,C\Entity)>2 PointEntity C\Entity,C\Destination RotateEntity C\Entity,0,EntityYaw(C\Entity),0 MoveEntity C\Entity,0,0,.2 Else RotateEntity C\Entity,0,EntityYaw(C\Entity),0 C\Destination=0 EndIf Case 2 If EntityDistance(C\Destination,C\Entity)>2 If C\CurrentNode<1 Then C\CurrentNode=1 If C\CurrentNode<=99 If EntityDistance(C\Entity,C\Node[C\CurrentNode])<1 C\CurrentNode=C\CurrentNode+1 If C\CurrentNode>C\CurrentNodesNeeded+1 Then C\CurrentNode=C\CurrentNodesNeeded+1 Else PointEntity C\Entity,C\Node[C\CurrentNode] TurnEntity C\Entity,0,DeltaYaw#(C\Entity,C\Node[C\CurrentNode]),0 MoveEntity C\Entity,0,0,.2 EndIf EndIf Else RotateEntity C\Entity,0,EntityYaw(C\Entity),0 C\Destination=0 EndIf End Select EndIf UpdateWorld RenderWorld Color 0,0,0 CameraProject Camera,EntityX(C\Entity),EntityY(C\Entity),EntityZ(C\Entity) Text ProjectedX(),ProjectedY(),"Player" Text 0,0,"USING METHOD:"+AI_METHOD+" Nodes:"+C\CurrentNode+"/"+(C\CurrentNodesNeeded+1) For Nodes=1 To C\CurrentNodesNeeded If nodes>=C\CurrentNode-1 ShowEntity C\Node[nodes] CameraProject Camera,EntityX(C\Node[nodes]),EntityY(C\Node[nodes]),EntityZ(C\Node[nodes]) Local X1#=ProjectedX() : Local Y1#=ProjectedY() CameraProject Camera,EntityX(C\Node[nodes+1]),EntityY(C\Node[nodes+1]),EntityZ(C\Node[nodes+1]) Local X2#=ProjectedX() : Local Y2#=ProjectedY() Line X1#,Y1#,X2#,Y2# Else HideEntity C\Node[nodes] EndIf Next Flip 0 Wend End Function NodesNeeded(obs,dest) Local NodeUsed=2,NodePick EntityPickMode Plane,0 PositionEntity C\Node[NodeUsed],PickedX(),EntityY(C\Entity),PickedZ() MoveEntity C\Node[NodeUsed],PickedNX()*4,0,PickedNZ()*4 Repeat NodePick=LinePick(EntityX(C\Node[NodeUsed]),EntityY(C\Node[NodeUsed]),EntityZ(C\Node[NodeUsed]),EntityX(dest)-EntityX(C\Node[NodeUsed]),EntityY(dest),EntityZ(dest)-EntityZ(C\Node[NodeUsed]),1) If NodePick If NodeUsed+1<100 Local NX#=EntityX(NodePick) Local DX#=EntityX(C\Entity) Local DELX#=(DX#-NX#) Local NZ#=EntityZ(NodePick) Local DZ#=EntityZ(C\Entity) Local DELZ#=(DZ#-NZ#) PositionEntity C\Node[NodeUsed+1],Ceil(EntityX(NodePick)),EntityY(C\Entity),Ceil(EntityZ(NodePick)) MoveEntity C\Node[NodeUsed+1],PickedNX()*4,0,PickedNZ()*4 NodedPick=LinePick(Ceil(EntityX(NodePick)),EntityY(C\Entity),Ceil(EntityZ(NodePick)),Ceil(EntityX(NodePick+1))-Ceil(EntityX(NodePick)),EntityY(C\Entity),Ceil(EntityZ(NodePick+1))-Ceil(EntityZ(NodePick)),1) UpdateNormals C\Node[NodeUsed+1] NodeUsed=NodeUsed+1 EndIf Else EntityPickMode Plane,2 Return NodeUsed EndIf Until NodeUsed>=99 EntityPickMode Plane,2 Return 0 ;Can't resolve it. End Function |