×
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.
122 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.

×