Как создать плавное движение объекта в С#
Всем привет! В рамках учебного проекта создаю платформер на 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);
}