Welcome Guest! To enable all features please try to register or login.
Options
View
Go to last post Go to first unread
VictorTrax  
#1 Posted : Sunday, June 7, 2015 9:38:31 AM(UTC)
VictorTrax

Rank: Administration

Reputation:

Groups: Administrators, Registered
Joined: 5/7/2015(UTC)
Posts: 42

Thanks: 2 times
Was thanked: 5 time(s) in 4 post(s)
In this guide we'll describe your tank's onboard systems and its outside environment, the game map.

The Game Map

Some members of the API involve position and orientation, so let's first consider the game map, the 3-D world where your tank lives. The map is an area of land 1,000 x 1,000 meters. Positions are represented as coordinates X, Y, and Z, where (0, 0, 0) is the origin at the center of the map. Values for X, Y, and Z increase as you go east, up, and north, respectively, so (500, 0, 500) is the northeast (top-right) corner and (-500, 0, -500) is the southwest corner. A Y coordinate of zero represents the lowest possible point in terms of altitude, and a tank will usually be well above zero, especially if it's on a hill. For orientation, we use the term heading, referring to the angle of rotation around the Y axis, in degrees from 0 to <360. North is 0 degrees, east is 90, south is 180, west is 270, etc.

A position in space is represented by a Vector3D, or a Vector if only two dimensions (X, Z) are relevant. A Vector3D has properties for X, Y, and Z, while the Vector type has only X and Y. One thing to note about how the Vector type is used is that, if it's being used to convey a position on the map, its Y property will represent the Z coordinate, e.g., Nav.MoveTo(new Vector(100, 200)) means move to coordinates (X=100, Z=200) -- the surface altitude at that place is not considered.

It should be noted that the various objects found on the map, when detected by the scanner or navigation system, will be represented by instances of ObjectInfo. That type provides a number of properties that describe the object, including the type of object (rock, wall, etc.), its current physical integrity (hit points), distance, and other information. Your AI can inspect those properties to decide how to proceed. We'll discuss more about object detection when we introduce the relevant onboard systems.

Information about the map and terrain is provided by the Map property on your AI class. This information, especially terrain height data, can be used to develop advanced tactics. (Note the terrain information only includes ground/surface data -- it doesn't include objects like rocks or walls, so you need to rely on your scanner for that.)

About Commands

When calling API methods it's important to remember that most command methods are effectively asynchronous -- they issue the command to the tank to perform the action and they return immediately. They don't wait for the action to be completed. All commands that involve mechanical movement, which takes time, are in this respect asynchronous. For example, when you call Nav.MoveTo, the method returns immediately. You can then do other work while the tank is on its way to the destination.

For most systems, if you want to wait for a command to complete, call the Wait method, which blocks (halts code execution in that thread) until that system's current operation is completed. Continuing the MoveTo example, calling Nav.Wait will wait until the destination is reached (or the tank gives up -- see Navigation System below) before proceeding with the next statement in your code. Also, you can abort most commands by calling Stop, and you can wait for the tank to complete the Stop command by calling Wait just as you would for a command like MoveTo.

Also important to note is that commands don't queue, i.e., a subsequent command for a given mechanism overrides any previous command of that type that may not be complete. For example, if you call Nav.MoveTo and then call Nav.Turn before the tank completes the MoveTo, the MoveTo command will be canceled and the tank will start turning.

Onboard Systems

A tank's mechanical parts, like the powertrain and turret, are linked to onboard systems you can control through the API, exposed as properties on your AI class. Keep in mind the below examples are presumed to be inside your AI class.

Navigation System

The tank's powertrain, which drives the tank, is controlled by the navigation system and is accessed by the Nav property. The tank can, of course, drive forward, backward, and turn. You can instruct it to move to a given destination and it will handle turning toward that position and driving there. If it gets bumped it will continue trying to reach that point. However, if it determines no progress is being made toward the destination after a few seconds, eventually it will silently give up and consider the command complete.

The navigation system's forward sensor constantly checks for potential obstacles and reports any it finds to your AI. The tank considers an object to be an obstacle if it determines that it may hit the object before reaching its destination. When this happens, these objects are sent to your OnObstaclesFound callback, so you can decide how to react. Keep in mind your callback may be invoked several times per second, and may repeatedly report the same obstacle, for example, if the tank is still moving toward it.

A common practice is to set a flag or assign the obstacles to a variable in OnObstaclesFound, and let your main thread (the one executing the Run method) deal with the obstacles, e.g., by destroying them or maneuvering around them. Note that your tank can only automatically detect obstacles in its path when moving forward -- not when turning in place or moving backward. Also, even when moving forward it's still possible for your tank to hit something before it can be detected as an obstacle, such as when another tank abruptly crosses in front of it or when your tank suddenly turns downward as it drives over the crest of a hill.
Code:

Nav.MoveTo(new Vector(100, 200)); // Move to (100, 200)
Nav.Move(-20, DriveDirection.Backward); // Drive backward to a point 20 meters behind the tank
Nav.TurnTo(45); // Rotate to a heading of 45 degrees
Nav.Turn(90); // Rotate clockwise 90 degrees
Nav.Turn(-45); // Rotate counterclockwise 45 degrees
Vector3D pos = Nav.Position; // Get the tank's current position
float heading = Nav.Heading; // Get the tank's current heading

Weapon System

The weapon system governs movement of the turret and barrel and coordinates firing, and is accessed by the Weapon property. The turret can rotate 360 degrees, and the barrel can move up and down within defined angular limits. For the turret, we use the term bearing to mean the turret's angle of rotation relative to the tank, so a bearing of 0 means the turret is aligned with the tank's forward direction, regardless of the tank's heading. For the barrel, the term pitch refers to how high the barrel is aiming relative to the tank, specifically, the barrel's angle of rotation around the turret's positive X axis. A pitch of zero is straight ahead (aligned with the tank), a negative pitch is downward, and a positive pitch is upward. For example, a 10 degree pitch means the barrel is aiming slightly upward.

The weapon fires an energy shell that travels in a straight line and explodes on impact with any object. After firing, your tank generates and starts charging a new shell. The time that takes is provided by the Weapon.Attributes.FireRate attribute, two seconds for example.

The amount of damage a shell causes when it hits a tank is the same no matter where it hits the tank. Also, there is no provision for "ignoring" shells of your other tanks -- friendly fire will damage your tank just as it would the enemy's. (You could develop clever AI to avoid firing when you might hit an ally tank, but that's beyond our scope here.)

In your AI you can directly control the weapon's bearing and pitch to aim at targets and fire at them, or you can command the weapon system to automatically track a target and fire when aimed. In either case, the tank rotates the turret in whichever direction is more efficient to reach a target bearing. While moving the turret and barrel, as with the navigation system, if the tank determines no progress is being made after a few seconds, eventually it will silently give up and consider the command complete.

With automatic tracking, the tank tries to keep the weapon aimed at a point on the target's surface, regardless of how your tank or the target moves. To do this, the weapon system repeatedly uses its sensor to update the position at which to aim, at a frequency determined by the system's tracking rate (Weapon.Attributes.TrackRate), twice per second for example. Hence, it may not be fast enough to keep accurate aim on a fast-moving target, and it may fire and miss. Finally, tracking is lost when the target is no longer detected, because it was destroyed, there is a line-of-sight obstruction, etc., or because it gets out of range. The weapon system's sensor range is the same as the scanner's (Scanner.Attributes.Range).
Code:

Weapon.TurnTo(0, 0); // Align turret with tank
Weapon.TurnTo(90, 10); // Aim to the right of the tank and slightly upward
Weapon.TurnTo(180, 10); // Aim behind the tank
Weapon.Track(target); // Automatically track an object and fire whenever aimed
ObjectInfo target = Weapon.TrackTarget; // Get the object currently being tracked

Scanner

The tank's scanner, accessed by the Scanner property, detects surrounding objects and sends updates of what it sees to your OnScanCompleted callback, where you can inspect the results and take appropriate action. It can detect objects up to a maximum distance (Scanner.Attributes.Range), and only objects in the line of sight -- it cannot see through dense objects, over hills, etc. How long a scan takes is determined by the scanner's scan rate (Scanner.Attributes.Rate), once every second for example, so your callback will be invoked approximately that often.

The scanner is enabled by default, but it can be turned off (rare).
Code:

Scanner.Wait(); // Wait for the next scan to complete

... Do something after the scan ...

Scanner.Stop(); // Disable the scanner

Communications

Your tank's communication system, accessed by the Comms property, includes a transceiver that allows it to send and receive messages. A message sent by your tank can be received by all your tanks (including itself), but not by enemy tanks. Incoming messages are passed to your OnCommsReceived callback, where you can inspect the message and take appropriate action.

The actual message is up to you. It can be a CommsMessage if all you want to send is basic information (current position, etc.), or it can be any concrete class derived from that class, so long as it is serializable by the .NET BinaryFormatter (System.Runtime.Serialization.Formatters.Binary.BinaryFormatter). An exception will occur if serialization fails. Also, a tank can only send one message at a time and no more often than about once per second. Calling Send when it's still busy sending a previous message will just fail to send the new message and return false to indicate that.

Obviously, comms are only useful if you have two or more tanks. They could be running the same AI class, though. That is, you could have two tanks on the battlefield sharing the same AI, sending and receiving comms to coordinate their activity, just as you could have multiple AI types communicating.

The communication system is turned on by default, but can be turned off by calling Stop (rare).
Code:

/// <summary>
/// Comms message that includes a target object.
/// </summary>
[Serializable]
public class TargetCommsMessage : CommsMessage
{
	readonly ObjectInfo _target;
	/// <summary>
	/// Target object.
	/// </summary>
	public ObjectInfo Target { get { return _target; } }

	/// <summary>
	/// Creates a new instance.
	/// </summary>
	/// <param name="sender">sender</param>
	/// <param name="target">target object</param>
	public TargetCommsMessage(TankAIBase sender, ObjectInfo target)
		: base(sender)
	{
		_target = target;
	}
}

...

// Send our enemy target to allies (assume we set  'target' earlier)
Comms.Send(new TargetCommsMessage(this, target));

Wrap-Up

To summarize, your tank operates in a 3-D world and has onboard systems you can utilize to control the tank's behavior. It can be aware of its surroundings and react to them, and it can communicate and coordinate with allies.

If you haven't already, look over the code for the sample tanks, included in the NuGet package along with the API library, for examples showing some of the above in practice.

Edited by user Wednesday, August 26, 2015 3:46:55 PM(UTC)  | Reason: Not specified

MesutEfendi  
#2 Posted : Monday, August 17, 2015 11:35:09 PM(UTC)
MesutEfendi

Rank: Newbie

Reputation:

Groups: Registered
Joined: 7/26/2015(UTC)
Posts: 3

Thanks: 2 times
What information can the scanner provide to the tank? Just a list of obstacles and tanks? How would one learn about the terrain around the tank etc?
VictorTrax  
#3 Posted : Tuesday, August 18, 2015 5:52:34 AM(UTC)
VictorTrax

Rank: Administration

Reputation:

Groups: Administrators, Registered
Joined: 5/7/2015(UTC)
Posts: 42

Thanks: 2 times
Was thanked: 5 time(s) in 4 post(s)
The scanner provides a list of objects that are in range and not obstructed from view by terrain or other objects. The scanner doesn't provide direct information about terrain itself, though. However, a tank can determine the slope of the terrain under it by looking at Nav.Pitch and Nav.Roll, so you know if you're headed uphill or downhill or leaning sideways left or right.
thanks 2 users thanked VictorTrax for this useful post.
MesutEfendi on 8/18/2015(UTC), jyu78749 on 1/18/2016(UTC)
MesutEfendi  
#4 Posted : Tuesday, August 18, 2015 9:27:13 AM(UTC)
MesutEfendi

Rank: Newbie

Reputation:

Groups: Registered
Joined: 7/26/2015(UTC)
Posts: 3

Thanks: 2 times
I hate to be a bother all day here, but I would very much like to implement tactics like hulldown, for which the tank needs to have an idea of the surrounding terrain, and that between it and the enemy. Perhaps a two dimensional matrix of short ints, signalling the height of evenly spaced points within the scanner's range, could be returned to the tank?
VictorTrax  
#5 Posted : Tuesday, August 18, 2015 10:18:26 AM(UTC)
VictorTrax

Rank: Administration

Reputation:

Groups: Administrators, Registered
Joined: 5/7/2015(UTC)
Posts: 42

Thanks: 2 times
Was thanked: 5 time(s) in 4 post(s)
That seems reasonable. A way to express the surrounding terrain is something that's been considered for a while now. A first step was adding Nav.Pitch and Nav.Roll. Hopefully we can implement something more soon.

Edited by user Tuesday, August 18, 2015 10:24:47 AM(UTC)  | Reason: Not specified

thanks 1 user thanked VictorTrax for this useful post.
MesutEfendi on 8/18/2015(UTC)
Cactusthorn  
#6 Posted : Thursday, August 20, 2015 6:58:56 AM(UTC)
Cactusthorn

Rank: Member

Reputation:

Groups: Registered
Joined: 8/10/2015(UTC)
Posts: 11

Was thanked: 1 time(s) in 1 post(s)
Hi,
I have for the last week or so, been collecting height data by running my tanks all over the place for many (and i mean A LOT) hours. Here is gray-scale output from all the data i have generated by know (dark is low, light is high):

Heigh map from collected data.

Even though you can't collect the data for every point on the map, i have developed a quite simple algorithm to fix the "holes". Here is the result after running the algorithm:

Heigh map after "hole fixing" algorithm.

In a pretty close future I hope to be able to implement ray-tracing into my code so my tanks will be able to do such things as staying out of view of enemy tanks simply by knowing were they are (with their position passed by a friendly radio call for instance), move to the ideal spot to the engage the enemy or implement tactics such a "hull down".

Perhaps once my "MAP Class", as i have called it, is polished enough i will make it public for you guys to use and improve. For the time being, i can pass you guys the "raw" data (from wich the upper image was generated) if you want me to.

Edit 1: I also plan on calculating a gradient map from this data, so my tanks will able to anticipate slopes and chose the fastest way up a hill. (As you have certainly found out by your self's, tanks can literally take minutes to get up a hill if they try to go straight up.)

Edit 2: I have also collected data on the obstacles whereabouts (gray: destructible, white indestructible):

Obstacle whereabouts, collected from scanner.

Edited by user Thursday, August 20, 2015 9:39:57 AM(UTC)  | Reason: Not specified

VictorTrax  
#7 Posted : Thursday, August 20, 2015 9:32:48 AM(UTC)
VictorTrax

Rank: Administration

Reputation:

Groups: Administrators, Registered
Joined: 5/7/2015(UTC)
Posts: 42

Thanks: 2 times
Was thanked: 5 time(s) in 4 post(s)
Nice!

For the API, the tentative plan is for the scan result to include a point or height map of visible, surrounding terrain, along with the object list that is being provided now. It sounds like you will already have this data, more or less, for the existing map. That's pretty impressive.
VictorTrax  
#8 Posted : Wednesday, August 26, 2015 10:53:48 AM(UTC)
VictorTrax

Rank: Administration

Reputation:

Groups: Administrators, Registered
Joined: 5/7/2015(UTC)
Posts: 42

Thanks: 2 times
Was thanked: 5 time(s) in 4 post(s)
You guys may already know by now, but in update 0.5.1 we added a new feature to the API so you have access to the terrain height of the entire map, exposed by the new Map property on TankAIBase. This was added in lieu of changing the scanner to return terrain data.

Edited by user Wednesday, August 26, 2015 3:24:53 PM(UTC)  | Reason: Not specified

Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You can vote in polls in this forum.

Notification

Icon
Error