躲避就是追捕的反行为。就像追捕类似于寻找,躲避类似于避开。
本质上讲,是预测出机车将要去到的位置并远离它。在这里所有的原则都和追捕相同。实际上,就连实现都几乎一模一样,除了最后一行用避开代替寻找:
public void evade(Vehicle target)
{
double lookAheadTime = position.dist(target.position) / _maxSpeed;
Vector2D predictedTarget = target.position.add(target.velocity.multiply(lookAheadTime));
flee(predictedTarget);
}
直接把追捕和躲避放一起测试:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Steer" xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
mc:Ignorable="d"
x:Class="Steer.PursueEvadeTest"
d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot" Background="White">
<local:SteeredVehicle x:Name="myPursuer" HorizontalAlignment="Left" Height="40" VerticalAlignment="Top" Width="40" RenderTransformOrigin="0.5,0.5">
<ed:RegularPolygon Fill="Blue" Height="40" InnerRadius="1" PointCount="3" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" Width="40" RenderTransformOrigin="0.5,0.5" StrokeThickness="0">
<ed:RegularPolygon.RenderTransform>
<CompositeTransform Rotation="90"/>
</ed:RegularPolygon.RenderTransform>
</ed:RegularPolygon>
</local:SteeredVehicle>
<local:SteeredVehicle x:Name="myEvader" HorizontalAlignment="Left" Height="40" VerticalAlignment="Top" Width="40" RenderTransformOrigin="0.5,0.5">
<ed:RegularPolygon Fill="#FFFD00FF" Height="40" InnerRadius="1" PointCount="5" Stretch="Fill" Stroke="Black" StrokeThickness="0" UseLayoutRounding="False" Width="40"/>
</local:SteeredVehicle>
</Grid>
</UserControl>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Steer
{
public partial class PursueEvadeTest : UserControl
{
public PursueEvadeTest()
{
// Required to initialize variables
InitializeComponent();
Loaded += new RoutedEventHandler(PursueEvadeTest_Loaded);
}
void PursueEvadeTest_Loaded(object sender, RoutedEventArgs e)
{
myPursuer.position = new Vector2D(200, 200);
myPursuer.edgeBehavior = Vehicle.BOUNCE;
myEvader.position = new Vector2D(400, 300);
myEvader.edgeBehavior = Vehicle.BOUNCE;
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
myPursuer.pursue(myEvader);
myEvader.evade(myPursuer);
myPursuer.update();
myEvader.update();
}
}
}