View Javadoc

1   /*
2    * Copyright (C) 2013 AMIS research group, Faculty of Mathematics and Physics, Charles University in Prague, Czech Republic
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  package cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.formation;
18  
19  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
20  import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
21  import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
22  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.NavMesh;
23  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.NavMeshConstants;
24  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
25  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotModuleController;
26  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
27  import cz.cuni.amis.utils.exception.PogamutException;
28  import javax.vecmath.Vector2d;
29  
30  /**
31   * A class able to make agents hold formations
32   * @author Jakub
33   */
34  public class Formation {
35      
36      
37      UT2004BotModuleController bot;
38      
39      Player leader;
40      Location leaderLastSeenLocation;
41      double leaderLastSeenRotation = 0;
42      long leaderLastTimeSeen = 0;
43      
44      Vector2d direction;
45      double distance;
46      
47      NavMesh navmesh;
48      
49      // direction is relative to leader's direction
50      boolean relativeRotation = true;
51      // bot turns to leader when he reaches the desired spot
52      boolean turnToLeaderAtDestination = true;
53      // should i see leader all the time?
54      boolean watchLeader = true;
55      // bot will not care about the navmesh
56      boolean suicideMode = false;
57  
58      
59      public Formation(UT2004BotModuleController bot) throws Exception {
60          this.bot = bot;
61          navmesh = bot.getNavMeshModule().getNavMesh();
62          if(navmesh==null) throw new Exception("Formation cannot be instatiated because there is no navmesh.");
63      }
64      
65      
66      
67      
68      /**
69       * Makes the bot move to the proper place
70       */
71      public void holdFormation() {
72          
73          if(leader == null) {
74              System.out.println("No leader - no formation");
75              return;
76          }
77          
78          // update leader's location
79          updateLeaderInfo();
80          
81          // what if i don't see leader?
82          if(null == bot.getPlayers().getVisiblePlayer(leader.getId())) {
83              if(watchLeader) {
84                  System.out.println("I lost the leader from sight. I look where i last saw him."); 
85                  bot.getMove().turnTo(leaderLastSeenLocation);
86                  return;
87              }
88          }
89          
90          if(leaderLastSeenLocation == null) {
91              System.out.println("I dont know where my leader is..."); 
92              return;
93          }
94          
95          // get the point where we want to be
96          double yaw = NavMeshConstants.transform2DVectorToRotation(direction);
97          if(this.relativeRotation) yaw += leaderLastSeenRotation;
98          Vector2d actualDirection = NavMeshConstants.transformRotationTo2DVector(yaw);
99          // stretch the vector to proper length
100         actualDirection.normalize();
101         actualDirection.x *= distance;
102         actualDirection.y *= distance;
103         // add vector to leaders location
104         double x = leaderLastSeenLocation.x + actualDirection.x;
105         double y = leaderLastSeenLocation.y + actualDirection.y;
106         double z = leaderLastSeenLocation.z;
107         
108         Location targetLocaton = new  Location(x,y,z);
109  
110         if(bot.getInfo().atLocation(targetLocaton, NavMeshConstants.StepSize/2)) {
111             System.out.println("I am at the right spot.");
112             if(this.turnToLeaderAtDestination) bot.getMove().turnTo(this.leaderLastSeenLocation);
113             return;
114         }
115         
116         Location currenLocation = bot.getInfo().getLocation();
117         
118         
119         Vector2d mainForce = new Vector2d(targetLocaton.x-currenLocation.x, targetLocaton.y-currenLocation.y);
120         mainForce.normalize();
121         mainForce.x *= NavMeshConstants.ForceToTarget; 
122         mainForce.y *= NavMeshConstants.ForceToTarget;
123          
124         
125         // add ray forces
126         yaw = bot.getInfo().getRotation().getYaw();
127         double distance;
128         double force;
129         // 1. front ray
130         Vector2d frontDirection = NavMeshConstants.transformRotationTo2DVector(yaw);
131         distance = navmesh.getDistanceFromEdge(currenLocation, frontDirection, NavMeshConstants.obstacleMaxDistance);
132         if(0 < distance && distance < NavMeshConstants.obstacleMaxDistance) {
133             force = (distance / NavMeshConstants.obstacleMaxDistance) * NavMeshConstants.obstacleMaxForce;
134             Vector2d frontForce = (Vector2d) frontDirection.clone();
135             frontForce.negate();
136             frontForce.normalize();
137             frontForce.x *= force;
138             frontForce.y *= force;
139             mainForce.add(frontForce);
140         }
141         
142         // 2. left front ray
143         Vector2d leftFrontDirection = NavMeshConstants.transformRotationTo2DVector(yaw-NavMeshConstants.UTQuarterAngle/2);
144         distance = navmesh.getDistanceFromEdge(currenLocation, leftFrontDirection, NavMeshConstants.obstacleMaxDistance);
145         if(0 < distance && distance < NavMeshConstants.obstacleMaxDistance) {
146             force = (distance / NavMeshConstants.obstacleMaxDistance) * NavMeshConstants.obstacleMaxForce;
147             Vector2d leftFrontForce = (Vector2d) leftFrontDirection.clone();
148             leftFrontForce.negate();
149             leftFrontForce.normalize();
150             leftFrontForce.x *= force;
151             leftFrontForce.y *= force;
152             mainForce.add(leftFrontForce);
153         }
154 
155         // 3. right front ray
156         Vector2d rightFrontDirection = NavMeshConstants.transformRotationTo2DVector(yaw+NavMeshConstants.UTQuarterAngle/2);
157         distance = navmesh.getDistanceFromEdge(currenLocation, rightFrontDirection, NavMeshConstants.obstacleMaxDistance);
158         if(0 < distance && distance < NavMeshConstants.obstacleMaxDistance) {
159             force = (distance / NavMeshConstants.obstacleMaxDistance) * NavMeshConstants.obstacleMaxForce;
160             Vector2d rightFrontForce = (Vector2d) rightFrontDirection.clone();
161             rightFrontForce.negate();
162             rightFrontForce.normalize();
163             rightFrontForce.x *= force;
164             rightFrontForce.y *= force;
165             mainForce.add(rightFrontForce);
166         }   
167         
168         
169         
170         
171         // end of adding ray forces
172         
173         // main force now tells which direction to go. Go there by step size
174         mainForce.normalize();
175         mainForce.x *= NavMeshConstants.StepSize; 
176         mainForce.y *= NavMeshConstants.StepSize;
177         x = currenLocation.x + mainForce.x;
178         y = currenLocation.y + mainForce.y;
179         z = currenLocation.z;
180         Location resultLocation = new Location(x,y,z);
181         
182         
183         System.out.println("Moving to resultLocation " + resultLocation);
184         bot.getMove().moveTo(resultLocation);
185     }
186     
187     public void updateLeaderInfo() {
188         if(bot.getPlayers().getVisiblePlayer(leader.getId())!=null) {
189             System.out.println("Updating leader's location...");
190             leaderLastSeenLocation = leader.getLocation();
191             leaderLastSeenRotation = leader.getRotation().getYaw();
192             leaderLastTimeSeen = System.nanoTime();
193         } else {
194             System.out.println("I cannot see the leader.");
195         }
196     }
197     
198     /**
199      * How many seconds did the bot not seen his leader?
200      * @return 
201      */
202     public int howLongLeaderNotSeen() {
203         double nano = (System.nanoTime() - this.leaderLastTimeSeen);
204         return (int)(nano / 1000000000);
205     }
206     
207     /**
208      * Setters 
209      */
210     public void setLeader(Player leader) {
211         this.leader = leader;
212         updateLeaderInfo();
213     } 
214     public void setDirection(Vector2d direction) {
215         this.direction = direction;
216     }     
217     public void setDistance(double distance) {
218         this.distance = distance;
219     }
220     
221     /**
222      * Getters
223      */
224     public Player getLeader() {
225         return leader;
226     } 
227     public Vector2d getDirection() {
228         return direction;
229     }     
230     public double getDistance() {
231         return distance;
232     } 
233     public Location getLeaderLastSeenLocation() {
234         return leaderLastSeenLocation;
235     }
236     public long getLeaderLastTimeSeen() {
237         return leaderLastTimeSeen;
238     }    
239    
240 }