伯乐共勉

讨论。NET专区
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
键盘
目前S60设备控制游戏唯一的方法就是键盘。然而在Symbian操作系统中已经有对触笔的支持,在将来的设备中可能会应用,但是暂时键盘还是控制游戏的实际解决办法。在开发游戏时应该考虑到各种不同的键盘设计和小键盘的限制。最好能够由用户自定义游戏中键的使用。

程序中键事件的处理是简单的:
        AppUI在HandleKeyEventL中接受键事件。
        AppUI通过调用视图的OfferKeyEventL传递键事件来激活视图

如果使用了AddToStackL,键事件自动从AppUI传递给视图加入控制堆栈。键事件不应该在AppUI中处理,除非期望的键事件功能是全局的(就是,和任何特定视图不相干)。

TKeyEvent和TEventCode—OfferKeyEventL传递的参数—包含三个重要值:
        键事件类型
        键的扫描代码
        键的特征代码

每一次按键都按顺序生成了三个事件:
        当键被按下时EEventKeyDown被接收
        键被按下后,EEventKey被接收,在键保持按下状态时,事件被周期性接收(键盘重复率;使用RWsSession::GetKeyboardRepeatRate查出时间间隔)
        放开按键时EEventKeyUp被接收

在实际的游戏中,通常用EEventKeyDown事件控制一个单独的动作(例如,发射一枚导弹)。如果需要持续的动作,像按住键使船只向一个方向移动, 应当设置一个标志用来在收到EEventKeyDown时指示键被按下,并且要在收到EEventKeyUp时重置标志。

如果按键保持很长时间,EEventKey事件会多次传给程序。重复率可以在RWsSession::SetKeyboardRepeatRate中修 改。这个特性是有用的,因为你可以像使用计时器一样多次在特定的时间间隔内重复一个单独的动作,例如,只要键被按下,每0.5秒就发射一枚导弹。

TKeyEvent为每个键包含两个单独的代码—扫描代码和特征代码。扫描代码(TKeyEvent::iScanCode)是游戏中处理键事件的实际选 择,因为它忽略了可能的键盘映射和FEP。TKeyEvent::iCode中的特征代码可能变化(例如,当一个键被按多次时),这依赖于键盘映射和 FEP是如何设置的。当控制游戏的时候,知道哪个物理键被按下比知道特征代码的结果更重要。

默认状态下同时按多个键是不可能的。仅仅率先被按下的键被接收。这叫键阻塞,默认只是开机键和笔形键是非阻塞键。许多游戏需要同时按多个键,两种方法可以实现:
        CAknAppUI提供了SetKeyBlockMode方法在程序中使键阻塞无效。
        键阻塞也是系统方面的设置,但是不建议更改它,因为它也影响其它程序的运行。

下面是关掉键阻塞得例子:
void CMyGameAppUi::ConstructL()
   {
      // Disable key blocking
      SetKeyBlockMode(ENoKeyBlock);
   }
Typically the OfferKeyEventL method in the game's view would look like this:
TKeyResponse CMyGameView::OfferKeyEventL(const TKeyEvent&  
      aKeyEvent,TEventCode aType)
   {
   switch(aType)
      {
      case EEventKey:
         if(aKeyEvent.iScanCode == EStdKeyNkp5 ||
               aKeyEvent.iScanCode == EStdKeyDevice3)
            {
            // EEventKey is called multiple times periodically as
            // long as the key is pressed down, so the ship will be
            // firing periodically too.
            iMyGameEngine->Fire();
            return EKeyWasConsumed;
            }
         break;

      case EEventKeyDown:
         switch(aKeyEvent.iScanCode)
            {
            // Key pressed down; start moving the ship to left or
            // right, and keep it moving as long as the key is
            // pressed.
            case EStdKeyNkp4:
            case EStdKeyLeftArrow:
               iMyGameEngine->SetShipMovingTo( ELeft );
               return EKeyWasConsumed;

            case EStdKeyNkp6:
            case EStdKeyRightArrow:
               iMyGameEngine->SetShipMovingTo( ERight );
               return EKeyWasConsumed;
            }
         break;

      case EEventKeyUp:
         switch(aKeyEvent.iScanCode)
            {
            // Key released; stop moving the ship
            case EStdKeyNkp4:
            case EStdKeyLeftArrow:
            case EStdKeyNkp6:
            case EStdKeyRightArrow:
               iMyGameEngine->SetShipMovingTo( ENowhere );
               return EKeyWasConsumed;
            }
         break;
      }

   return EKeyWasNotConsumed;
}