开发游戏引擎(19)

 

2. 调整窗体尺寸

在第2章中曾经讨论过,如果改变了设备的方向,窗体的尺寸就会发生改变。这种情况可能发生在用户将应用程序最小化,对设备进行重新配置或者只是旋转了有重力感应功能的新设备时。

当窗体大小发生改变时,需要调整游戏以适应新的尺寸。这可能需要我们对游戏中的图形进行重新定位(甚至要加载全新的图形)或者显示一条消息说明该游戏在新的屏幕方向上不能正常工作。

然而我们需要做出响应,使游戏引擎拦截到该事件,并执行所需的操作。正如Activated 事件一样,我们要在CGameEngineGDIBase类的构造函数中为窗体添加Resize事件处理程序。这次调用GameFormResize函数,该函数如程序清单4-21所示。

程序清单4-21  对游戏窗体大小发生改变进行响应

/// <summary>

/// Respond to the game form resize event

/// </summary>

private void GameFormResize(object sender, EventArgs e)

{

// If we have no back buffer or its size differs from

// that of the game form, we need to re-prepare the game.

if (_backBuffer == null ||

GameForm.ClientSize.Width != _backBuffer.Width ||

GameForm.ClientSize.Height != _backBuffer.Height)

{

// Re-prepare the game.

Prepare();

// Force the whole form to repaint

ForceRepaint();

}

}

该函数的主要目的是再次调用Prepare方法(游戏引擎就是在这里完成对Resize事件的响应的),并强制执行一次重绘,这样在新尺寸的窗体中对全部对象进行渲染。

但是,Resize事件会经常不定期地被触发(例如,当窗体被打开时)。为了忽略这些虚假的调用,我们将窗体的尺寸同后台缓冲区中的窗体大小进行对比。如果两者匹配,就忽略该调用。只有在检测到确实发生了尺寸变化时,才调用Prepare方法和ForceRepaint方法。

3. 处理SIP

在触摸屏设备上,SIP随时都可能会打开和关闭。当SIP关闭时,它占用的区域如果不包含在移动区域中,就会保持原样而不进行绘制,这将看上去很不协调,而使用户感到很不适应。因此,我们需要捕获SIP的关闭事件,当它发生时就强制执行重绘。

对该事件的响应方式与前面其他的窗体事件是完全相同的,只是如果尝试在一个smart phone设备上与InputPanel控件进行交互的话,就会抛出一个异常,这使情况稍微复杂了一些。因此,在添加事件处理程序之前要检测游戏是否运行在smart phone平台上(如果是,那么设备上不会包含SIP,也不需要对其事件进行处理)。

为了实现该功能,要在类中添加一个名为_inputPanel的InputPanel类变量,在CgameEngine-

GDIBase类的构造函数中使用程序清单4-22中的代码对它进行初始化。

程序清单4-22  初始化SIP事件处理程序

// If we are running on a touch-screen device, instantiate the inputpanel

if (!IsSmartphone)

{

_inputPanel = new Microsoft.WindowsCE.Forms.InputPanel();

// Add the event handler

_inputPanel.EnabledChanged += new System.EventHandler(SIPEnabledChanged);

}

读书导航