Как создать плавное движение объекта в С#

Всем привет! В рамках учебного проекта создаю платформер на Windows Forms. Смог реализовать движение, прыжок, однако не могу догадаться, как сделать "плавный" кувырок. Плавный - означает ускорение в начале и замедление в конце. Плюс, думается мне, что движение тоже реализовано не совсем правильно.

Код реализации RigidBody:

class RigidBody
{
    public PointF Position { get; set; }
    public PointF Velocity { get; set; }
    public float Mass { get; set; }
    public bool Gravity { get; set; }
    public PointF Force { get; set; }
    //public Rectangle Hitbox { get; set; }
    public float Spring { get; set; }
    public float Friction { get; set; }

    public RigidBody()
    {
        Mass = 1;
        Gravity = true;
    }

    public virtual void Update(float dt)
    {
        var force = Force;
        if (Gravity)
            force = new PointF(force.X - Friction * 9.8f * Mass, force.Y + 9.8f * Mass);

        var ax = force.X / Mass;
        var ay = force.Y / Mass;

        Velocity = new PointF(Velocity.X + ax * dt, Velocity.Y + ay * dt);
        Position = new PointF(Position.X + Velocity.X * dt, Position.Y + Velocity.Y * dt);
    }

    public void OnGroundCollision(float groundY)
    {
        if (Velocity.Y < -float.Epsilon)
            return;
        Position = new PointF(Position.X, groundY - 0.0001f);
        Velocity = new PointF(Velocity.X, -Velocity.Y * Spring);
    }

Код реализации игрока:

class Player : RigidBody
{
    //private readonly Dictionary<PlayerAction, string[]> animations;
    public int HealthPoint { get; set; }
    public float Width { get; set; }
    public float Height { get; set; }
    public float JumpForce { get; set; } = 50;
    public float Speed { get; set; } = 10;

    public Player() : base()
    { 
    }

    public void Move(float speedDirection)
    {
        Velocity = new PointF(Velocity.X + speedDirection, Velocity.Y);
    }

    public void Jump()
    {
        if (Position.Y + Height / 2 > World.Ground - 10)
            Velocity = new PointF(Velocity.X, Velocity.Y - JumpForce);
    }

    public void Roll()
    {
        Velocity = new PointF(Velocity.X + 2, Velocity.Y);
        Position = new PointF(Position.X + Velocity.X, Position.Y);
    }

    public override void Update(float dt)
    {
        if (Position.Y + Height / 2 > World.Ground)
            OnGroundCollision(World.Ground - Height / 2);
        base.Update(dt);
    }
}

Код формы:

public partial class GameForm : Form
{
    private Player player;
    private DateTime lastUpdate = DateTime.MinValue;
    private bool keyPressed = false;
    public GameForm()
    {
        InitializeComponent();
        SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);

        Size = new Size(800, 600);

        player = new Player()
        {
            Height = 50,
            Width = 50,
            Position = new PointF(200, 100),
            Spring = 0,
            //Friction = 0.2f
        };

        Application.Idle += delegate { Invalidate(); };
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Update();
        e.Graphics.DrawLine(Pens.Aquamarine, 0, World.Ground, Width, World.Ground);
        e.Graphics.FillRectangle(Brushes.Black, 
                                 player.Position.X - player.Width / 2,
                                 player.Position.Y - player.Height / 2,
                                 player.Width,
                                 player.Height);
    }

    new void Update()
    {
        var now = DateTime.Now;
        var dt = (float)(now - lastUpdate).TotalMilliseconds / 100;

        if (lastUpdate != DateTime.MinValue)
            player.Update(dt);

        lastUpdate = now;
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        switch(e.KeyCode)
        {
            case Keys.Space:
                player.Jump();
                keyPressed = true;
                break;
            case Keys.D:
                if (!keyPressed)
                {
                    player.Move(player.Speed);
                    keyPressed = true;
                }
                break;
            case Keys.A:
                if (!keyPressed)
                {
                    player.Move(-player.Speed);
                    keyPressed = true;
                }
                break;
            case Keys.Z:
                player.Roll();
                break;
        }
        base.OnKeyDown(e);
    }

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        base.OnKeyPress(e);
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        keyPressed = false;
        switch (e.KeyCode)
        {
            case Keys.D:
                player.Velocity = new PointF(0, player.Velocity.Y);
                break;
            case Keys.A:
                player.Velocity = new PointF(0, player.Velocity.Y);
                break;
        }
        base.OnKeyUp(e);
    }

Ответы (0 шт):