在c#中平滑移动一个点
本文关键字:一个 平滑 移动 | 更新日期: 2023-09-27 18:13:22
我对c#编程相当陌生,可能需要一些帮助来解决我遇到的这个问题。我的观点是,玩家的位置有一个非常不稳定的移动,这是由于按住一个键造成的延迟。像这样:e…
你如何使它更顺利地移动,(摆脱延迟?)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
namespace kek
{
class player
{
Image Player;
Point Playerposition = new Point(600, 200);
Form1 game;
public void playerinitialize(Form game)
{
this.game = (Form1)game;
Player = Bitmap.FromFile("player.png");
game.KeyDown += Game_KeyDown;
game.KeyPress += Game_KeyPress;
}
private void Game_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar < 50)
{
Playerposition.Y -= 10;
}
}
private void Game_KeyDown(object sender, KeyEventArgs e)
{
//Player move on keypress
if (e.KeyCode == Keys.W)
{
Playerposition.Y -= 10;
}
if (e.KeyCode == Keys.S)
{
Playerposition.Y += 10;
}
if (e.KeyCode == Keys.A)
{
Playerposition.X -= 10;
}
if (e.KeyCode == Keys.D)
{
Playerposition.X += 10;
}
//Playerposition.Y -= GamePad.GetState(PLayerIndex.One).ThumbSticks.Left.Y;
//Playerposition.Y += GamePad.GetState(PLayerIndex.One).ThumbSticks.Right.Y;
//Playerposition.X -= GamePad.GetState(PLayerIndex.One).ThumbSticks.Left.X;
//Playerposition.X += GamePad.GetState(PLayerIndex.One).ThumbSticks.Right.X;
}
public void Draw(Graphics graphics)
{
//on update
graphics.DrawImage(Player, Playerposition);
}
}
}
首先,最好不要在游戏开发中使用WinForms,但这并非不可能实现你想要的东西。
Key对于您的要求是不更新键事件中的位置。一个基本的游戏循环会持续做以下事情。首先,它会"更新位置",其次,它会在屏幕上绘制新的位置。
首先我们想要更新位置,但要做到这一点,我们必须知道一个键是否被按下。一种方法是捕获按下键和按上键事件,并在键盘图中标记它们。在更新中,我们现在只检查一个键是否按下,并相应地更新"播放器"的位置。
前段时间我刚刚创建了一个有趣的小演示项目。我会和你分享的。希望能有所帮助。
Update:在更新移动时也要考虑到每次两次抽取之间的时间可能不同。所以你应该在更新中决定应该添加的移动量。看蛇。UpdatePositions方法?我认为在1秒后玩家应该移动100个单位(像素)。因此,我根据现在和最后一帧之间的时间计算位移量。
创建一个名为SmoothAnimationDemo的Winform项目,并用下面的代码替换Form1.cs的代码。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace SmoothAnimationDemo
{
public partial class Form1 : Form
{
// check every x frames, calculate fps, adjust x
private readonly FrameInfo _frameInfo = new FrameInfo(DateTime.Now);
private readonly List<Animation> _animations = new List<Animation>();
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
FrameInfoVisible = false; // Set to true if needed.
RegisterAnimation(new Snake(this));
}
public bool FrameInfoVisible { get; set; }
public void RegisterAnimation(Animation animation)
{
_animations.Add(animation);
}
private int _skipframes = 1;
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Skip updating if needed.
if (_skipframes > 0)
{
_skipframes--;
}
else
{
_frameInfo.Update();
foreach (var animation in _animations)
animation.UpdatePositions(_frameInfo);
_skipframes = 0; // adjust to skip frames or leave at 0 to not skip frames.
}
// init drawing
var gfx = e.Graphics;
gfx.Clear(Color.Black);
// draw each frame.
foreach (var animation in _animations)
{
animation.Draw(gfx);
gfx.ResetTransform(); // in case the animation used transform methods.
}
// draw timer info on top
if (FrameInfoVisible)
_frameInfo.Draw(gfx);
// wait till a certain time has passed before drawing again.
//Thread.Sleep(10);
Invalidate(); // ensure new paint soon
}
}
/// <summary>
/// abstract base class for animations.
/// An animation contains two methods. First one used for updating animation data, eg positions.
/// Second one used for drawing the data onto a graphics object.
/// </summary>
public abstract class Animation : IDrawable, IAnimatable
{
public abstract void Draw(Graphics gfx);
public abstract void UpdatePositions(FrameInfo frameInfo);
}
/// <summary>
/// Contains info about our frames
/// </summary>
public class FrameInfo
{
public DateTime FirstFrameTime { get; set; }
public DateTime PrevFrameTime { get; set; }
public DateTime FrameTime { get; set; }
public int FrameCount { get; set; }
public double FramesPerSecond { get; set; }
public FrameInfo(DateTime now)
{
FirstFrameTime = now;
}
public void Update()
{
PrevFrameTime = FrameTime;
FrameTime = DateTime.Now;
FrameCount++;
FramesPerSecond = 1000.0 / (FrameTime - PrevFrameTime).TotalMilliseconds;
}
public void Draw(Graphics gfx)
{
gfx.DrawString("Frame time", SystemFonts.DefaultFont, Brushes.Black, 0, 0);
gfx.DrawString(String.Format(": {0:hh:mm:ss.zzzz}", FrameTime - FirstFrameTime), SystemFonts.DefaultFont, Brushes.Black, 70, 0);
gfx.DrawString("Frame", SystemFonts.DefaultFont, Brushes.Black, 0, 16);
gfx.DrawString(": " + FrameCount, SystemFonts.DefaultFont, Brushes.Black, 70, 16);
gfx.DrawString("FPS", SystemFonts.DefaultFont, Brushes.Black, 0, 32);
gfx.DrawString(": " + FramesPerSecond, SystemFonts.DefaultFont, Brushes.Black, 70, 32);
}
}
internal interface IAnimatable
{
void UpdatePositions(FrameInfo frameInfo);
}
internal interface IDrawable
{
void Draw(Graphics gfx);
}
/// <summary>
/// Animation module
/// </summary>
internal class Snake : Animation
{
public Snake(Control form)
{
form.KeyDown += form_KeyDown;
form.KeyUp += form_KeyUp;
}
readonly Dictionary<Keys, bool> _keyMap = new Dictionary<Keys, bool>
{
{ Keys.Up, false },
{ Keys.Down, false },
{ Keys.Left, false },
{ Keys.Right, false }
};
void form_KeyUp(object sender, KeyEventArgs e)
{
if (_keyMap.ContainsKey(e.KeyCode))
_keyMap[e.KeyCode] = false;
}
void form_KeyDown(object sender, KeyEventArgs e)
{
if (_keyMap.ContainsKey(e.KeyCode))
_keyMap[e.KeyCode] = true;
}
private PointF _headPos = new PointF(100.0f, 100.0f);
public override void UpdatePositions(FrameInfo info)
{
// Ensure that the motion is moving at a
var speed = 100; // 100 units within 1 second
var perc = (double)(info.FrameTime - info.PrevFrameTime).TotalMilliseconds / 1000;
var displaceAmount = (float)(speed * perc);
if (_keyMap[Keys.Up])
_headPos.Y -= displaceAmount;
if (_keyMap[Keys.Down])
_headPos.Y += displaceAmount;
if (_keyMap[Keys.Right])
_headPos.X += displaceAmount;
if (_keyMap[Keys.Left])
_headPos.X -= displaceAmount;
}
public override void Draw(Graphics gfx)
{
gfx.SmoothingMode = SmoothingMode.AntiAlias;
gfx.DrawString(String.Format("[{0},{1}]", _headPos.X, _headPos.Y), SystemFonts.DefaultFont, Brushes.Black, 0.0f, 48.0f);
gfx.DrawEllipse(Pens.White, _headPos.X, _headPos.Y, 10.0f, 10.0f);
}
}
}