[Silverlight动画]转向行为 - 群落

简介: 说到群落,很难不引用Craig Reynolds和他的"boilds"模拟系统。Reynolds很牛的将一个看似非常恐怖的复杂过程,拆成了几个比较简单的行为。 想想鸟群,它含有三个主要角色: 首先,鸟们都保持在同一个区域。

 

说到群落,很难不引用Craig Reynolds和他的"boilds"模拟系统。Reynolds很牛的将一个看似非常恐怖的复杂过程,拆成了几个比较简单的行为。
想想鸟群,它含有三个主要角色:
首先,鸟们都保持在同一个区域。如果有只鸟离队伍远了,就该马上归队。这叫凝聚。如图


其次,尽管鸟们都在一起飞,但是要避免不会互相碰到。为此,它们各自都有一个空间来预防其它鸟太接近。这叫分离。

 

最后,鸟们飞行在同一个方向。当然各自的角度不一定相同,但是大方向是差不多的。这叫队列。

 

这三个行为 凝聚分离队列组成了复杂的群落行为。
当考虑鸟群时,就以整个群落是一条心去想象,或者认为每个鸟都充分认识群中的其它鸟。我不想为此去争论什么,但我要说,当开始理解这三个行为,何以促成群落 行为时,你会发现,每个鸟根本不需要知道多少东西,也不需要什么民主集中一条心来指挥群落。实际上,每个鸟就只需要看看临近的几只伙伴。如果靠太近就离远 点,如果方向差太多就转过来点,最终以此形成了传说中的群落行为。
尽管群落行为技术上被拆成了三个子行为,然而它们几乎总是捆绑出现的。一般不太会只对角色使用其中一两个行为,所以就把这仨放于同一个函数中好了。这样效率也高,避免要做三次循环。
        public void flock(List<Vehicle> vehicles) {
            Vector2D averageVelocity = _velocity.clone();
            Vector2D averagePosition = new Vector2D(0, 0);
            int inSightCount = 0;
            for (int i = 0; i < vehicles.Count; i++)
            {
                Vehicle vehicle = vehicles[i];
                if (vehicle!=this&&inSight(vehicle))
                {
                    averageVelocity = averageVelocity.add(vehicle.velocity);
                    averagePosition = averagePosition.add(vehicle.position);
                    if (tooClose(vehicle))
                    {
                        flee(vehicle.position);
                        inSightCount++;
                    }
                }
            }
            if (inSightCount>0)
            {
                averageVelocity = averageVelocity.divide(inSightCount);
                averagePosition = averagePosition.divide(inSightCount);
                seek(averagePosition);
                _steeringForce.add(averageVelocity.subtract(_velocity));
            }
        }
首先,传递一个持有机车的数组。通过遍历这个数组找出进入视野的其它机车。把进入视野的机车的速度和位置都加起来,然后统计次数,最后以此求得平均值。如果机车靠太近,用避开函数离开之,以此实现分离。唯一要注意的地方就是处理过程中对自身的忽略。
当走完整个数组,算出平均速度和位置后,寻找平均位置,叠加平均转向力即完成任务。
似乎没啥了不起,不过有几个函数我们还没介绍呢,视野中(inSight)和太接近(tooClose):
inSight 函数判定一个机车是否能看到另一个机车。为此,先要检测两者间距离是否在视野范围内,如果不是就返回false。接着用向量的数学运算判断机车的前后关 系,这里采用的实现方式比较死板,只认前方的机车,在后面就当作看不见。这个做做例子够用了,如果要作改进,可以先考虑做一个可变化的视野范围。窄的视野 范围意味着角色只能沿着视野方向,注意不到两边,宽的视野意味着角色可以看到边上的一些东西。不同的视野范围,会导致不同的群落模式。
再来是tooClose函数,这个简单的不想说了。
        private double _inSightDist = 200;
        private double _tooCloseDist = 60;

        private bool tooClose(Vehicle vehicle)
        {
            return _postion.dist(vehicle.position) < _tooCloseDist;
        }

        private bool inSight(Vehicle vehicle)
        {
            if (_postion.dist(vehicle.position)>_inSightDist)
            {
                return false;
            }
            Vector2D heading = _velocity.clone().normalize();
            Vector2D difference = vehicle.position.subtract(_postion);
            double dotProd = difference.dotProd(heading);
            if (dotProd<0)
            {
                return false;
            }
            return true;
        }

测试:

<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" x:Class="Steer.FlockTest"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="White">


    </Grid>
</UserControl>

    public partial class FlockTest : UserControl
    {
        private List<Vehicle> _vehicles;
        private int _numVehicles = 30;
        public FlockTest()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(FlockTest_Loaded);
        }

        void FlockTest_Loaded(object sender, RoutedEventArgs e)
        {
            _vehicles = new List<Vehicle>();
            for (int i = 0; i < _numVehicles; i++)
            {
                SteeredVehicle vehicle = new SteeredVehicle();
                RegularPolygon rp = new RegularPolygon();
                rp.Width = 15;
                rp.Height = 15;
                rp.Fill = new SolidColorBrush(Colors.Blue);
                rp.PointCount = 3;
                TransformGroup tf = new TransformGroup();
                CompositeTransform ct = new CompositeTransform();
                tf.Children.Add(ct);
                rp.RenderTransform = tf;
                ct.Rotation = 90;
                vehicle.Children.Add(rp);
                vehicle.Width = 15;
                vehicle.Height = 15;
                vehicle.HorizontalAlignment = HorizontalAlignment.Left;
                vehicle.VerticalAlignment = VerticalAlignment.Top;
                LayoutRoot.Children.Add(vehicle);
                _vehicles.Add(vehicle);
            }
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            foreach (SteeredVehicle vehicle in _vehicles)
            {
                vehicle.flock(_vehicles);
                vehicle.update();
            }
        }
    }
相关文章
|
容器
Silverlight & Blend动画设计系列二:旋转动画(RotateTransform)
原文:Silverlight & Blend动画设计系列二:旋转动画(RotateTransform)   Silverlight的基础动画包括偏移、旋转、缩放、倾斜和翻转动画,这些基础动画毫无疑问是在Silverlight中使用得最多的动画效果,其使用也是非常简单的。
1013 0
|
容器 数据可视化 内存技术
Silverlight & Blend动画设计系列一:偏移动画(TranslateTransform)
原文:Silverlight & Blend动画设计系列一:偏移动画(TranslateTransform)   用户界面组件、图像元素和多媒体功能可以让我们的界面生动活泼,除此之外,Silverlight还具备动画功能,它可以让应用程序“动起来”。
816 0
Silverlight & Blend动画设计系列四:倾斜动画(SkewTransform)
原文:Silverlight & Blend动画设计系列四:倾斜动画(SkewTransform)   Silverlight中的倾斜变化动画(SkewTransform)能够实现对象元素的水平、垂直方向的倾斜变化动画效果。
840 0
|
容器
Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)
原文:Silverlight & Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)   正如你所看到的,Blend是一个非常强大的节约时间的设计工具,在Blend下能够设计出很多满意的动画作品,或许他具体是怎么实现的,通过什么方式实现的我们还是一无所知。
941 0
Silverlight & Blend动画设计系列七:模糊效果(BlurEffect)与阴影效果(DropShadowEffect)
原文:Silverlight & Blend动画设计系列七:模糊效果(BlurEffect)与阴影效果(DropShadowEffect)   模糊效果(BlurEffect)与阴影效果(DropShadowEffect)是两个非常实用和常用的两个特效,比如在开发相册中,可以对照片的缩略图添加模糊效果,在放大照片的过程中动态改变照片的大小和模糊的透明度来达到一个放大透明的效果。
1085 0
Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效
原文:Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效   当我们在进行Silverlight & Blend进行动画设计的过程中,可能需要设计出很多效果不一的图形图像出来作为动画的基本组成元素。
1046 0
|
API
Silverlight & Blend动画设计系列十:Silverlight中的坐标系统(Coordinate System)与向量(Vector)运动
原文:Silverlight & Blend动画设计系列十:Silverlight中的坐标系统(Coordinate System)与向量(Vector)运动   如果我们习惯于数学坐标系,那么对于Silverlight中的坐标系可能会有些不习惯。
1260 0

热门文章

最新文章

下一篇
无影云桌面