Enemy Kart
Because we made VehicleMove
controllable via the pedal and turn variables, we can use the same exact vehicle movement code for both the player and the enemy. The only difference is that while the player uses keyboard keys to change the pedal and turn variables, the enemy will use some AI logic to decide whether it should press the gas and/or turn the kart.
Make a new subclass of VehicleMove
called EnemyMove
. For now, just override its Update
function, and make sure it calls VehicleMove::Update
.
Now make a new Actor
subclass called Enemy
, it needs:
- A scale of
0.75f
- A
MeshComponent
using"Assets/Kart.gpmesh"
and set to texture index6
- An
EnemyMove
Now look at the Assets/HeightMap/Path.csv
file. This file contains the cell row (CellX
) and cell column (CellY
) for each of the cells on the desired route the Enemy
should take.
In EnemyMove
, add a std::vector
of Vector3
s to the member data, which you’ll use to store the different points on the route. Then load path file in the EnemyMove
constructor. For each CSV row, convert the (cell row, cell col) to world space with the height map’s CellToWorld
and store the actual world space position of each target point in your std::vector
.
Once loaded, set the position of the owner to the first point in the path.
Now in Game
, dynamically allocate an Enemy
in LoadData
, and save it in a member variable.
Your enemy kart (in purple) should appear to the right and in front of your kart at the starting line:
Making the Enemy Move
Now in EnemyMove
, you should track the index of the “next” target point on the route. Since the enemy spawns at point 0, your “next” target point should initialize to 1.
Now in EnemyMove::Update
, you need to implement the logic as discussed in the lecture slides. This should happen before the call to VehicleMove::Update
, since you want to decide whether to accelerate and/or turn before the physics updates in VehicleMove
.
The basic idea is:
- Figure out if you’re “close enough” to the next target point, and if you are, advance your “next target point” index. Keep in mind the path will run out as the Enemy takes laps, so don’t forget to wrap around back to 0
- Figure out if the next target point is “reasonably” in front of you, and if it is, set the pedal to true
- Figure out if you think you need to turn, and if so, whether it’s left or right, and set the turn state based on this
Each of the above steps should be independent checks. For example, it’s possible that the enemy will decide to both accelerate and turn at the same time.
Hint: Step #2 can be figured out with a dot product, and step #3 can be figured out with a dot product to decide if you should turn, and a cross product to decide if you should turn left or right.
Once this is working properly, you should see the enemy kart effectively following the path, as in the original lab video. Here’s a picture of what it might look like:
If you notice the enemy car getting stuck and trying to endlessly turn to reach a point, it probably means step #1 is too strict (or steps #2/#3 aren’t making the right decisions).
Finally, if you think it’ll be too easy to beat the enemy driver, you can (optionally) give the enemy a better kart by changing some of the tunable parameters. For example, I went with a linear acceleration between 500 and 2500, an angular drag of 0.9f, and a ramp time of 1.5f.
Once you’ve pushed this code, you’re ready to move on to part 3.