zoukankan      html  css  js  c++  java
  • [转载]Silverlight 动画与向量

    这次将使用向量和动画结合来模拟物体在具有重力下的运动效果,主要逻辑:
    1.定义小球的重力,摩擦力、以及运动速度的递减变量
    2.根据鼠标拖拽小球的前后位置的差值来设置小球的起始速度,拖动越快速度也就越大。
    3.小球开始运动的时候 ,首先根据小球的重力从新设置小球在Y轴上的运动速度,其次检测小球在运动到上下左右边界的情况,以及运动到角
    落的情况,并重新设置小球位置。
    运行效果图如下:
    一、ball对象主要逻辑均有ball对象处理,其代码如下:
    ball.xaml 代码
    <UserControl.Resources>
    <Storyboard x:Name="Move" Duration="00:00:00"/>
    </UserControl.Resources>
    <Canvas x:Name="LayoutRoot" Width="40" Height="40">
    <Ellipse Width="40" Height="40" Canvas.Left="0" Canvas.Top="0" x:Name="redEllipse">
    <Ellipse.Fill>
    <RadialGradientBrush>
    <RadialGradientBrush.RelativeTransform>
    <TransformGroup>
    <ScaleTransform ScaleX="1" ScaleY="1"/>
    <SkewTransform AngleX="0" AngleY="0"/>
    <RotateTransform Angle="0"/>
    <TranslateTransform X="0.15" Y="-0.125"/>
    </TransformGroup>
    </RadialGradientBrush.RelativeTransform>
    <GradientStop Color="#FFFFFFFF" Offset="0"/>
    <GradientStop Color="#FFFF0000" Offset="1"/>
    </RadialGradientBrush>
    </Ellipse.Fill>
    </Ellipse>
    </Canvas>
    ball.xaml.cs代码
    public partial class ball : UserControl
    {
    /// <summary>
    /// 重力
    /// </summary>
    public double Gravity;
    /// <summary>
    /// 容器高度
    /// </summary>
    public double RootHeight;
    /// <summary>
    /// 容器宽度
    /// </summary>
    public double RootWidth;
    /// <summary>
    /// 是否捕捉焦点
    /// </summary>
    private bool isMouseCaptured;
    /// <summary>
    /// 鼠标位置
    /// </summary>
    private Point mousePosition;
    /// <summary>
    /// 鼠标位置缓存
    /// </summary>
    private Point oldMouse;
    /// <summary>
    /// 小球位置
    /// </summary>
    private Point ballPosition;
    /// <summary>
    /// 小球X轴速度
    /// </summary>
    private double VelocityX = 0;
    /// <summary>
    /// 小球Y轴速度
    /// </summary>
    private double VelocityY = 0;
    //偏移量,X/Y轴速度均要乘以此变量
    private double restitution = .6;
    //摩擦力
    private double friction = .9;
    public ball()
        {
            InitializeComponent();
    this.MouseLeftButtonDown += new MouseButtonEventHandler(ball1_MouseLeftButtonDown);
    this.MouseLeftButtonUp += new MouseButtonEventHandler(ball1_MouseLeftButtonUp);
    this.MouseMove += new MouseEventHandler(ball1_MouseMove);
            Move.Completed += new EventHandler(Move_Completed);
        }
    void Move_Completed(object sender, EventArgs e)
        {
    //根据重力计算小球速度,重力影响Y轴速度
            VelocityY += Gravity;
    //根据小球上一次的位置参数、小球的速度和方向更新ballPosition的值
            ballPosition.X += VelocityX;
            ballPosition.Y += VelocityY;
    //考虑小球运动到角落的情况
    if (ballPosition.Y + this.Height >= RootHeight && (ballPosition.X + this.Width) >= RootWidth)
            {
    //小球运动到右下角
                ballPosition.X = RootWidth - (this.Width + 1);
            }
    if (ballPosition.Y + this.Height >= RootHeight && ballPosition.X <= 0)
            {
    //小球运动到左下角
                ballPosition.X = 0;
                VelocityX *= -restitution;
            }
    if (ballPosition.Y <= 0)
            {
    //小球运动到上边界的时候,则设置其Top值不能小于0,改变其Y轴运动方向
                ballPosition.Y = 0;
                VelocityY *= -restitution;
            }
    else if ((ballPosition.Y + this.Height) >= RootHeight)
            {
    //小球运动到下边界的时候,则设置其Top值为容器高度减自身高度,改变其Y轴运动方向,
    //每次运动到底部都要根据虚拟的摩擦力来使X轴的速度减慢
                ballPosition.Y = RootHeight - this.Height;
                VelocityY *= -restitution;
                VelocityX *= friction;
            }
    else if ((ballPosition.X + this.Width) >= RootWidth)
            {
    //小球运动到右边界,则设置其Left值最大值为容器宽度减自身宽度,并改变X轴速度的方向
                ballPosition.X = RootWidth - this.Width;
                VelocityX *= -restitution;
            }
    else if (ballPosition.X <= 0)
            {
    //小球运动到左边界,则设置其Left值最小为0,不能超出边界,并改变X轴速度的方向
                ballPosition.X = 0;
                VelocityX *= -restitution;
            }
    //设置小球最新位置
            Canvas.SetLeft(this, ballPosition.X);
            Canvas.SetTop(this, ballPosition.Y);
            Move.Begin();
        }
    void ball1_MouseMove(object sender, MouseEventArgs e)
        {
            FrameworkElement item = sender as FrameworkElement;
    if (isMouseCaptured)
            {
    //记录鼠标点击点位置
                oldMouse.X = mousePosition.X;
                oldMouse.Y = mousePosition.Y;
    //计算当前对象的坐标位置,根据扑捉点位置和当前位置计算
    double deltaV = e.GetPosition(null).Y - mousePosition.Y;
    double deltaH = e.GetPosition(null).X - mousePosition.X;
    //计算小球最新位置
    double newTop = deltaV + Canvas.GetTop(item);
    double newLeft = deltaH + Canvas.GetLeft(item);
    //设置对象的新位置
                Canvas.SetTop(this, newTop);
                Canvas.SetLeft(this, newLeft);
    //检测小球拖动过程中是否触碰到边界
    if (Canvas.GetLeft(this) < 0 || Canvas.GetTop(this) < 0)
                {
                    outOfBounds(item);
                }
    if (Canvas.GetLeft(this) + this.Width >= RootWidth)
                {
                    outOfBounds(item);
                }
    if (Canvas.GetTop(this) + this.Height >= RootHeight)
                {
                    outOfBounds(item);
                }
                mousePosition = e.GetPosition(null);
    //根据拖拽前后位置的差值设置小球运动的启始速度
                VelocityX = (mousePosition.X - oldMouse.X) / 2;
                VelocityY = (mousePosition.Y - oldMouse.Y) / 2;
            }
        }
    void ball1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement item = sender as FrameworkElement;
            isMouseCaptured = false;
            item.ReleaseMouseCapture();
            mousePosition.X = mousePosition.Y = 0;
            item.Cursor = null;
    //小球初始位置
            ballPosition.X = Canvas.GetLeft(this);
            ballPosition.Y = Canvas.GetTop(this);
            Move.Begin();
        }
    void ball1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
    //捕捉焦点、停止动画、从新计算鼠标位置
            Move.Stop();
            FrameworkElement item = sender as FrameworkElement;
            mousePosition = e.GetPosition(null);//获取鼠标位置
            isMouseCaptured = true;
            item.CaptureMouse();
            item.Cursor = Cursors.Hand;
            VelocityX = 0;
            VelocityY = 0;
        }
    /// <summary>
    /// 处理小球超出边界的行为,当执行此方法将释放焦点,并开始动画
    /// </summary>
    private void outOfBounds(FrameworkElement item)
        {
            isMouseCaptured = false;
            item.ReleaseMouseCapture();
            item.Cursor = null;
            ballPosition.X = Canvas.GetLeft(this);
            ballPosition.Y = Canvas.GetTop(this);
            Move.Begin();
        }
    }
    二、gravityBall对象
    此对象容器,承载小球
    gravityBall.xaml代码
    <Canvas x:Name="LayoutRoot" Background="White" Width="800" Height="600">
    <Rectangle x:Name="borderStroke" Width="800" Height="600" Stroke="#FF000000" Canvas.Left="0" Canvas.Top="0">
    <Rectangle.Fill>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FF03174D" Offset="1"/>
    <GradientStop Color="#FFC8C8C8" Offset="0"/>
    </LinearGradientBrush>
    </Rectangle.Fill>
    </Rectangle>
    <Slider Width="150" Canvas.Top="38" Canvas.Left="12" x:Name="gravitySlider"/>
    <TextBlock Text="重 力: " TextWrapping="Wrap" Canvas.Left="14" Canvas.Top="10" x:Name="msgGravity"/>
    </Canvas>
    gravityBall.xaml.cs代码
    public partial class gravityBall : Page
    {
    private ball redBall;
    //初始重力
    private double globalGravity = .6;
    public gravityBall()
        {
            InitializeComponent();
            redBall = new ball();
            gravitySlider.Minimum = 0;
            gravitySlider.Maximum = 2;
            gravitySlider.Value = globalGravity;
            msgGravity.Text = "重 力: " + globalGravity;
            Canvas.SetLeft(redBall, 100);
            Canvas.SetTop(redBall, 100);
            redBall.Gravity = globalGravity;
            redBall.RootWidth = LayoutRoot.Width;
            redBall.RootHeight = LayoutRoot.Height;
            LayoutRoot.Children.Add(redBall);
            gravitySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(gravitySlider_ValueChanged);
        }
    private void gravitySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
    //更改小球的重力
            globalGravity = gravitySlider.Value;
            redBall.Gravity = globalGravity;
            msgGravity.Text = "重 力: " + globalGravity.ToString("0.00");
        }
    }
    至此整个示例的的代码完成。

  • 相关阅读:
    使用 pymssql 调用存储过程
    控制input框的输入格式
    Pycharm创建指定版本的Django
    div在页面中居中显示
    odoo12--centos7搭建odoo12
    odoo12--models模型
    odoo12--创建第一个模块
    odoo12模块目录
    odoo12代码目录说明
    win10安装odoo12教程
  • 原文地址:https://www.cnblogs.com/makubexsoft/p/1942783.html
Copyright © 2011-2022 走看看