[Silverlight动画]转向行为 - 机车

简介: 机车类是转向角色的基类,但它不提供任何转向行为,只处理与运动相关的基本内容,如位置,速度,质量以 及角色接触场景边缘后的反应(反弹还是穿越出现在另一边)。转向机车(SteeredVehicle)类继承机车类,并为之增加转向行为。

机车类是转向角色的基类,但它不提供任何转向行为,只处理与运动相关的基本内容,如位置,速度,质量以 及角色接触场景边缘后的反应(反弹还是穿越出现在另一边)。转向机车(SteeredVehicle)类继承机车类,并为之增加转向行为。使用这样的结构 其目的是为了让机车类可以用于仅需要移动而不需要转向行为的对象,同时也可以让转向机车类不考虑基本运动的细节而专心实现转向功能。

    /// <summary>
    /// 机车类
    /// </summary>
    public class Vehicle : Canvas
    {
        protected string _edgeBehavior = WRAP;
        protected double _mass = 1.0;
        protected double _maxSpeed = 10;
        protected Vector2D _postion;
        protected Vector2D _velocity;

        private CompositeTransform _compositeTransform;
        private TransformGroup _transformGroup;

        /// <summary>
        /// 边缘行为
        /// </summary>
        public const string WRAP = "wrap";
        public const string BOUNCE = "bounce";

        public Vehicle()
        {
            _postion = new Vector2D(0, 0);
            _velocity = new Vector2D(0, 0);
            this.Loaded += new System.Windows.RoutedEventHandler(Vehicle_Loaded);
        }

        void Vehicle_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            var transformGroup = this.RenderTransform as TransformGroup;
            if (transformGroup == null)
            {
                _transformGroup = new TransformGroup();
                this.RenderTransform = _transformGroup;
                _compositeTransform = new CompositeTransform();
                _transformGroup.Children.Add(_compositeTransform);
            }
        }

        public virtual void update()
        {
            _velocity.truncate(_maxSpeed);
            _postion = _postion.add(_velocity);

            if (_edgeBehavior == WRAP)
            {
                wrap();
            }
            else if (_edgeBehavior == BOUNCE)
            {
                bounce();
            }

            x = position.x;
            y = position.y;
            _compositeTransform.Rotation = _velocity.angle * 180 / Math.PI;
        }

        /// <summary>
        /// 反弹
        /// </summary>
        private void bounce()
        {
            Content stage = App.Current.Host.Content;
            if (position.x > stage.ActualWidth)
            {
                position.x = stage.ActualWidth;
                velocity.x *= -1;
            }
            else if (_postion.x < 0)
            {
                position.x = 0;
                velocity.x *= -1;
            }

            if (position.y > stage.ActualHeight)
            {
                position.y = stage.ActualHeight;
                velocity.y *= -1;
            }
            else if (position.y < 0)
            {
                position.y = 0;
                velocity.y *= -1;
            }
        }

        /// <summary>
        /// 巡游
        /// </summary>
        private void wrap()
        {
            Content stage = App.Current.Host.Content;
            if (position.x > stage.ActualWidth)
            {
                position.x = 0;
            }
            if (position.x < 0)
            {
                position.x = stage.ActualWidth;
            }
            if (position.y > stage.ActualHeight)
            {
                position.y = 0;
            }
            if (position.y < 0)
            {
                position.y = stage.ActualHeight;
            }
        }

        public string edgeBehavior
        {
            get
            {
                return _edgeBehavior;
            }
            set
            {
                _edgeBehavior = value;
            }
        }

        public double mass
        {
            get
            {
                return _mass;
            }
            set
            {
                _mass = value;
            }
        }

        public double maxSpeed
        {
            get
            {
                return _maxSpeed;
            }
            set
            {
                _maxSpeed = value;
            }
        }

        public Vector2D position
        {
            get
            {
                return _postion;
            }
            set
            {
                _postion = value;
                x = _postion.x;
                y = _postion.y;
            }
        }

        public Vector2D velocity
        {
            get
            {
                return _velocity;
            }
            set
            {
                _velocity = value;
            }
        }

        public double x
        {
            get
            {
                return _compositeTransform.TranslateX;
            }
            set
            {
                _compositeTransform.TranslateX = value;
                _postion.x = value;
            }
        }

        public double y
        {
            get
            {
                return _compositeTransform.TranslateY;
            }
            set
            {
                _compositeTransform.TranslateY = value;
                _postion.y = value;
            }
        }
    }

首先,采用两个2D向量来分别表示位置和速度,用_position,_velocity代替x,y,vx,vy。 大多数工作都发生在update函数中。一上来先试着截断(truncate)速度向量,确保不会超过最大速度,然后把速度向量加于(add)位置向量上。

_position = _position.add(_velocity);

接着检测是否在边缘,是的话调用wrap或者bounce函数。最终,根据位置向量更新对象的x和y值,并调整其角度:

  x = position.x;

  y = position.y;

  _compositeTransform.Rotation = _velocity.angle * 180 / Math.PI;

为Vehicle类做一个快速测试

<UserControl x:Class="Steer.VehicleTest"
    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"
    d:DesignHeight="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="White">
        <local:Vehicle x:Name="myStar" HorizontalAlignment="Left" Width="40" Height="40" VerticalAlignment="Top" Margin="0" RenderTransformOrigin="0.5,0.5">
        	<ed:BlockArrow Fill="#FFF4F4F5" Height="40" Orientation="Right" Stroke="Black" UseLayoutRounding="False" Width="40"/>
        </local:Vehicle>
    </Grid>
</UserControl>
    public partial class VehicleTest : UserControl
    {
        public VehicleTest()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
            myStar.edgeBehavior = SteeredVehicle.BOUNCE;
            myStar.position = new Vector2D(100, 100);
            myStar.velocity.length = 5;
            myStar.velocity.angle = Math.PI / 4;
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            myStar.update();
        }
    }
Vehicle对象并增加到显示列表。它的位置由一个2D向量决定:
_vehicle.position = new Vector2D(100, 100);

在例子中将Vehicle对象放到舞台中。它的位置由一个2D向量决定:_vehicle.position = new Vector2D(100, 100);

另一个改变位置的方法是直接设置位置的x和y值。

myStar.position.x = 100; 

myStar.position.y = 100;

或者直接设置被重载过的x和y,与此同时position也会跟着一起改变。

myStar.x = 100; 

myStar.y = 100;

例子中对设置速度采用了另一种方式:长度(length)和角度(angle),这也显示了向量在使用上的弹性。

myStar.velocity.length = 5;

myStar.velocity.angle = Math.PI / 4;

长度在这里指速度的大小,角度指方向。angle是弧度,所以Math.PI / 4相当于45度。

最后在CompositionTarget.Rendering事件上调用update函数。

机车类的测试已经足够了。让我们开始迈向更好更强大的转向行为之旅吧。

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

热门文章

最新文章