×
Namespaces

Variants
Actions

Windows Phone 7 摇动检测

From Nokia Developer Wiki
Jump to: navigation, search
WP Metro Icon UI.png
SignpostIcon XAML 40.png
SignpostIcon WP7 70px.png
Article Metadata

代码示例
测试基于
SDK: Windows Phone 7.1 SDK

兼容于
文章
WS - OtomiiLu 在 09 Aug 2012 创建
最后由 hamishwillee 在 19 Jul 2013 编辑

在日常的手机使用的过程中,我们经常会进行人机交互,摇动手机也是其中一种。 本文将演示如何在Windows Phone 7程序中获取手机摇动的数据,主要演示左右摇动和上下摇动的获取.

Contents

摇动支持

首先我设置了摇动的Enum:

public enum ActionEnum
{
None = 0,
LeftRightShake = 1,
UpDownShake = 2
}

然后,我就可以使用以下代码来设置支持的Action

accHelper.SupportedAction = ActionEnum.LeftRightShake | ActionEnum.UpDownShake;

然后,我可以使用以下来匹配,是否支持这个Action,这里是是否匹配LeftRightShake

(SupportedAction & ActionEnum.LeftRightShake).Equals(ActionEnum.LeftRightShake)

这样做的原理是二进制匹配: None = 0000,

LeftRightShake = 0001,

UpDownShake = 0010

ActionEnum.LeftRightShake | ActionEnum.UpDownShake = 0011

当需要判断的时候,如下:

SupportedAction & ActionEnum.LeftRightShake = 0001,去掉了属于UpDownShake的那个1


所以最终,只需要

(SupportedAction & ActionEnum.LeftRightShake).Equals(ActionEnum.LeftRightShake)

来匹配即可.

Windows Phone 7重力系统概要

重力是由于加速度产生的,加速度值采用 3 维矢量表示,该矢量表示在 X、Y 和 Z 轴中的加速度分量(采用重力单位)。 当设备面朝平台时,加速度的方向相对于设备以便对 Z 轴应用 -1g,当垂直于平台顶部放置设备时,对 Y 轴应用 -1g。 加速度计传感器将检测重力以及由于手机运动而产生的任何力。

重力坐标类Axis

重力坐标类提供了一个重力最基本的X,Y,Z方向,同时还提供了记录坐标的时间和记录坐标时,手机的移动方向.

    public class Axis
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public DateTime CurrentDateTime { get; set; }
public AccelerationDirection AccDirection { get; set; }
}

以下是坐标的方向的Enum,因为我们就监控两种摇动,所以仅提供了4个方向.

public enum ActionEnum
{
None = 0,
LeftRightShake = 1,
UpDownShake = 2
}

重力坐标集合类AxisCollection

AxisCollection是最主要的一个类,提供了很多的方法,为了重力判断的使用.

在AxisCollection中的Add方法并没有这么容易添加,这个需要是判断为有一定幅度的震动的时候,猜可以判断为新的行为:

        public void Add(Axis axis)
{
var Gravity = axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z;
if (Gravity < 0.8 || Gravity > 1.2)
{
AxisList.Add(axis);
if (-0.3 > axis.X || axis.X > 0.3)
{
if (axis.X < -0.3) axis.AccDirection = AccelerationDirection.Left;
else if (axis.X > 0.3) axis.AccDirection = AccelerationDirection.Right;
}
else
{
if ((axis.Y * axis.Y + axis.Z * axis.Z > 1.2)) axis.AccDirection = AccelerationDirection.Up;
else if (axis.Y * axis.Y + axis.Z * axis.Z < 0.8) axis.AccDirection = AccelerationDirection.Down;
}
axis.CurrentDateTime = DateTime.Now;
}
}

这些个数字中的0.3,1.2,0.8都是对用户震动的检测.

然后是IsMoving方法,这个方法是用来判断手机时候在Action.如果为True,那么就是在移动.如果为False,那么就是有一定时间没有进行移动了.

        public bool IsMoving()
{
if (AxisList.Count != 0)
{
if (DateTime.Now.Subtract(AxisList.Last().CurrentDateTime).TotalMilliseconds > 666)
{
return false;
}
}
return true;
}

最后就是最最重要的CheckCurrentAction方法了.通过Check方法,可以Check当前的操作是左右晃动,还是上下晃动,我们这里设置的是2,我们也可以改变这个数值,使得需要更加多的晃动,才判断为一次行为.

        public void CheckCurrentAction()
{
if (AxisList.Count == 0) CurrentActionEnum = ActionEnum.None;
else
{
if (!(CurrentActionEnum .Equals( ActionEnum.None)))
{
return;
}
if ((SupportedAction & ActionEnum.LeftRightShake).Equals(ActionEnum.LeftRightShake) &&
AxisList.Where(al => al.AccDirection.Equals(AccelerationDirection.Left)).Count() > 2 && AxisList.Where(al => al.AccDirection.Equals(AccelerationDirection.Right)).Count() > 2)
CurrentActionEnum = ActionEnum.LeftRightShake;
else if ((SupportedAction & ActionEnum.UpDownShake).Equals(ActionEnum.UpDownShake) &&
AxisList.Where(al => al.AccDirection.Equals(AccelerationDirection.Up)).Count() > 2 && AxisList.Where(al => al.AccDirection.Equals(AccelerationDirection.Down)).Count() > 2)
CurrentActionEnum = ActionEnum.UpDownShake;
}
}

最后,是Reset方法,重置所有的Child,当进过一段时间不移动后,那么就需要进行Reset.

        public bool Reset()
{
try
{
AxisList.Clear();
}
catch (Exception)
{
return false;
}
return true;
}

帮助类AccHelper

AccHelper类的主要功能就是帮助我们进行中心控制,封装一些我们不需要处理的操作. 下面,就是整个WPAcchelper类

namespace AccHelper
{
public class WPAccHelper
{
private Accelerometer accelerometer = new Accelerometer();
private AxisCollection axisCollection = new AxisCollection();
public ActionEnum SupportedAction
{
get { return axisCollection.SupportedAction; }
set { axisCollection.SupportedAction = value; }
}
public WPAccHelper()
{
accelerometer.Start();
accelerometer.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged);
}
 
void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
{
var newAxis = new Axis() { X = e.SensorReading.Acceleration.X, Y = e.SensorReading.Acceleration.Y, Z = e.SensorReading.Acceleration.Z };
axisCollection.Add(newAxis);
if (!axisCollection.IsMoving())
{
axisCollection.Reset();
return;
}
axisCollection.CheckCurrentAction();
}
 
public string GetInfo()
{
return axisCollection.CurrentActionEnum.ToString();
}
}
}

通过这个类,我们可以不用手动调用AxisCollection中的方法,而全部交给Helper类,所有的Reset和Check都不用我们手动来.

GamePage页面

接着我们看下我们需要在主页面中做什么:

  • 声明一个WPAcchelper类,并设定支持的晃动类型是什么
WPAccHelper accHelper;
accHelper = new WPAccHelper();
accHelper.SupportedAction = ActionEnum.LeftRightShake | ActionEnum.UpDownShake;

然后,直接在OnDraw方法中写出当前的晃动是什么,即可.不需要更多的操作.

        private void OnDraw(object sender, GameTimerEventArgs e)
{
SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.DrawString(MySprite, accHelper.GetInfo(), new Vector2(0, 0), Color.White);
spriteBatch.End();
// TODO: Add your drawing code here
}

项目截图

ShakeDetect.JPG

项目文件和总结

File:AccelerometerHelper.zip

本项目指在提供一种思想,如何通过重力,检测当前的行为,重力的检测,在游戏中经常的用到,是非常重要的一部分.
This page was last modified on 19 July 2013, at 04:15.
89 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×