Windows Phone’i on sisse ehitatud kolmesuunaline kiirendusandur. Alljärgnevas rakenduses kasutatakse punase palli liigutamiseks kahte dimensiooni, kuid värvilised jooned ekraanil iseloomustavad telefoni liikumist kolmes erinevas suunas.
MSDN artikkel: http://msdn.microsoft.com/en-us/library/ff431810(v=vs.92).aspx
Antud kood on internetinäidete põhjal kokku pandud kahest erinevast rakendusest – kolmemõõtmeliste joonte kuvamine ning palli edasi-tagasi sõitmine mööda ekraani.
How accelerometer is working–check it out!
MainPage.xaml
<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="AccelerometerTest.MainPage"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid Name="MyGrid" Width="411" Height="768">
<Line x:Name="xLine" X1="200" Y1="400" X2="260" Y2="400" Stroke="Red" StrokeThickness="4" Margin="0"/>
<Line x:Name="yLine" X1="200" Y1="400" X2="200" Y2="340" Stroke="Green" StrokeThickness="4" Margin="0"/>
<Line x:Name="zLine" X1="200" Y1="400" X2="260" Y2="340" Stroke="Blue" StrokeThickness="4" Margin="0"/>
<Rectangle x:Name="Track" Height="80" Stroke="#FFC0C0C0"
RadiusX="40" RadiusY="40" Margin="0" Width="410" />
<Ellipse x:Name="Ball" Width="80" Height="80" Margin="0">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.234,0.255">
<GradientStop Color="White"/>
<GradientStop Color="Red" Offset="0.759"/>
</RadialGradientBrush>
</Ellipse.Fill>
<Ellipse.RenderTransform>
<TranslateTransform x:Name="BallTransform" />
</Ellipse.RenderTransform>
</Ellipse>
<TextBlock Height="50" HorizontalAlignment="Left" Margin="0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Width="200" />
<TextBlock Height="50" HorizontalAlignment="Left" Margin="0,50,0,0" Name="textBlock2" Text="TextBlock" VerticalAlignment="Top" Width="200" />
<TextBlock Height="50" HorizontalAlignment="Left" Margin="0,100,0,0" Name="textBlock3" Text="TextBlock" VerticalAlignment="Top" Width="200" />
</Grid>
</phone:PhoneApplicationPage>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;
using Microsoft.Phone.Shell;
namespace AccelerometerTest
{
public partial class MainPage : PhoneApplicationPage
{
private const int sum = 25;
private const double gravity = 32.2; // raskusjõud (ft/sec2)
private const double damping = 0.5; // põrketugevus
private const double mul = 128.0; // palli liikumise tundlikkus
private double _sx = 0.0;
private double _sy = 0.0;
private double _vx = 0.0;
private double _vy = 0.0;
private double _ax = 0.0;
private double _ay = 0.0;
private double _time = DateTime.Now.Ticks;
private double width, height;
private double time;
private Accelerometer _accel = new Accelerometer();
Vector3 acceleration;
public MainPage()
{
InitializeComponent();
//järgmised kaks rida on selle jaoks, et telefonile ei tuleks "lukku" peale
PhoneApplicationService phoneAppService = PhoneApplicationService.Current;
phoneAppService.UserIdleDetectionMode = IdleDetectionMode.Disabled;
width = (Application.Current.Host.Content.ActualWidth - Ball.Width) / 2.0;
height = (MyGrid.Height - Ball.Height) / 2.0;
// Start acceleroemeter
_accel.CurrentValueChanged +=
new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(OnReadingChanged);
_accel.Start();
}
private void OnReadingChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
{
time = e.SensorReading.Timestamp.Ticks;
acceleration = e.SensorReading.Acceleration;
Dispatcher.BeginInvoke(() => UpdateDisplay());
// käivita UI thread
}
private double calculate(double[] k) {
double ysum = 0;
for (int i = 0; i < sum; i++)
ysum += k[i];
return ysum;
}
private void UpdateDisplay()
{
//saadakse kätte kiirendused kolmes suunas
double x = acceleration.X;
double y = acceleration.Y;
double z = acceleration.Z;
//time on suurusjärgus 0,02 ja = (praegune aeg - eelmine aeg) / 10 000 000
double ajavahemik = (time - _time) / 10000000.0;
//ax = ((kiirendus * raskusjõud (1G)) + eelmine kiirendus) / 2
// keskmine kiirendus kahe ajavahemiku vahel
double ax = ((x * gravity) + _ax) / 2.0;
double ay = ((y * gravity) + _ay) / 2.0;
// vx (kiirus) = eelmine keskmine kiirus + (keskmine kiirendus * aeg [ehk hetkel keskmine kiirus])
double vx = _vx + (ax * ajavahemik);
double vy = _vy + (ay * ajavahemik);
//palli uus asukoht teljel = eelmine asukoht + ((((eelmine kiirus + praegune kiirus) / 2 ) * aeg ) * kordaja=128)
//lühemalt: palli uus asukoht = eelmine asukoht + käesoleva asukoht
double sx = _sx + ((((_vx + vx) / 2.0) * ajavahemik) * mul);
double sy = _sy - ((((_vy + vy) / 2.0) * ajavahemik) * mul);
//alljärgnev arvutus tekitab põrkamise
// kui asukoht on väiksem kui -laius. laius on pool ekraanilaiusest - palli läbimõõt
//siis palli asukoht on minimaalne laius ja kiirus on -kiirus * 0,5
//(see on siis kiiruse vähenemine poole võrra aga vastassuunas)
if (sx < -width)
{
sx = -width;
vx = -vx * damping;
}
else if (sx > width)
{
sx = width;
vx = -vx * damping;
}
if (sy < -height)
{
sy = -height;
vy = -vy * damping;
}
else if (sy > height)
{
sy = height;
vy = -vy * damping;
}
// salvesta parameetrid järgmise tsükli tarvis
_time = time;
_ax = ax;
_ay = ay;
_vx = vx;
_vy = vy;
_sx = sx;
_sy = sy;
//tehakse transformX ning omistatakse sellele asukoha väärtus
//tulemus on see, et pall liigub ettenähtud kohale
BallTransform.X = sx;
BallTransform.Y = sy;
//joonistatakse kolmemõõtmelised värvilised jooned
xLine.X2 = xLine.X1 + acceleration.X * 400;
yLine.Y2 = yLine.Y1 - acceleration.Y * 400;
zLine.X2 = zLine.X1 - acceleration.Z * 200;
zLine.Y2 = zLine.Y1 + acceleration.Z * 200;
//kuvatakse kiirendusnumbrid
textBlock1.Text = "X: " + x.ToString("0.000");
textBlock2.Text = "Y: " + y.ToString("0.000");
textBlock3.Text = "Z: " + z.ToString("0.000");
}
}
}