Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
1.0.0:pathfinding [2023/03/21 15:30] – [Click to Start Pathfinding] admin | 1.0.0:pathfinding [2023/03/21 15:34] (current) – [Click to Start Pathfinding] admin | ||
---|---|---|---|
Line 155: | Line 155: | ||
Image1.Bitmap.Assign(FVerifyBmp); | Image1.Bitmap.Assign(FVerifyBmp); | ||
</ | </ | ||
+ | |||
+ | |||
+ | ===== Click to Start Pathfinding | ||
+ | |||
+ | Many developers may struggle with the question how to combine the setup above with user interaction. | ||
+ | |||
+ | Speaking for a classic Point & Click Adventure, a recommend way is to add a simple plane (TPlane, TGorillaPlane) for click detection. | ||
+ | |||
+ | All other 3D elements should be set to HitTest = false, to not disturb mouse interaction with the helper plane. | ||
+ | |||
+ | We then register a MouseUp event on the viewport, where we put all of our mouse handling. | ||
+ | |||
+ | <file pascal> | ||
+ | var | ||
+ | FDestPoint : TPoint3D; | ||
+ | | ||
+ | procedure TForm1.GorillaViewport1MouseUp(Sender: | ||
+ | Shift: TShiftState; | ||
+ | var LRayPos, | ||
+ | LRayDir : TPoint3D; | ||
+ | LHitPos, | ||
+ | LNormal, | ||
+ | LScreenPos : TPoint3D; | ||
+ | begin | ||
+ | // 1) Get 3D position of click, by converting screen coordinates into 3D coordinates | ||
+ | LScreenPos := GorillaViewport1.ScreenToWorld(PointF(X, | ||
+ | |||
+ | // 2) Cast a ray from camera to the clicking position, to retrieve the real | ||
+ | // 3D destination coordinate | ||
+ | LRayPos := GorillaCamera1.AbsolutePosition; | ||
+ | LRayDir := (LScreenPos - LRayPos).Normalize(); | ||
+ | if GorillaPlane1.RayCastIntersect(LRayPos, | ||
+ | begin | ||
+ | // If raycasting was successfully - we can start store the point hit by the ray | ||
+ | FDestPoint := LHitPos; | ||
+ | FDestPoint.Y := 0; | ||
+ | | ||
+ | // Aftwards we start pathfinding | ||
+ | UpdatePathfinding(); | ||
+ | end; | ||
+ | end; | ||
+ | |||
+ | procedure TForm1.UpdatePathfinding(); | ||
+ | var LAgentPos : TPoint3D; | ||
+ | begin | ||
+ | // Get the agent position (pathfinding moving object) | ||
+ | LAgentPos := GorillaModel1.AbsolutePosition; | ||
+ | | ||
+ | // Compute the path from 3D position - this will generate our new walking path | ||
+ | FPathFinder.FindPath(LAgentPos, | ||
+ | |||
+ | // Stop the current animation | ||
+ | FPathAnim.Stop(); | ||
+ | FPathAnim.Enabled := false; | ||
+ | |||
+ | // Apply computed path data to our existing TGorillaPath3D instance, instead for recreating each time | ||
+ | FPathFinder.ApplyToPath3D(FPath); | ||
+ | |||
+ | // Reset the used path data in our path animation | ||
+ | FPathAnim.Duration := FPath.Path.GetLength; | ||
+ | FPathAnim.Path := FPath.Path; | ||
+ | |||
+ | // For correct rotation of our character, we need the polygon to detect the | ||
+ | // next node to adjust to - | ||
+ | // NOTICE: READ THE SECTION BELOW | ||
+ | FPath.Path.FlattenToPolygon(FPolygon); | ||
+ | |||
+ | // Restart movement on path | ||
+ | FPathAnim.Enabled := true; | ||
+ | FPathAnim.Start(); | ||
+ | end; | ||
+ | </ | ||
+ | |||
===== Auto-Rotate an animated character ===== | ===== Auto-Rotate an animated character ===== | ||
Line 228: | Line 301: | ||
</ | </ | ||
- | ===== Click to Start Pathfinding | ||
- | |||
- | Many developers may struggle with the question how to combine the setup above with user interaction. | ||
- | |||
- | Speaking for a classic Point & Click Adventure, a recommend way is to add a simple plane (TPlane, TGorillaPlane) for click detection. | ||
- | |||
- | All other 3D elements should be set to HitTest = false, to not disturb mouse interaction with the helper plane. | ||
- | |||
- | We then register a MouseUp event on the viewport, where we put all of our mouse handling. | ||
- | |||
- | <file pascal> | ||
- | var | ||
- | FDestPoint : TPoint3D; | ||
- | | ||
- | procedure TForm1.GorillaViewport1MouseUp(Sender: | ||
- | Shift: TShiftState; | ||
- | var LRayPos, | ||
- | LRayDir : TPoint3D; | ||
- | LHitPos, | ||
- | LNormal, | ||
- | LScreenPos : TPoint3D; | ||
- | begin | ||
- | // 1) Get 3D position of click, by converting screen coordinates into 3D coordinates | ||
- | LScreenPos := GorillaViewport1.ScreenToWorld(PointF(X, | ||
- | |||
- | // 2) Cast a ray from camera to the clicking position, to retrieve the real | ||
- | // 3D destination coordinate | ||
- | LRayPos := GorillaCamera1.AbsolutePosition; | ||
- | LRayDir := (LScreenPos - LRayPos).Normalize(); | ||
- | if GorillaPlane1.RayCastIntersect(LRayPos, | ||
- | begin | ||
- | // If raycasting was successfully - we can start updating the path | ||
- | FDestPoint := LHitPos; | ||
- | FDestPoint.Y := 0; | ||
- | | ||
- | // Start pathfinding | ||
- | UpdatePathfinding(); | ||
- | end; | ||
- | end; | ||
- | |||
- | procedure TForm1.UpdatePathfinding(); | ||
- | var LAgentPos : TPoint3D; | ||
- | begin | ||
- | // New computation of path | ||
- | LAgentPos := GorillaModel1.AbsolutePosition; | ||
- | FPathFinder.FindPath(LAgentPos, | ||
- | |||
- | // Stop the current animation | ||
- | FPathAnim.Stop(); | ||
- | FPathAnim.Enabled := false; | ||
- | |||
- | // Apply computed path data to our existing TGorillaPath3D instance, instead for recreating each time | ||
- | FPathFinder.ApplyToPath3D(FPath); | ||
- | |||
- | // Reset the used path data in our path animation | ||
- | FPathAnim.Duration := FPath.Path.GetLength; | ||
- | FPathAnim.Path := FPath.Path; | ||
- | |||
- | // For correct rotation of our character, we need the polygon to detect the | ||
- | // next node to adjust to | ||
- | FPath.Path.FlattenToPolygon(FPolygon); | ||
- | |||
- | // Restart movement on path | ||
- | FPathAnim.Enabled := true; | ||
- | FPathAnim.Start(); | ||
- | end; | ||
- | </ | ||
Next: [[renderpass|Render Pass]] | Next: [[renderpass|Render Pass]] |