2012-01-31 9 views
1

こんにちは私は現在、このチュートリアルを使用してWindowsフォームアプリケーションであるプロジェクトにXNAモジュールを埋め込みます: http://create.msdn.com/en-US/education/catalog/sample/winforms_series_1。 これは、簡単な練習のための最高のチュートリアルだと思うので、それに追いつくことにしました。Windowsフォーム環境でのXNA-ControlのGameTimeクラスの置き換え

GameTimeが必要なときに問題が発生し、XNAコントロールの実装でGameTimeが存在しません。私はGoogleですばやい解決策を探して、GameTimeが通常のXNAゲームでどのように実装されているかを説明しようとしましたが、私が見つけた情報が多ければ、私はもっと混乱しました... ここに質問があります:

  • 通常のXNAゲームでは、GameTime.ElapsedGameTimeに「最終更新からの経過時間」と記載されています。 - どういう意味ですか?通過したミリ秒は何ですか?しかし、図面と更新の間に一定の時間間隔があり、それは16ミリ秒ごとに起こるので、それは意味をなさない。私には意味がないようで、ここで少し説明したい。 ElapsedGameTimeはリニア補間でスムージング動作に大きな役割を果たしますが、その最大値が約16msの場合には意味がありません。XNAコントロールに正確なGameTimeの実装はありますか?そうでない場合、WindowsフォームでGameTimeをシミュレートするベストプラクティスは何ですか?

申し訳ありませんが、私の質問は今、それちょっと本当に重要な私には以前に求められていると、既にGoogleの検索に基づいて回答を得ることを試みたが、明確なもの

+0

FYI: 'Game.IsFixedTimeStep'を偽に設定することで、可変期間を持つことができます。 –

答えて

0

GameTime取得に失敗した場合可変時間ステップを使用することを選択した場合は、structがより適切です。デフォルトでは、XNAは一定の時間ステップを実行します(したがって、すべての更新は通常の状況で定期的な間隔で行われます)。

ユーザー入力に基づいてコントロールを更新するだけでなく(ユーザーが何も接触しなくてもゲームが行われるなど)、コントロールを更新する必要があるため、GameTimeが必要です。

単純なアプローチは、単純にあなたの更新/レンダリング関数を呼び出したフォーム上にタイマーコントロールを持つことです。タイマーの間隔を関数に渡します。 XNAで通常GameTimeを受け入れる機能を持つことができます。または、間隔に基づいて自分でGameTimeを作成することができます。

もう1つの方法は、できるだけ早く(おそらくポイントまで)試して更新する別のスレッドを作成することです。これは、更新/レンダリングを行うUIスレッドでコールバックを発生させます。 GameTimeを扱うことは、あなたが最後に走ったときに記録することができ、その時と現在の時差を時間デルタとして渡すという点で、上記と同様です。

1

GameTimeは、最終更新から経過した固定または可変の時間、ゲームの開始以降の合計時間、およびターゲットパフォーマンスに関連するIsRunningSlowlyフラグを提供します。 When WinForms met Game Loop

+0

+1。その記事は、彼の大部分のように、本当に最高の答えです。 –

+0

すべての機能を備えたデフォルトのXna Gameクラスを使用するよりも優れていますか? :P – Blau

+0

私は、OPが何らかの理由でGameクラスを使用できないと仮定しています(それは間違っているかもしれません)。そのため彼自身がゲームループを実装する必要があります。 –

0

GameTime:ここ

はリサイズでゲームタイマーについての素晴らしい記事です。ElapsedGameTimeTimeSpanオブジェクトを返します。TotalMilisecondsプロパティを使用してミリ秒を含む(ただしこれに限定されません)任意の時間単位を取得できます。

TimeSpanが常に同じ理由は、XNAが既定で固定のタイムステップを使用するためです。 Dmitryがコメント内で指摘するようにGame.IsFixedTimeStepプロパティを設定することでこれを変更できます。この質問のタイムステップについては、Fixed time step vs Variable time stepという優れた議論と、それを実装するためのコードがあります。

0

このコードはうまく動作しますが、唯一の違いはゲームクラス内のコンストラクタです。残りはWindows用の通常のxnaゲームのようなものです。

これは私がこのeditor for 2D sprites and skeletal animations

に使用したコードの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 

フォーム

public partial class SkeletonManagerDialog : Form, IXnaFormContainer 
{   
    public Control XnaControl { get { return spriteBoneEditor1.XnaPicture; } } 
    public XnaControlGame Game { get; set; } 
    .... 
} 

XnaGame

です210
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舞台裏

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   
    }  
} 
0

、XNAは約60 FPSに時間ステップを修正するための機能を提供します。 Winformsアプリケーションにその機能を書き込まない限り、その機能は使用できません。しかし、その固定された時間ステップの代わりに、可変の時間ステップで作業するのは良い選択です。

私は、GraphicsDeviveControlから派生したクラスでStopwatchを使用してこの問題に取り組んできました。

次に、Draw()メソッドで変数に経過時間を設定してからリセットします。次に例を示します。

public class XnaControl : GraphicsDeviceControl 
{ 
    Stopwatch timer; 

後に、drawメソッド

protected override void Draw() 
    { 
     float elapsed = (float)timer.Elapsed.TotalSeconds; 
     timer.Restart(); 
     systemBase.UpdateSimulation(elapsed); 
     systemBase.DrawSimulation(elapsed); 
    } 

で、更新&引き分けと一緒に「経過」を送信することにより、あなたは、任意の変数のような補間方法で物事を計算することができますタイムステップゲーム/アプリケーション。

+0

XnaControlのマウスの動きの例を表示できますか? – SpicyWeenie

関連する問題