(xbox情報を追加)
Windowsの場合、基本的にフォームを作成して表示し、そのハンドルとフォーム自体を保存する必要があります。このハンドルを使用して、GraphicsDeviceを作成できます。次に、Application.Idleを、更新とレンダリングを呼び出す独自の関数にフックします。例えば
public class MyGame
{
public Form form;
public GraphicsDevice GraphicsDevice;
public MyGame()
{
form = new Form();
form.ClientSize = new Size(1280, 1024);
form.MainMenuStrip = null;
form.Show();
}
public void Run()
{
PresentationParameters pp = new PresentationParameters();
pp.DeviceWindowHandle = form.Handle;
pp.BackBufferFormat = SurfaceFormat.Color;
pp.BackBufferWidth = 1280;
pp.BackBufferHeight = 1024;
pp.RenderTargetUsage = RenderTargetUsage.DiscardContents;
pp.IsFullScreen = false;
pp.MultiSampleCount = 16;
pp.DepthStencilFormat = DepthFormat.Depth24Stencil8;
GraphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
GraphicsProfile.HiDef,
pp);
Application.Idle += new EventHandler(Application_Idle);
Application.Run(form);
}
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Message message;
while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
/* Your logic goes here
Custom timing and so on
Update();
Render();
*/
}
}
void Render()
{
GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.Black, 1, 0);
//Your logic here.
GraphicsDevice.Present();
}
[StructLayout(LayoutKind.Sequential)]
private struct Message
{
public IntPtr hWnd;
public int msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public Point p;
}
[return: MarshalAs(UnmanagedType.Bool)]
[SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint
messageFilterMin, uint messageFilterMax, uint flags);
}
編集1
xboxの場合、ゲームループを使用して独自のカスタム実行関数をスロットルされた真のループに配置できる場合があります。真の間に実行される内部では、おそらくIntPtr.Zeroをハンドルとしてグラフィックスデバイスの初期化と検証を行う必要があります。
編集2
私はこのようなものを使用します(http://www.koonsolo.com/news/dewitters-gameloop/から取得)
private long nextGameTick;
private Stopwatch stopwatch;
const int ticksPerSecond = 60;
const int skipTicks = 1000 / ticksPerSecond;
private const int maxSkip = 10;
`constructor
stopwatch = Stopwatch.StartNew();
nextGameTick = stopwatch.ElapsedMilliseconds;
`loop
int loops = 0;
long currentTick = stopwatch.ElapsedMilliseconds;
while ( (ulong)(currentTick - nextGameTick) > skipTicks && loops < maxSkip)
{
Update(16.667f);
nextGameTick += skipTicks;
loops++;
}
PreRender();
Render();
PostRender();
編集3
コンテンツマネージャーの作成はもう少し手間がかかりましたが、それでも管理可能でした。IServiceProviderを実装するクラスを作成する必要があります。このクラスは、IGraphicsDeviceProviderを実装する次のクラスを作成するために、コンストラクターでGraphicsDeviceを取ります。さらに、私はこのようにGetServiceを実装します
//in implementer of IServiceProvider
public object GetService ( Type serviceType )
{
if ( serviceType == typeof ( IGraphicsDeviceService ) )
{
return myGraphicsService;
}
return null;
}
便宜上、クラスにメソッドを追加して、マネージャーを作成して返すこともできます
//in implementer of IServiceProvider
public ContentManager CreateContentManager( string sPath )
{
ContentManager content = new ContentManager(this);
content.RootDirectory = sPath;
return content;
}
さらに、IGraphicsDeviceServiceを実装し、GraphicsDeviceへの参照を取得するクラスを作成します。次に、その中にプロパティとフィールドを作成します。
//in implementer of IGraphicsDeviceService
private GraphicsDevice graphicsDevice;
public GraphicsDevice GraphicsDevice
{
get
{
return graphicsDevice;
}
}
だから、呼び出しは何かのようになってしまいます
MyServiceProvider m = new MyServiceProvider(graphicsDevice);
ContentManager content = m.CreateContentManager("Content");
どこ
MyServiceProvider(GraphicsDevice graphicsDevice)
{
myGraphicsService = new MyGraphicsDeviceService(graphicsDevice);
}
MyGraphicsDeviceService(GraphicsDevice gfxDevice)
{
graphicsDevice = gfxDevice;
}
-コードを断片化して申し訳ありませんが、最近書いたものではないので、パーツを覚えるのに苦労しています。
編集4
カスタムゲームで奇妙なケースがありました。フォームを新しくしたときに、バインドする必要があったことを思い出しました。
private void IgnoreAlt(object pSender, KeyEventArgs pEventArgs)
{
if (pEventArgs.Alt && pEventArgs.KeyCode != Keys.F4)
pEventArgs.Handled = true;
}
に
form.KeyUp += IgnoreAlt;
form.KeyDown += IgnoreAlt;
そうでなければ私はいくつかの恐ろしい屋台を手に入れました。