C# Windows窗体环境中XNA控件的游戏时类替换
您好,我正在尝试使用本教程将XNA模块嵌入到我的项目中,该项目是一个Windows窗体应用程序: . 我想这是最容易练习的教程了,所以我决定继续学习 当我需要游戏时间时,问题就出现了,在XNA控件的实现中,游戏时间并不存在。我试着在谷歌上寻找一个快速的解决方案,并试图找到一个解释游戏时间是如何在一个普通的XNA游戏中实现的,但我发现的信息越多,我就越困惑。。。 以下是问题:C# Windows窗体环境中XNA控件的游戏时类替换,c#,winforms,time,xna,C#,Winforms,Time,Xna,您好,我正在尝试使用本教程将XNA模块嵌入到我的项目中,该项目是一个Windows窗体应用程序: . 我想这是最容易练习的教程了,所以我决定继续学习 当我需要游戏时间时,问题就出现了,在XNA控件的实现中,游戏时间并不存在。我试着在谷歌上寻找一个快速的解决方案,并试图找到一个解释游戏时间是如何在一个普通的XNA游戏中实现的,但我发现的信息越多,我就越困惑。。。 以下是问题: 在常规XNA游戏GameTime.ElapsedGameTime中,描述中显示“自上次更新以来经过的游戏时间。”-这是什
- 在常规XNA游戏GameTime.ElapsedGameTime中,描述中显示“自上次更新以来经过的游戏时间。”-这是什么意思?它是否给出了经过的毫秒数?但这没有任何意义,因为在绘图和更新之间有一个恒定的时间跨度,并且差不多每16毫秒发生一次。。这对我来说似乎毫无意义,我想在这里得到一点解释。我知道ElapsedGameTime在使用线性插值平滑运动方面起着重要作用,但如果其最大值在16ms左右,则没有任何意义
- XNA控件中是否实现了精确的游戏时间?如果不是,那么在Windows窗体中模拟游戏时间的最佳实践是什么
抱歉,如果以前有人问过我的问题,那么现在对我来说非常重要,我已经尝试过基于谷歌搜索得到答案,但是没有得到任何明确的答案如果您选择使用可变时间步长,
GameTime
结构更相关。默认情况下,XNA运行固定的时间步长(因此在正常情况下,所有更新都以固定的间隔进行)
我猜您需要一个GameTime
,因为您希望刷新控件,而不仅仅是基于用户输入(例如,像游戏一样,即使用户不碰任何东西也会发生事情)
在这种情况下,一种简单的方法是在表单上有一个计时器控件,它只调用更新/渲染函数。你可以把计时器的时间间隔传递给你的函数。您可以使用XNA中通常接受GameTime
的函数,只接受double或float等。或者您可以根据时间间隔自己创建GameTime
另一个选择是创建另一个线程,该线程将尝试以尽可能快的速度更新(可能在一定程度上)。这将在UI线程上引发回调,从而执行更新/呈现。处理
GameTime
与上述类似,您可以记录上次运行的时间,并将当时与现在的差值作为时间增量传递。GameTime
提供自上次更新以来经过的固定或可变时间,游戏开始后的总时间,以及与目标性能相关的isrunningslowy
标志
这是一篇关于WinForms中游戏计时器的好文章:。为您提供一个对象,您可以在其中检索任意时间单位,包括(但不限于)通过属性的毫秒数
TimeSpan总是相同的原因是XNA默认使用固定的时间步长。您可以通过设置Dmitry在注释中指出的属性来更改此设置。在这个问题中,有一个关于时间步的极好的讨论,以及一些实现它们的代码。这段代码工作得很好,唯一的区别是game类中的构造函数,其余的类似于windows的普通xna游戏 这是我用于此的代码 Program.cs
namespace SpriteEditor
{
#if WINDOWS
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles( );
Application.SetCompatibleTextRenderingDefault( false );
XnaControlGame.CreateAndShow<SkeletonManagerDialog, SkeletonXnaGame>( );
}
}
#endif
using System;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace SpriteEditor
{
public interface IXnaFormContainer
{
Control XnaControl { get; }
XnaControlGame Game { get; set; }
}
public abstract class XnaControlGame : Microsoft.Xna.Framework.Game
{
public Control Parent { get; private set; }
public static void CreateAndShow<T, Q>( )
where T : Form, IXnaFormContainer, new( )
where Q : XnaControlGame
{
using ( T form = new T( ) )
{
form.Show( );
using ( Q game = ( Q ) Activator.CreateInstance( typeof( Q ), new object[] { form.XnaControl.Handle, form, form.XnaControl } ) )
{
form.Game = game;
game.Parent = form.XnaControl;
game.Run( );
}
}
}
#region Private Vars to Build Embedded Xna Control
IntPtr _XnaDrawingSurface;
GraphicsDeviceManager graphics;
System.Windows.Forms.Form parentForm;
System.Windows.Forms.Control controlXna;
System.Windows.Forms.Control gameForm;
#endregion
#region Constructor
public XnaControlGame( IntPtr handle,
System.Windows.Forms.Form parentForm,
System.Windows.Forms.Control surfaceControl )
{
graphics = new GraphicsDeviceManager( this );
graphics.GraphicsProfile = GraphicsProfile.Reach;
Content.RootDirectory = "Content";
this.parentForm = parentForm;
this.controlXna = surfaceControl;
gameForm = System.Windows.Forms.Control.FromHandle( this.Window.Handle );
gameForm.VisibleChanged += new EventHandler( gameForm_VisibleChanged );
controlXna.SizeChanged += new EventHandler( pictureBox_SizeChanged );
// preparing device settings handler.
_XnaDrawingSurface = handle;
Mouse.WindowHandle = handle;
graphics.PreparingDeviceSettings += OnPreparingDeviceSettings;
graphics.PreferredBackBufferWidth = (controlXna.Width > 0) ? controlXna.Width : 50;
graphics.PreferredBackBufferHeight = (controlXna.Height > 0) ? controlXna.Height : 50;
parentForm.FormClosed += delegate( object sender, System.Windows.Forms.FormClosedEventArgs e )
{
this.Exit( );
Application.Exit( );
};
}
#endregion
#region Events
private void OnPreparingDeviceSettings( object sender, PreparingDeviceSettingsEventArgs e )
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = _XnaDrawingSurface;
}
private void gameForm_VisibleChanged( object sender, EventArgs e )
{
if ( gameForm.Visible == true )
gameForm.Visible = false;
}
void pictureBox_SizeChanged( object sender, EventArgs e )
{
if ( parentForm.WindowState !=
System.Windows.Forms.FormWindowState.Minimized )
{
graphics.PreferredBackBufferWidth = controlXna.Width;
graphics.PreferredBackBufferHeight = controlXna.Height;
graphics.ApplyChanges( );
OnSizeChanged( );
}
}
protected virtual void OnSizeChanged( ) { }
#endregion
}
}
XnaGame
public partial class SkeletonXnaGame : XnaControlGame
{
public SkeletonXnaGame( IntPtr ptr, Form form, Control control )
: base( ptr, form, control ) { }
//--------------------------------------------------------------------------
protected override void Update( GameTime gameTime )
{
float Seconds = ( float ) gameTime.ElapsedGameTime.TotalSeconds;
HandleMouse( );
if ( TryHandleCamera( ) ) return;
if ( MouseIsInsideViewport) HandleLeftClick( Seconds );
if ( SkeletonManager.SelectedBone != null ) UpdateSelectedBone( Seconds );
if ( SkeletonManager.SelectedShape != null ) UpdateSelectedShape( Seconds );
if ( SkeletonManager.CurrentSequence != null ) SkeletonManager.CurrentSequence.Update( Seconds );
base.Update( gameTime );
}
....
}
XnaControlGame.cs
namespace SpriteEditor
{
#if WINDOWS
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles( );
Application.SetCompatibleTextRenderingDefault( false );
XnaControlGame.CreateAndShow<SkeletonManagerDialog, SkeletonXnaGame>( );
}
}
#endif
using System;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace SpriteEditor
{
public interface IXnaFormContainer
{
Control XnaControl { get; }
XnaControlGame Game { get; set; }
}
public abstract class XnaControlGame : Microsoft.Xna.Framework.Game
{
public Control Parent { get; private set; }
public static void CreateAndShow<T, Q>( )
where T : Form, IXnaFormContainer, new( )
where Q : XnaControlGame
{
using ( T form = new T( ) )
{
form.Show( );
using ( Q game = ( Q ) Activator.CreateInstance( typeof( Q ), new object[] { form.XnaControl.Handle, form, form.XnaControl } ) )
{
form.Game = game;
game.Parent = form.XnaControl;
game.Run( );
}
}
}
#region Private Vars to Build Embedded Xna Control
IntPtr _XnaDrawingSurface;
GraphicsDeviceManager graphics;
System.Windows.Forms.Form parentForm;
System.Windows.Forms.Control controlXna;
System.Windows.Forms.Control gameForm;
#endregion
#region Constructor
public XnaControlGame( IntPtr handle,
System.Windows.Forms.Form parentForm,
System.Windows.Forms.Control surfaceControl )
{
graphics = new GraphicsDeviceManager( this );
graphics.GraphicsProfile = GraphicsProfile.Reach;
Content.RootDirectory = "Content";
this.parentForm = parentForm;
this.controlXna = surfaceControl;
gameForm = System.Windows.Forms.Control.FromHandle( this.Window.Handle );
gameForm.VisibleChanged += new EventHandler( gameForm_VisibleChanged );
controlXna.SizeChanged += new EventHandler( pictureBox_SizeChanged );
// preparing device settings handler.
_XnaDrawingSurface = handle;
Mouse.WindowHandle = handle;
graphics.PreparingDeviceSettings += OnPreparingDeviceSettings;
graphics.PreferredBackBufferWidth = (controlXna.Width > 0) ? controlXna.Width : 50;
graphics.PreferredBackBufferHeight = (controlXna.Height > 0) ? controlXna.Height : 50;
parentForm.FormClosed += delegate( object sender, System.Windows.Forms.FormClosedEventArgs e )
{
this.Exit( );
Application.Exit( );
};
}
#endregion
#region Events
private void OnPreparingDeviceSettings( object sender, PreparingDeviceSettingsEventArgs e )
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = _XnaDrawingSurface;
}
private void gameForm_VisibleChanged( object sender, EventArgs e )
{
if ( gameForm.Visible == true )
gameForm.Visible = false;
}
void pictureBox_SizeChanged( object sender, EventArgs e )
{
if ( parentForm.WindowState !=
System.Windows.Forms.FormWindowState.Minimized )
{
graphics.PreferredBackBufferWidth = controlXna.Width;
graphics.PreferredBackBufferHeight = controlXna.Height;
graphics.ApplyChanges( );
OnSizeChanged( );
}
}
protected virtual void OnSizeChanged( ) { }
#endregion
}
}
使用系统;
使用System.Windows.Forms;
使用Microsoft.Xna.Framework;
使用Microsoft.Xna.Framework.Graphics;
使用Microsoft.Xna.Framework.Input;
命名空间SpriteEditor
{
公共接口IXnaFormContainer
{
控件XnaControl{get;}
XnaControlGame游戏{get;set;}
}
公共抽象类XnaControlGame:Microsoft.Xna.Framework.Game
{
公共控件父项{get;private set;}
公共静态void CreateAndShow()
其中T:Form,IXnaFormContainer,new()
Q:XnaControlGame在哪里
{
使用(T form=newt())
{
form.Show();
使用(Q game=(Q)Activator.CreateInstance(typeof(Q),新对象[]{form.XnaControl.Handle,form,form.XnaControl}))
{
形式。游戏=游戏;
game.Parent=form.XnaControl;
game.Run();
}
}
}
#用于构建嵌入式Xna控件的区域专用变量
INTPTRu XnaDrawingSurface;
图形管理器图形;
System.Windows.Forms.Form父窗体;
System.Windows.Forms.controlcontrolxna;
System.Windows.Forms.Control游戏窗体;
#端区
#区域构造函数
公共XnaControlGame(IntPtr手柄,
System.Windows.Forms.Form父窗体,
System.Windows.Forms.Control surfaceControl)
{
graphics=新的GraphicsDeviceManager(此);
graphics.GraphicsProfile=GraphicsProfile.Reach;
Content.RootDirectory=“Content”;
this.parentForm=parentForm;
this.controlXna=表面控制;
gameForm=System.Windows.Forms.Control.FromHandle(this.Window.Handle);
gameForm.VisibleChanged+=新事件处理程序(gameForm\u VisibleChanged);
controlXna.SizeChanged+=新事件处理程序(pictureBox_SizeChanged);
//正在准备设备设置处理程序。
_XnaDrawingSurface=手柄;
Mouse.WindowHandle=句柄;
graphics.PreparingDeviceSettings+=OnPreparingDeviceSetting
protected override void Draw()
{
float elapsed = (float)timer.Elapsed.TotalSeconds;
timer.Restart();
systemBase.UpdateSimulation(elapsed);
systemBase.DrawSimulation(elapsed);
}