XNA游戏:重力感应
Windows Phone XNA游戏提供的重力传感器可以利用量测重力的原理判手机移动的方向,允许使用者利用摇动或甩动手机的方式控制游戏的执行,其原理和汽车的安全气囊相同,在侦测到汽车快速减速的时候立刻充气以保护驾驶人与乘客不会受伤。要使用重力传感器当做游戏程序的输入,以 XNA 为基础的游戏程序可以利用 Accelerometer 类别提供的功能启用/停用重力加速器,取得重力加速器的状态,以及处理重力加速器引发的事件。
Accelerometer 类别常用的属性
属性名称 |
说明 |
State |
管理重力加速器状态的属性,其型态为 SensorState 列举型态。有关 SensorState 列举型态合法的内容值可以参考表4 的说明。 |
Accelerometer 类别常用的方法
方法名称 |
说明 |
Start |
开始从重力加速器读取数据。 |
Stop |
结束从重力加速器读取数据。 |
Accelerometer 类别常用的事件
事件名称 |
说明 |
ReadingChanged |
当重力加速器读取到数据时会引发的事件。 |
处理 ReadingChanged 事件的事件处理程序的第二个参数的型态为 AccelerometerReadingEventArgs 类别,其 X、Y、与 X 属性的内容值代表智能型手机在 X 轴、Y 轴、和 Z 轴的加速方向,而不是三度空间的坐标,其单位为重力单位,也就是 G 力 (1G = 9.81 m/s2)。除了 X、Y、与 Z 三个属性以外,还有一个名称为 Timestamp 的属性,负责记录重力加速器读取数据的时间点。
请注意当手机放在平坦的桌面上,而且正面朝上的时候,AccelerometerReadingEventArgs 类别的 Z 字段的内容值会是 -1.0,表示 Z 轴承受 -1G 的重力,而当手机放在平坦的桌面上,而且正面朝下的时候,AccelerometerReadingEventArgs 类别的 Z 字段的内容值就会是 +1.0,表示 Z 轴承受 1G 的重力。
[说明]
透过 Accelerometer 类别的 State 属性取得的重力加速器状态是 SensorState 列举型态的数据,其合法的内容值请参考表 的说明:
内容值名称 |
说明 |
NotSupported |
未支持重力加速器。 |
Ready |
重力加速器处于可以处理数据的状态。 |
Initializing |
重力加速器正在初始化。 |
NoData |
未支持重力加速器。 |
NoPermissions |
呼叫者没有权限取用重力加速器接收到的数据。 |
Disabled |
重力加速器处于禁用的状态。 |
要使用重力加速器判断智能型手机加速的方向,首先您必须使用鼠标的右键点中 [Solution Explorer] 窗口中的项目名称,从出现的菜单选择 [Add Reference] 功能,然后于出现的窗口中选择名称为 Microsoft.Devices.Sensors 的组件,添加引用上去。
下面看一个例子:
using System; using System.Windows; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Media; using Microsoft.Devices.Sensors; namespace AccelerometerSample { /// <summary> /// This is the main type for your game /// </summary> public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; SpriteFont readingsFont;//字体资源 Accelerometer accelerometer;//重力加速器 double X; double Y; double Z; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; // Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); } /// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here //初始化重力加速器 accelerometer = new Accelerometer(); //读取重力改变事件 accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(AccelerometerReadingChanged); //开始其中重力加速器 accelerometer.Start(); base.Initialize(); } /// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here //加载字体资源 readingsFont = Content.Load<SpriteFont>("readings"); } /// <summary> /// UnloadContent will be called once per game and is the place to unload /// all content. /// </summary> protected override void UnloadContent() { // TODO: Unload any non ContentManager content here accelerometer.Stop(); } /// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here base.Update(gameTime); } /// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); //绘制文字 spriteBatch.DrawString(readingsFont, "X: " + X.ToString("0.00"), new Vector2(50, 50), Color.White); spriteBatch.DrawString(readingsFont, "Y: " + Y.ToString("0.00"), new Vector2(50, 75), Color.White); spriteBatch.DrawString(readingsFont, "Z: " + Z.ToString("0.00"), new Vector2(50, 100), Color.White); spriteBatch.End(); base.Draw(gameTime); } void AccelerometerReadingChanged(object sender, AccelerometerReadingEventArgs e) { //触发UI更新 Deployment.Current.Dispatcher.BeginInvoke(() => NewReading(e)); } //赋值XYZ的值 void NewReading(AccelerometerReadingEventArgs e) { X = e.X; Y = e.Y; Z = e.Z; } } }