有没有老哥会做这个跳动皮球的程序

img

这个应该不难吧?学过物理的话应该很简单的吧

效果图给你:

img

代码:

    public class SportBall
    {
        public SportBall(double mass, double energyLoss, double vx, double h, Point axisOrigin, Color c)
        {
            // 质量
            Mass = mass;
            // 每次撞击动能损失
            KineticEnergyLoss = energyLoss;
            // 水平方向初速度
            Vx = vx;
            // 初始高度
            InitHeight = h;
            // 由自由落体运动公式根据初始高度h计算初次落地时竖直方向速度
            Vy = Math.Sqrt(2 * h / g);

            // 总能量 = 动能 + 重力势能
            TotalEmergy = 0.5 * Mass * vx * vx + Mass * g * h;

            AxisOrigin = axisOrigin;
            BallColor = c;
            // 记录轨迹点
            pathList = new List<PointF>();
            pathList.Add(new PointF((float)(AxisOrigin.X + BallDiameter / 2), (float)(AxisOrigin.Y - BallDiameter / 2)));
        }

        #region 运动相关
        // 重力加速度g 9.8m/s^2
        private const double g = 98;
        // 每个阶段竖直上抛运动时长
        private double t0y;
        // 每一帧时刻
        private double t0x;
        // 质量 单位:kg
        public double Mass { get; private set; }
        // 每次撞击动能损失 单位:J
        public double KineticEnergyLoss { get; private set; }
        // 总能量
        public double TotalEmergy { get; private set; }
        // 初始高度
        public double InitHeight { get; private set; }
        // 相对于坐标系水平方向位移
        public double HorizontalDisplacement { get; private set; }
        // 相对于坐标系竖直方向位移
        public double VerticalDisplacement { get; private set; }
        // 每个阶段竖直上抛运动竖直方向初速度
        public double Vy { get; private set; }
        // 每个阶段竖直上抛运动水平方向初速度
        public double Vx { get; private set; }

        // y方向速度
        public double Vy_R { get; private set; }
        // x方向速度
        public double Vx_R { get; private set; }
        #endregion

        #region 外观相关
        // 球体颜色
        public Color BallColor { get; set; }
        // 球体直径
        public double BallDiameter { get; set; }
        #endregion

        #region 坐标系相关
        public Point AxisOrigin { get; private set; }
        #endregion

        List<PointF> pathList;

        // 开始运动
        public void StartSport(double timeSpan)
        {

            // 将毫秒换算成秒
            double ts = timeSpan / 1000;
            // 如果能量消耗完停止运动
            if (TotalEmergy <= 0) return;

            //1.水平方向做匀速直线运动
            HorizontalDisplacement += UniformSpeed(ts - t0x, Vx);
            t0x = ts;

            double displacement = ThrowUp(ts - t0y, Vy);
            if (displacement <= 0)
            {
                Collision();
                t0y = ts;
            }
            else
            {
                VerticalDisplacement = displacement;
            }
        }

        private double UniformSpeed(double t, double vx)
        {
            Vx_R = vx;
            return vx * t;
        }

        // 竖直上抛运动
        private double ThrowUp(double t, double v0)
        {
            Vy_R = v0 - g * t;
            return v0 * t - 0.5 * g * t * t;
        }
        // 碰撞
        private void Collision()
        {
            double newEnergy = TotalEmergy - KineticEnergyLoss;
            double rate = newEnergy / TotalEmergy;
            TotalEmergy = newEnergy;
            // 撞击之后根据损失后的总能量计算水平方向速度以及数值方向初速度
            Vx = Vx * rate;
            Vy = Math.Sqrt(2 * (TotalEmergy - 0.5 * Mass * Vx * Vx) / Mass);
        }

        public void Draw(Graphics g)
        {
            DrawAxis(g);
            DrawBall(g);
            DrawPath(g);
        }
        // 画球
        private void DrawBall(Graphics g)
        {
            if (BallDiameter <= 0) BallDiameter = 10;
            if (BallColor == null) BallColor = Color.Red;
            if (AxisOrigin == null) AxisOrigin = new Point(0, 0);
            double x = AxisOrigin.X + HorizontalDisplacement - BallDiameter / 2;
            double y = AxisOrigin.Y - VerticalDisplacement - BallDiameter / 2;
            g.FillEllipse(new SolidBrush(BallColor), (float)x, (float)y, (float)BallDiameter, (float)BallDiameter);
            pathList.Add(new PointF((float)(x + BallDiameter / 2), (float)(y + BallDiameter / 2)));
        }
        // 画坐标轴
        private void DrawAxis(Graphics g)
        {
            g.DrawLine(new Pen(new SolidBrush(Color.Black)), AxisOrigin.X, AxisOrigin.Y, (float)(HorizontalDisplacement + 200), AxisOrigin.Y);
            g.DrawLine(new Pen(new SolidBrush(Color.Black)), AxisOrigin.X, AxisOrigin.Y, AxisOrigin.X, (float)(AxisOrigin.Y - InitHeight - 50));
        }
        // 画运动轨迹
        private void DrawPath(Graphics g)
        {
            g.DrawLines(new Pen(new SolidBrush(Color.Black)), pathList.ToArray());
        }
    }