[Silverlight动画]转向行为 - 到达行为

2010-06-25 03:18

[Silverlight动画]转向行为 - 到达行为

by 王喆(nasa)

at 2010-06-24 19:18:00

original http://www.cnblogs.com/nasa/archive/2010/06/24/sl-steering-behaviors-7-Arrive.html


作者: 王喆(nasa) 发表于 2010-06-24 19:18 原文链接 阅读: 497 评论: 1

到达行为在很多场合都可以被当作是寻找行为。实际上,它们之间的算法和处理方式都一样。唯一不同的是,在到达模式中,一辆机车在到达目标的某一距离时,会变成一种精确模式慢慢地靠近目标点。
为了了解到达行为的必要性,可以先运行一下SeekTest类,然后移动鼠标到某处让机车过来“抓住”它。会看到机车快速的越过了鼠标,接着它发现过头了,又返回来,还是过头了....于是会一直循环下去。这是因为机车始终保持着最大速度迈向目标,哪怕离目标只有几像素。
到达行为通过减速接近目标,解决了这个问题:

        public void arrive(Vector2D target) {
            Vector2D desiredVelocity = target.subtract(_postion);
            desiredVelocity.normalize();

            double dist = _postion.dist(target);
            if (dist>_arrivalThreshold)
            {
                desiredVelocity = desiredVelocity.multiply(_maxSpeed);
            }
            else
            {
                desiredVelocity = desiredVelocity.multiply(_maxSpeed * dist / _arrivalThreshold);
            }
            Vector2D force = desiredVelocity.subtract(_velocity);
            _steeringForce = _steeringForce.add(force);
        }

程序一开始和寻找行为一样。但是在期望速度乘以最大速率时,做了距离检测。如果距离大于某个值,那一切照旧。程序往后走,接着的事情也和寻找一样。
关键是,距离小于某个值时所做的事情。本来乘以_maxSpeed现改为乘以_maxSpeed * dist / _arriveThreshold。如果距离仅仅小于某个值一点点,那么dist / _arriveThreshold会非常接近1.0,可能是0.99。因此,期望速度的大小也会非常接近于(略小于)最大速率。如果距离接近0,那么得到 的比率也会非常非常小,期望速度改变也会很小。最终速度会趋向于0(假设只有一个行为作用于该机车)。

 

当然,转向机车类需要这么一个“某个值”属性,所以我们把它加上去:
private double _arrivalThreshold = 100;
public double arriveThreshold {
    get { return _arrivalThreshold; }
    set { _arrivalThreshold = value; }
}
看看这些是如何运用在测试类中的:

<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.ArriveTest"
    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">
            <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 ArriveTest : UserControl
    {
        double mouseX = 0;
        double mouseY = 0;
        public ArriveTest()
        {
            // Required to initialize variables
            InitializeComponent();

            Loaded += new RoutedEventHandler(SeekTest_Loaded);
        }

        void SeekTest_Loaded(object sender, RoutedEventArgs e)
        {
            MouseMove += new MouseEventHandler(SeekTest_MouseMove);
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

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

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

和测试寻找行为唯一的不同就是在Rendering中把函数名seek换成了arrive。运行一下试试把鼠标移动到某处,机车先是以寻找模式发现 目标,然后慢慢的停在鼠标所在位置。再次移动鼠标又会回到寻找模式。通过调整arriveThreshold属性,看看机车接近目标时的变化吧。
如果愿意可以再试着玩玩增加多辆机车,或者现在就进入下一个行为:追捕。 

评论: 1 查看评论 发表评论

软件研发团队管理年会(上海,7.10-7.11)


最新新闻:
· 我完全支持云计算,但不要让它成为一个噱头(2010-06-25 08:12)
· Android 2.2 for Intel 夏天公布(2010-06-25 08:10)
· 盛大“出海”(2010-06-25 07:46)
· 视频:三星 Windows Phone 7 原型机上手玩(2010-06-25 07:44)
· iBooks 扼杀字体,苹果正破坏标准(2010-06-25 07:42)

编辑推荐:C#会重蹈覆辙吗?反射及元数据的性能问题

网站导航:博客园首页  个人主页  新闻  闪存  小组  博问  社区  知识库