1
\$\begingroup\$

I want an object (for example a ball) to move right when I tilt my Windows Phone device to the right. The same with the directions left, up and down. If the Windows Phone device isn't getting tilt in a direction, the object should rest in place.

How can I do that?

Update: I updated my code but it's still not working. The ball doesn't move if I tilt my Windows Phone device. In addition, the ball just moves continuously upwards.

What is wrong?

I don't know how to normalize the ball's velocity vector afterwards. How can I do that?

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Motion motion;
    Texture2D Ball;
    Vector2 BallPos = new Vector2(400, 300);
    Vector2 BallVelocity;
    float m_pitchForwardThreshold = 1f;
    float m_pitchBackwardThreshold = -1f;
    float m_speed = 0.5f;
    float m_rollForwardThreshold = 1f;
    float m_rollBackwardThreshold = 1f;

    void motion_CurrentValueChanged(object sender, SensorReadingEventArgs<MotionReading> e)
    {
        UpdateUI(e.SensorReading);
    }

    private void UpdateUI(MotionReading e)
    {
        float pitch = e.Attitude.Pitch;
        float roll = e.Attitude.Roll;

        if (pitch >= m_pitchForwardThreshold)
        {
           BallVelocity.Y = m_speed;
        }

        if (pitch <= m_pitchBackwardThreshold)
        {
            BallVelocity.Y = -m_speed;
        }

        if (roll >= m_rollForwardThreshold)
        {
            BallVelocity.Y = m_speed;
        }

        if (roll <= m_rollBackwardThreshold)
        {
            BallVelocity.Y = -m_speed;
        }

        BallPos = new Vector2(BallPos.X + BallVelocity.X, BallPos.Y + BallVelocity.Y);
    }

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        TargetElapsedTime = TimeSpan.FromTicks(333333);
        InactiveSleepTime = TimeSpan.FromSeconds(1);
    }

    protected override void Initialize()
    {
        if (Motion.IsSupported)
        {
            motion = new Motion();
            motion.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
            motion.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<MotionReading>>(motion_CurrentValueChanged);
            motion.Start();
        }

        base.Initialize();
    }


    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        Ball = Content.Load<Texture2D>("BallSprite");
    }

    protected override void Update(GameTime gameTime)
    {

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();
          spriteBatch.Draw(Ball, BallPos, null, Color.White, 0, new Vector2(Ball.Width/2, Ball.Height/2), 1f, SpriteEffects.None, 1);           
        spriteBatch.End();

        base.Draw(gameTime);
    }
}
\$\endgroup\$
0
\$\begingroup\$

The Windows Phone Motion class can be used to read the current orientation (CurrentValue, which will be a motion reading) a yaw/pitch/roll attitude. The value of each measure will be in radians. The yaw/pitch/roll measurements are the same as those in traditional flight dynamics (so it's pitch and roll you want).

If you give your ball a velocity vector, you can then adjust that vector in your game's update logic for the ball based on the current values of the phone's attitude. For example, you might do something like:

// One-time setup...
var motion = new Motion();
var ball = new Ball();

// Elsewhere, in the update logic...
var reading = motion.CurrentValue as MotionReading;
if (reading != null) {
  var pitch = reading.Attitude.Pitch;
  var roll = reading.Attitude.Roll;
  if (pitch >= m_pitchForwardThreshold) {
    ball.Velocity.Y = m_speed;
  }

  if (pitch <= m_pitchBackwardThreshold) {
    ball.Velocity.Y = -m_speed;
  }

  // Repeat for roll...
}

In this scenario, the thresholds are used to check if the attitude measurement gets far enough out of the 'dead zone' of the normal orientation of the phone. I'm not familiar offhand with the way in which the radian values of this sensor will map to reality and the orientation of the device, so you'll need to do a bit of experimenting there, and also to find values that are comfortable for your game.

Do make sure to normalize your ball's velocity vector afterwards, if you choose to go exactly this route; otherwise applying both pitch and roll will make the ball move much faster. Or maybe that's what you want. Just be aware of it.

Another thing to be aware of with any motion-based controls is that a user may not always keep the device in a relatively fixed orientation while playing your game (they may transition from sitting to laying down, for example), which will not alter their perception of the device's orientation (relative to themselves) but will alter the device's absolute orientation in space. You need to be aware of this when using motion sensors, and perhaps rely on other sensors (such as the gyroscope, if available, or accelerometer) to help recalibrate your motion data when necessary. There are questions on that very subject floating around on this site, so you may want to search.

\$\endgroup\$
  • \$\begingroup\$ How can I move an object with the Windows Phone accelerometer? What is the difference between the Motion class and the accelerometer? For example, an object should be moved each time 50 pixel to the right if the Windows phone device is getting tilt to the right. Should I use the Motion class or the accelerometer in this case? \$\endgroup\$ – Homer_Simpson Dec 20 '13 at 23:14
  • \$\begingroup\$ See this page for the overview of the differences between the various sensors. I think the Motion class would be simpler to start with in your case (as described above) or perhaps the Gyroscope. The APIs, which are all linked from that page, are quite similar. \$\endgroup\$ – Josh Dec 20 '13 at 23:16
  • \$\begingroup\$ I updated my question with the new code. Something must be wrong because it's not working. \$\endgroup\$ – Homer_Simpson Dec 22 '13 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.