Sengoku Devlog 5
Spear Samurai AI:
I was able to complete the spear samurai AI last week, combined with Jon’s awesome animations! This now puts us at 6 standard enemies: the archer, the spear soldier, the spear samurai, the heavy samurai, the soldier with the rifle, and the ninja. It took me about 4 days to get this guy up and running in terms of the AI, with the biggest challenge being in determining the exact conditions that have to be met for the spear samurai to do its second attack type: a spear throw. We wanted this enemy to throw his spear at the player when the player was escaping, kind of like a last ditch effort to attack the player; however, defining what exactly we meant by the player escaping in terms of in game behavior was tricky. Did we mean whenever the enemy falls off the camera? Should the enemy throw his spear if he falls out of the camera view as a result of his own action, or should he only throw the spear if the player causes the enemy to fall out of the camera? How can I determine that the player caused the enemy to fall out of the camera view? Should the spear samurai throw his spear if the path it must take to reach the player is obstructed, meaning that it will not be able to reach the player and do its spear thrust attacks? How can I determine that the path to the player is obstructed? What if there is a ledge between the player and this enemy? These are some of the questions that came into mind while trying to get the spear throw in. After 2 days, I got it to where the enemy only throws his spear if he is still running to the player and 1 or more of these 3 conditions are met:
1.) The enemy has fallen out of the camera view as a result of the player’s movement, which I determine as the source of the enemy falling out of the view via 2 flags called characterAttempingToMoveLeft and characterAttempingToMoveRight; the condition basically works like this (not exact C# code but good enough to get the basic idea across):
if ((enemyXCord < leftSideOfCamera) && (player.characterAttemptingToMoveRight == true)) {
throwSpear();
else if ((enemyXCord > rightSideOfCamera) && (player.characterAttemptingToMoveLeft == true)) {
throwSpear();
}
Again, this is not the exact C# code, but the basic idea is this: if the enemy has fallen out of the camera view on the left side, and the player is moving right (represented by (enemyXCord < leftSideOfCamera) && (player.characterAttemptingToMoveRight == true)), then it is the player causing the enemy to fall out of the camera view because the player, in moving right, is causing the camera to move right. The same idea goes for falling out of the right side of the camera. Also, I choose to use the boolean flags instead of just straight up checking the player’s x velocity because the player’s x velocity is set to 0 whenever the player is moving against a wall, and this can throw things off for these types of checks because the camera follows the player at a slower speed than the player moves at. For example, this enemy would not throw the spear if it falls out of the camera view but the player’s x velocity is 0 because the user is trying to move the character into a wall. Using the boolean flags allows me to say that the user is still trying to move left or right, regardless if the velocity is set to 0 (I can probably also get rid of these flags entirely and just check if the user is holding the move left or right button, but this check can get longer than it needs to be if I want to do this for other controls like a joystick or d pad, a boolean simplifies this).
2.) If the path to the player is obstructed and the enemy is still inside of the camera, then throw the spear. Detecting path obstruction is essentially done by raycasting left and right, and if something is hit, then if the x value of the normal vector of that thing hit is greater than 1 it is an obstruction because this means the surface faces either left or right. The code for this is pretty long (but not too hard to understand), so I don’t really show it here; however, raycasting is the basic idea behind it all, just like it is for the final case below.
3.) If there is a ledge between the enemy and the player, throw the spear. Again, the check for a ledge is done via raycasting straight down at 3 different positions: the bottom left, the bottom center, and bottom right of the enemy. If any of these raycasts fails to hit something, then there is no floor there and the enemy may need to stop or else it will fall.
Below is a video of the AI in action!
New blood effect:
I was also able to update our blood effect last week. I drew up 6 different random red shapes inside of Piskel, along with 5 different blood splatters that spawn in right when a particle hits the surface of something, and self destruct after a time between 6 - 8 secs (assigned randomly in code to give more variation) has passed. In order to know when a particle has hit another collider, I made use of unity’s particle collisions option called SendCollisionMessages. After checking that option on, I then attached a script onto the particle effect itself where I put the method called OnParticleCollision(GameObject other) in, which is where all collision messages get sent for the particle effect game object. Using this method, along with the ParticleSystem.GetCollisionEvents() method, I am then able to handle the spawning in and correct positioning of the blood splatters. Below is a video of the effect in action:
Some more castle tileset progress:
I was also able to work more on the city tilesets, particularly on the castle tiles. The section with the tree murals, samurai mural on the sliding doors, and pointed roof is where we plan to put one of our main bosses at.
Thanks for reading!