首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Silverlight动画]转向行为 - 避开行为

[Silverlight动画]转向行为 - 避开行为

作者头像
用户1172164
发布2018-01-16 11:56:16
9250
发布2018-01-16 11:56:16
举报

避开行为与寻找行为彻底相反。实际上,除了代码最后一行用相减代替了相加以外,其它都一样。

public void flee(Vector2D target) {
    Vector2D desiredVelocity = target.subtract(_postion);
    desiredVelocity.normalize();
    desiredVelocity = desiredVelocity.multiply(_maxSpeed);
    Vector2D force = desiredVelocity.subtract(_velocity);
    _steeringForce = _steeringForce.subtract(force);
}

由于和寻找几乎一样,所以就不详细解释了。最后一句的含义是“很好,既然发现了目标,那就调头往回走吧。”在此为避开做一个简单的测试:

<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.FleeTest"
	d:DesignWidth="640" d:DesignHeight="480">

	<Grid x:Name="LayoutRoot" Background="White">
		<local:SteeredVehicle x:Name="myStar" 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>
	</Grid>
</UserControl>
	public partial class FleeTest : UserControl
    {
        double mouseX = 0;
        double mouseY = 0;
		public FleeTest()
		{
			// Required to initialize variables
            InitializeComponent();
            Loaded += new RoutedEventHandler(SeekTest_Loaded);
        }

        void SeekTest_Loaded(object sender, RoutedEventArgs e)
        {
            myStar.position = new Vector2D(100, 100);
            myStar.edgeBehavior = Vehicle.BOUNCE;
            myStar.velocity.length = 5;
            myStar.velocity.angle = Math.PI / 4;

            MouseMove += new MouseEventHandler(SeekTest_MouseMove);
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            myStar.flee(new Vector2D(mouseX, mouseY));
            myStar.update();
        }

        void SeekTest_MouseMove(object sender, MouseEventArgs e)
        {
            mouseX = e.GetPosition(null).X;
            mouseY = e.GetPosition(null).Y;
        }
    }

抛开代码中调用的函数名称不谈,最主要的不同是,用两行代码将机车的初始位置放在离场景边缘有一段距离的地方,并且把接触场景边缘后的反应改为反弹。删除这两行再测试,就知道为什么要加这两行了。机车会为了避开鼠标在角落间来回切换,导致近似看不见。

现在我们有了一对正反行为,接下来要做的是为这对行为创建一对机车来看看情况。

<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.SeekFleeTest1"
	d:DesignWidth="640" d:DesignHeight="480">

	<Grid x:Name="LayoutRoot" Background="White">
		<local:SteeredVehicle x:Name="mySeek" HorizontalAlignment="Left" Height="40" VerticalAlignment="Top" Width="40" RenderTransformOrigin="0.5,0.5" Margin="84,50,0,0">
			<ed:RegularPolygon Fill="#FFFF0C00" 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="myflee" 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>
	</Grid>
</UserControl>
	public partial class SeekFleeTest1 : UserControl
	{
		public SeekFleeTest1()
		{
			// Required to initialize variables
            InitializeComponent();
            Loaded += new RoutedEventHandler(SeekTest_Loaded);
        }

        void SeekTest_Loaded(object sender, RoutedEventArgs e)
        {
            mySeek.position = new Vector2D(200, 200);
            mySeek.edgeBehavior = Vehicle.BOUNCE;

            myflee.position = new Vector2D(100, 300);
            myflee.edgeBehavior = Vehicle.BOUNCE;

            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            mySeek.seek(myflee.position);
            myflee.flee(mySeek.position);
            mySeek.update();
            myflee.update();
        }
	}

这对机车叫寻找者(_seeker)和避开者(_fleer)。我相信不用再解释寻找者寻找避开者,避开者避开寻找者了吧。先运行一下看看两辆机车互动的效果,然后尝试改变它们的各种参数,再看看会发生什么。

我们还可以把两个行为同时用于一辆机车上。下面的例子中,机车A同时寻找和避开机车B,机车B同时寻找和避开机车C,机车C同时的寻找和避开机车A。这三辆机车会因为追捕各自的目标而形成一个圆。

<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.SeekFleeTest2"
	d:DesignWidth="640" d:DesignHeight="480">

	<Grid x:Name="LayoutRoot">
		<local:SteeredVehicle x:Name="myA" HorizontalAlignment="Left" Height="40" VerticalAlignment="Top" Width="40" RenderTransformOrigin="0.5,0.5">
			<ed:RegularPolygon Fill="#FFFF0C00" 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="myB" 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="myC" HorizontalAlignment="Left" Height="40" VerticalAlignment="Top" Width="40" RenderTransformOrigin="0.5,0.5">
			<ed:RegularPolygon Fill="#FFCEFF00" 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>
	</Grid>
</UserControl>
	public partial class SeekFleeTest2 : UserControl
	{
		public SeekFleeTest2()
		{
			// Required to initialize variables
            InitializeComponent();
            Loaded += new RoutedEventHandler(SeekTest_Loaded);
		}
        void SeekTest_Loaded(object sender, RoutedEventArgs e)
        {

            myA.position = new Vector2D(200, 200);
            myA.edgeBehavior = Vehicle.BOUNCE;
            myB.position = new Vector2D(400, 200);
            myB.edgeBehavior = Vehicle.BOUNCE;
            myC.position = new Vector2D(300, 260);
            myC.edgeBehavior = Vehicle.BOUNCE;

            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }
        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            myA.seek(myB.position);
            myA.flee(myC.position);

            myB.seek(myC.position);
            myB.flee(myA.position);

            myC.seek(myA.position);
            myC.flee(myB.position);

            myA.update();
            myB.update();
            myC.update();
        }
	}

记得再试试改变各种参数,观察发生的变化。如果这些都没问题了,那就开始探索下一个行为:到达。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2010-06-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档