打造轻量级Windows Phone7 游戏引擎-Samurai 第二话(中) Inputs 问题解决篇一
1.如何让原本的“轮询”模式变成“事件响应”模式?
(当然了,这里的事件响应模式本质上还是轮询,并没有提高效率,仅仅是方便了编程,希望读者注意)
简要概括做法就是:
事先以“手势种类”为Key以及“响应方法”为Value进行注册,在游戏过程中,SAInput在更新后,根据监听到的手势决定是否调用相应方法。
我们先定义一个委托:
public delegate void OnInputDelegate(GestureSample gestureSample); //处理手势的委托定义
然后定义一个字典,用来存储手势和响应方法的映射关系:(对inputDictionary的管理就是最为重要的部分了~)
private static Dictionary<GestureType, OnInputDelegate> inputDictionary = new Dictionary<GestureType, OnInputDelegate>(); //手势与委托的字典
public static void EnableGesture(GestureType gestureType, OnInputDelegate onInput)
{
if (!inputDictionary.ContainsKey(gestureType))
{
TouchPanel.EnabledGestures = TouchPanel.EnabledGestures | gestureType;
inputDictionary.Add(gestureType, onInput);
}
}
(注意的是,同一个手势不要注册多个响应(当然,其实大家可以在这个基础上改进使之可以同一手势支持多个相应,想想用什么方法吧~))然后就是真正处理部分的代码了,在贴下来该段代码之前还是不得不吐个槽:这也太简单太水了吧...
foreach (GestureType g in inputDictionary.Keys)
{
if (gestureSample.GestureType == g)
{
inputDictionary[g].Invoke(gestureSample);
break; //ATTENTION
}
}
就是这个样子的,只要检测到有相应的手势,直接触发相应的响应方法即可~
同理,我们可以对BackButton进行同样的处理:
设置委托:
public delegate void OnBackButtonDelegate(); //处理back键的委托定义
注册响应事件:
public static void EnableBackButton(OnBackButtonDelegate onBackButton)
{
//OnBackButton += onBackButton;
OnBackButton = onBackButton;
}
(同样的,这里也是只支持一个响应方法,不过如果使用注释掉的那个语句就可以注册多个方法了~不好意思哈,直接说出来了~不过因为注册了多个响应方法并不是必要的,而且这样做的话,会让代码比较凌乱,所以还是不要用注释掉的那一行了)
处理响应:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
if (OnBackButton != null)
{
OnBackButton.Invoke();
}
}
2.如何既能用Gesture,又能用底层的TouchCollection?
虽然在书上见到了提醒不要既用TouchCollection又用Gesture,但是经过尝试似乎没有问题,大家如果用的时候遇见了问题,一定要告我一声。 在这里多说一句,XNA的Gesture本来就是加工 TouchCollection中的信息得到的。也就是说如果我们自己心情好的话,可以直接无视掉Gesture,自己利用TouchCollection实现自定义的Gesture,不过比较惭愧,笔者有些懒惰啊~
代码如下:
设置委托:
public delegate void OnTouchCollectionDelegate(TouchCollection touchCollection);
注册响应事件:
public static void EnableTouchCollection(OnTouchCollectionDelegate temp)
{
OnTouchCollection = temp;
}
处理响应:(好吧,这已经简单到无力吐槽了)注意,我将TouchCollection的处理放在了Gesture的前面,这个时候是没问题的,欢迎大家尝试将Gesture放在前面的情况~
if (OnTouchCollection != null)
{
OnTouchCollection.Invoke(touchCollection);
}
在介绍完页面管理系统后再进行详述。
另外,这篇博客中的代码仅仅是用于讲解的一部分,要达到实际应用以及可以和其他部分进行整合的程度,还需要做一些其他控制开关啦,注销啦等等之类的工作。所以,在晚些时候SAInput这部分写完的时候我会附上较为完整的代码。