Moving your Iam

From AI Wiki

Jump to: navigation, search

Contents

Moving your Iam

If you've gotten this far you most likely succeeded in getting your first Iam to do something. You know now how to make your Iam say something and how to perform a certain action. One of the most important actions however, moving, hasn't been shown yet. If you look at the functions available to your behavior you'll see there's a walk(Location location) function. Location is nothing more than a simple object containing an X, Y and Z coordinate, and is located in the com.avatar_reality.blue_mars.map package. If you call this function, your Iam will walk to the location specified. The function run() will do the same, except that the Iam will be running and get there faster. Sounds easy enough, no? Did we really need to allocate a whole section to this? Unfortunately, yes.

If you've paid attention to the MyIam.xml file in the IamTemplate project, you'll notice that it starts by specifying a 'spawn-location'. That is the location where your Iam will appear when it logs in. How did we get that coordinate? We got that by opening the city Cry-file in the City-Editor available to city-developers, where we can display the coordinates of different places. And then we chose a location that suited our needs. But what if you're an Iam-developer but not a city-developer? For whatever reason, you may not have access to the original city-file. This may be the hardest thing to get used to when developing an Iam for Blue Mars, and that is that the Iams have no intrinsic knowledge about the world they reside in. Nor are there any commands available to query about the world and its objects. Your Iam is basically blind and numb. The technical reason why this is, is that relaying world information to each avatar would be too costly and clog the network. That doesn't make us Iam developers any happier of course. But it is what it is and lets get to it to see how we can make our Iams know where they are and where they're going.

First, let's give a small demonstration. Start your Iam, or the template one or any other you have available, but add the following argument: -gui. So in the command-line it would become java -jar IamFramework.jar -gui. In Eclipse you can achieve the same by selecting Run -> Run Configurations. In the dialog that opens, select TestMyIam under the Java Applications section (or right-click on the Java Applications section and select New), click the Arguments tab and type -gui in the Program Arguments box. Then click Run. Your Iam will start as before, but there will also be a small control-window that pops up. If you log into Blue Mars to watch your Iam and you click on any of the arrows, you'll see your Iam move. It may not move in the direction you expect, as that actually depends on the angle from which you look at your Iam. The top and bottom buttons will rotate it. So you have some sort of remote-control of your Iam. Click some more to see your Iam move in different directions. Now, move your Iam towards the building in front of it. Keep clicking. You'll see that the Iam hesitates and briefly stops when it reaches the wall. But if you keep clicking, all of a sudden it will end up right inside the (solid) wall. That is because your Iam doesn't know there's a wall. It has no way of knowing without external help. It also shows Iams can do something player avatars can't, they can go any place. Although that may have its uses on occasion, generally we'd prefer Iams to behave just like players do and respect the existence of object and buildings. So how do we do that?

Maps

If our Iams can't see nor feel, in order to navigate a world we need to give our Iams a map. In the interface of a behavior you'll see that there's a getMap() function. Unfortunately it returns null when called. That's because we didn't put anything in there yet. Now open MyIam.xml (if you didn't name it differently in the meantime) and add make the following change:

<bean id="IamTownMap" class="com.avatar_reality.blue_mars.iam.map.SparseMap">
	<constructor-arg index="0" value="maps/IamTown/map.txt"/>
        <constructor-arg index="1" value="maps/IamTown/objectlist.xml"/>
</bean>

<bean id="testIam" class="com.avatar_reality.blue_mars.iam.framework.IamBot">
	<property name="spawnLocation">
		<ref bean="SpawnLocation"/>
	</property>
        <property name="loginName" value="blue_mars_test@yahoo.com"/>
	<property name="password" value="bot123"/>
	<property name="cityName" value="AR_IamTown"/>
	<property name="genderString" value="Female"/>
	<property name="name" value="Alexis"/>
 	<property name="map">
		<ref bean="IamTownMap"/>
	</property>
	<property name="isMonitored" value="true"/>
	<property name="behaviorList">
           <list>
			<ref bean="MyIamBehavior"/>
           </list>
	</property>
</bean>


Note the additions related to maps. Now run the Iam again (with the -gui option). Now all of a sudden you get another window. Welcome to the Matrix. What you see now is a map of IamTown. If you use the scroll-bars to go down a bit you'll see a turquoise dot. That is your Iam. You may see some red dots as well. If you logged into Blue Mars with your client to look at your Iam you should see at least one nearby. If you move your avatar, you'll see the red dot move. If you use the controls to move your Iam, you'll see the turquoise dot move. If you click with your mouse on the map, it will display the coordinate of where you clicked in the console.

If you look at the XML above you'll see that the map is specified as maps/IamTown/map.txt. This is a sub-directory of the template project. So it has been pre-generated and has been supplied to you. There's a lot more to maps than this, but that is subject of a later section. Let's first see what you can do with a map. If you look at the getMap() function of your behavior you'll see it returns a com.avatar_reality.blue_mars.map.Map object. You can lookup the interface of this in the Javadocs to see what you can do with it. For now let's focus on the isAccessible() function. This function tells you if a certain location is accessible. That information can be used to navigate your Iam around buildings and obstacles. Experienced game programmers may know all about path-searching, A-star algorithms and more. Fact is however that navigation is such a fundamental activity of any Iam that we have created a NavigatingBehavior ready for you to be used out of the box. For this you need to make a few small changes. Instead of sub-classing BehaviorAdapter for your Iam's behavior, you need to sub-class this NavigatingBehavior. Now you can call the function navigate() instead of walk() and your Iam will start walking towards the desired location. If there are any buildings or obstacles in the way, it will navigate around them. In fact, if there are other avatars in the way it will even try to avoid colliding with them. (It may not always successfully avoid collision, especially when there are many moving avatars around, but it will try.) The only caveat is that when using the NavigatingBehavior class, it's required to call super.update() in your behavior's update() function. Otherwise it will not navigate very far.

Charting your own maps

(Update: although the section below is still valid, new tools have made it a lot easier to automatically generate maps. see the section "Create a city map" for details on this.)

OK, you may say, that NavigatingBehavior is all handy-dandy but what if I want to navigate around 'my' city instead of IamTown? You didn't include a map for all the cities available. So where do I get it? That's also subject for another section. Let's first see what you can do in case you had no map and no way to get one. In that case you could build your own. Instead of getting into the nitty-gritty details of map-files, let's look at another possibility. Let's create a new XML file called SurveyorIam.xml that looks like this:

<beans>
	<bean id="classpath" class="com.avatar_reality.blue_mars.iam.ClassPathBean">
		<property name="jarList">
			<list>
				<value>file:MyIam.jar</value>
				<value>file:IamLibrary.jar</value>
			</list>
		</property>
	</bean>

	<bean id="SpawnLocation" class="com.avatar_reality.blue_mars.iam.map.Location"> 
		<constructor-arg index="0" value="3458"/>
		<constructor-arg index="1" value="1918"/>
		<constructor-arg index="2" value="31"/>
	</bean>
	
	<bean id="IamTownMap" class="com.avatar_reality.blue_mars.iam.map.SparseMap">
		<constructor-arg index="0" value="maps/IamTown/mymap.txt"/>
                <constructor-arg index="1" value="maps/IamTown/objectlist.xml"/>
 	</bean>

	<bean id="SurveyingBehavior" class="com.avatar_reality.blue_mars.iam.behavior.implementations.SurveyingBehavior" scope="prototype">
		<property name="mapFileName" value="maps/IamTown/mymap.txt"/>
	</bean>
 	
	<bean id="miam" class="com.avatar_reality.blue_mars.iam.framework.IamBot">
		<property name="spawnLocation">
			<ref bean="SpawnLocation"/>
		</property>
 		<property name="loginName" value="blue_mars_test@yahoo.com"/>
		<property name="password" value="bot123"/>
		<property name="cityName" value="AR_IamTown"/>
		<property name="map">
			<ref bean="IamTownMap"/>
		</property>
 		<property name="genderString" value="Male"/>
		<property name="name" value="Mr. Inspector"/>
		<property name="isMonitored" value="true"/>
		<property name="behaviorList">
                    <list>
				<ref bean="SurveyingBehavior"/>
                    </list>
		</property>
	</bean>
</beans>

Warning: If you haven't done so already, before you continue make sure you download the [IamLibrary.jar] and place it next to the IamFramework.jar in your project.

Try to run this Iam by adding the -config=SurveyorIam.xml argument when you run the TestMyIam application. This shows another feature of the framework. If you hadn't added the -config argument, the framework would have tried to create an Iam both from the MyIam.xml file and from the SurveyorIam.xml. That is a very handy feature in case you want to run more than one Iam at once. In this case you'd most likely get an error that your Iam is already logged in when trying to start the second Iam, since they use the same user-name and password.

What you see now is that the map window remains blank. This is due to the fact that we changed "map.txt" into "mymap.txt", a file that doesn't exist. If you log into Blue Mars with the regular client however, and you move towards the location where the Iam stands, you'll see a trail appear in the map window. What is happening is that the SurveyingBehavior observes the movement of other avatars and deduces from that information which locations are accessible and which not. The more you move around, the more the area with trails expands. The more other players are present in your Iam's neighborhood, the faster it goes. You'll notice though, that once you get beyond a certain point, it stops adding trails to the map. In fact, the red dot representing your avatar may even disappear from the screen altogether. That's because Iams can only 'see' other avatars within a certain distance. So the area you can show to the Iam is limited this way. It would be much better if the Iam could follow you. OK, let's see how we'd do that. Let's make a few changes to SurveyorIam.xml.

<beans>
	<bean id="classpath" class="com.avatar_reality.blue_mars.iam.ClassPathBean">
		<property name="jarList">
			<list>
				<value>file:MyIam.jar</value>
				<value>file:IamLibrary.jar</value>
			</list>
		</property>
	</bean>

	<bean id="SpawnLocation" class="com.avatar_reality.blue_mars.iam.map.Location"> 
		<constructor-arg index="0" value="3458"/>
		<constructor-arg index="1" value="1918"/>
		<constructor-arg index="2" value="31"/>
	</bean>
	
	<bean id="IamTownMap" class="com.avatar_reality.blue_mars.iam.map.SparseMap">
		<constructor-arg index="0" value="maps/IamTown/mymap.txt"/>
 	</bean>

	<bean id="SurveyingBehavior" class="com.avatar_reality.blue_mars.iam.behavior.implementations.SurveyingBehavior" scope="prototype">
		<property name="mapFileName" value="maps/IamTown/mymap.txt"/>
	</bean>
 	<bean id="FollowingBehavior" class="com.avatar_reality.blue_mars.iam.behavior.implementations.FollowingBehavior" scope="prototype"/>

	<bean id="miam" class="com.avatar_reality.blue_mars.iam.framework.IamBot">
		<property name="spawnLocation">
			<ref bean="SpawnLocation"/>
		</property>
		<property name="loginName" value="blue_mars_test@yahoo.com"/>
		<property name="password" value="bot123"/>
		<property name="cityName" value="AR_IamTown"/>
		<property name="map">
			<ref bean="IamTownMap"/>
		</property>
 		<property name="genderString" value="Male"/>
		<property name="name" value="Mr. Inspector"/>
		<property name="isMonitored" value="true"/>
		<property name="behaviorList">
                    <list>
				<ref bean="SurveyingBehavior"/>
				<ref bean="FollowingBehavior"/>
                    </list>
		</property>
	</bean>
</beans>

This version has just a few lines added to it concerning something called FollowingBehavior. This shows another powerful feature of the Iam-framework. Iams can have multiple behaviors in them. Each behavior receives the same messages directed to the Iam and each can control the Iam's actions. This makes it very easy to reuse often needed behaviors. Often a complex Iam can be built by assembling it from a collection of fairly simple behaviors. But we digress, behaviors will be treated extensively in other sections to come. Let's continue. Use your avatar to walk up to the Iam and say "target me". You may notice that this has the effect of the Iam turning towards you. It may even move a little closer to you, provided it has a path towards you. To get the Iam moving, you first have to move your avatar through the Iam to make sure it can follow you by showing it a trail from its spawn-location to your avatar. Now you can move around as far as you like and the Iam will follow, all the while adding trails to the map.

After creating some trails you'll notice it's actually going to be a lot of work to create a map in the same detail as the pre-generated one we provided for you. Still, there's a real usefulness to this method. First, as we noticed before, you may not have a pre-generated map available for the world that you want to build a Iam for. In that case you always have the option to build one this way. If the world is a popular one, with many players visiting, you could well buid an extensive map with as much details as the pre-generated ones in short order. But you also may simply want to restrict rather more tightly what area your Iam knows and what paths it takes to move around.

Rotating your Iam

Although not exactly moving, obviously the orientation of your Iam is just as important as its location. For a large part this is taken care of for you. Whenever you move your Iam, the Blue Mars client will automatically rotate the avatar to face the direction it's moving. But while standing still, you may want to explicitly set the direction in which your Iam is facing. Technically it's possible to directly set the angle of your Iam with respect to the X,Y and Z axis. You do this by calling the methods setPitch(), setRoll() and setYaw() respectively on the orientation object that you can retrieve through the getOrientation() method. But we have provided a convenience method called face(Location location) which simply rotates your Iam to face in the direction of the given location. One common thing to do is make your Iam face towards another avatar. After all, when talking to someone it's not very polite to look the other way! The following example code will rotate your Iam to face someone who just said something:

public void receiveSayAction(String entityName, String text)
{
    Entity entity = findEntity(entityName);
   face(entity.getLocation());
   ... say something back ...
}

Actually, because it's so common to face another avatar, you can even just call face(entityName). It has the same effect as the code above. But we wanted to show another important method: findEntity(). A lot of the incoming messages pass the entityName as a parameter. With findEntity() you can get the Entity object that has a lot more information about this avatar, like location, orientation, name etc, etc.

Summary

This concludes the introduction to moving around and maps. Unfortunately this was a bit more complicated than what most people probably would have liked. And we haven't even dug into the real details of it yet. A few other useful features passed by briefly in the meantime. This section showed how you can use different XML files to define different Iams and specify which one you want to run. It also introduced how you can combine different behaviors in one Iam to assemble a more complex one. Hopefully you also got more feel of how Spring is used to configure an Iam and how to link up completely separate classes without needing a compiler. And lastly you learned how to rotate your Iam and how to find more information about other avatars.

Personal tools