Thursday, December 13, 2007



After some "deliberation", my scissor creatures are now 3 times as large, and 10 times as few. Doing this allowed me to involve more complex sense and think routines as many many little scissors quickly bogged down the engine.

The perception function, only searching for the player, implements a distance check, uses the dot product to determine if the player is in front, and a ray cast to see if the player is not obstructed to determine if we can actually see the player. While this works very well for initial perception of the player, it can be easy to deceive the AI by running behind it. To overcome this, I crafted the logic so that when we have been following the player, and they run out of the field of view, we simply check the distance again and maintain pursuit if the player is close enough (most of the time).

When the AI is not chasing down the player, it will follow predetermined paths. Currently, I have 4 of these paths, with two AI spawned on each. Because of this, and the way that the AI move (quick, but slow to stop) they seem to race around some invisible track. In a way, this comes across as a game that the scissors play normally. The screen shot below shows one of these paths with the AI running about.



Within the AI, I have 4 important functions.

  • The first, "think", is a scheduled routine that calls the sensory "checkFOVPlayer", then carries out the simple finite state automata. The FSA has two states, following the player, and not following the player. The states are guided simply by whether or not the AI can "see" the player (or if it has "forgotten" where the player is, see above).

  • The second, "checkFOVPlayer", determines if the player is in the field of view of the AI. It is explained in some detail above, and is included below.

  • The "onCollision" callback event is being used for attacking the player. When the AI rams into the player, it will push them both apart and damage the player. Very simple response, but it is effective.

  • The last, "onReachDestination", is another callback which is triggered when the engine finishes moving the object to its destination. When this occurs, and the AI is not following the player (running the track), it will iterate to the next node and let the engine move us to the next node.




function scissorbody::checkFOVPlayer(%this,%obj) {
%line = VectorSub(%obj.player.getPosition(),%obj.getPosition());
//%dist = VectorLen(%line);
%dist = manhattanDistance(%line);
%cantsee = true;
if (%dist < dot =" VectorDot(%obj.getEyeVector(),%line);"> 0.0) {
%typemask = %TypeMasks::TerrainObjectType & $TypeMasks::StaticShapeObjectType;
if (ContainerRayCast(%obj.getPosition(),%obj.player.getPosition(),%typemask) $= 0) {
%obj.setMoveDestination(%obj.player.getPosition(),true);
%obj.followPlayer = true;
%cantsee = false;
}
}
}
if (%cantsee && ($dist > 30)) {
%obj.followPlayer = false;
%obj.stop();
}
}

No comments: