Aiming at the opponent

Before you can go through this example you need to first setup your environment. You can find out how to do that in our Getting started guide .

In this example you will learn how to make your warrior units aim at the opponent. At the end we will also give you a few extra tips that will improve your warriors aiming mechanics drastically!

This is how our units will be able to aim:


Basic aiming

Code

Below is the code for this example.

⚠️ To keep the example clean we didn’t include the whole code for the bot. In order to use this code you need to paste it to an appropriate location in your bot implementation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Paste this code in update(...) method.

// Iterate through all of your units.
for (int i = 0; i < state.units.length; i++) {
    UnitData unit = state.units[i];

    /// If the unit is a warrior and it sees at least one 
    // opponent then turn towards it and shoot.
    if (unit.type == UnitType.WARRIOR && unit.opponentsInView.length > 0) {

        // Get the first opponent that the unit sees.
        OpponentInView opponent = unit.opponentsInView[0];

        // Calculate the aiming angle between units orientation and the opponent. The closer
        // the angle is to 0 the closer is the unit aiming towards the opponent.
        float aimAngle = MathUtil.angleBetweenUnitAndPoint(unit, opponent.x, opponent.y);

        // Stop the unit.
        api.setSpeed(unit.id, Speed.NONE);

        // Based on the aiming angle turn towards the opponent.
        if (aimAngle < 0) {
            api.setRotation(unit.id, Rotation.RIGHT);
        } else {
            api.setRotation(unit.id, Rotation.LEFT);
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Paste this code in update(...) method.

# Iterate through all of your units.
for unit in state["units"]:

    # If the unit is a warrior and it sees at least one opponent 
    # then turn towards it and shoot.
    if unit["type"] == UnitType.WARRIOR and len(unit["opponentsInView"]) > 0:

        # Get the first opponent that the unit sees.
        opponent = unit["opponentsInView"][0]

        # Calculate the aiming angle between units orientation and the opponent. The closer
        # the angle is to 0 the closer is the unit aiming towards the opponent.
        aim_angle = math_util.angle_between_unit_and_point(unit, opponent["x"], opponent["y"])

        # Stop the unit.
        api.set_speed(unit["id"], Speed.NONE)
        
        # Based on the aiming angle turn towards the opponent.
        if aim_angle < 0:
            api.set_rotation(unit["id"], Rotation.RIGHT)
        else:
            api.set_rotation(unit["id"], Rotation.LEFT)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Paste this code in update(...) method.

// Iterate through all of your units.
for (unit in state.units) {

    // If the unit is a warrior and it sees at least one 
    // opponent then turn towards it and shoot.
    if (unit.type == UnitType.WARRIOR && unit.opponentsInView.isNotEmpty()) {

        // Get the first opponent that the unit sees.
        val opponent = unit.opponentsInView[0]

        // Calculate the aiming angle between units orientation and the opponent. The closer
        // the angle is to 0 the closer is the unit aiming towards the opponent.
        val aimAngle = MathUtil.angleBetweenUnitAndPoint(unit, opponent.x, opponent.y)

        // Stop the unit.
        api.setSpeed(unit.id, Speed.NONE)

        // Based on the aiming angle turn towards the opponent.
        if (aimAngle < 0) {
            api.setRotation(unit.id, Rotation.RIGHT)
        } else {
            api.setRotation(unit.id, Rotation.LEFT)
        }
    }
}

Explanation

In order to aim at the opponent we need to make warrior unit turn towards it. Deciding about where to turn is achieved by calculating the angle between the warrior’s orientation and the opponent as show in the image below. With every GameState you receive orientationAngle for each unit. The aiming angle is the angle from unit’s orientation towards the point. If the aiming angle is 0 the unit is looking directly towards the opponent, if it is positive the unit is looking to the right side of the opponent and if it is negative it is looking towards the left side of the opponent.


Angles

When we calculate the aiming angle we just need to make our warrior turn towards the direction that will decrease the size of the aiming angle.

Library MathUtil has a couple of helper functions that you can use for quicker bot development.

♖ Extra tips

  1. Better aiming - Although the warrior can turn towards the opponent it can’t aim properly and misses him very often. You can easily fix that by adjusting the rotation speed when the aim angle gets smaller. For example when the angle is smaller than 15 degrees don’t rotate with RIGHT or LEFT but with SLOW_RIGHT and SLOW_LEFT rotations.

  2. Following opponent - When the aim angle is small enough you can make your warrior move forward with Api command setSpeed(int unitId, Speed speed). This will automatically make it follow the opponent when it tries to flee. But be careful, your warrior units now go close to the opponents when they fight them and will thus be often killed by their teammates that are aiming at the same opponent. You will need to implement some team kill prevention logic to fix that! MathUtil will come in handy.

  3. Choose your target - If your warrior has more then one opponent in it’s viewing area, shoot at the one with the least amount of health or pick some other interesting strategy.

Next up

In the next example we will improve the logic for spawning our units. It is very important that we have a good balance between how many worker and how many warrior units we spawn and have on the map at the same time. Follow the link below to learn more.

Next: Smartly spawn your units