4

Windows Phone has a nice tilt effect for buttons, like it is shown on the picture below:

Metro Tilt Effect

Is it possible to re-implement this behaviour in XNA using SpriteBatch? I can detect the touch location and calculate the points where rectangle corners should be, but I don't know how to render the image using this distortion.

Impworks
  • 2,647
  • 3
  • 25
  • 53

2 Answers2

3
Matrix projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1);
Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);

basicEffect.World = Matrix.Identity;
basicEffect.View = Matrix.Identity;
basicEffect.Projection = halfPixelOffset * projection;

basicEffect.TextureEnabled = true;
basicEffect.VertexColorEnabled = true;

spriteBatch.Begin(0, null, null, null, null, basicEffect);

You can pass a BasicEffect into the SpriteBatch.Begin method. This allows you to use custom shader with spritebatch and more interestingly in your case allows you to control the camera and transform the quad that backs the SpriteBatch. The above is the default and should behave as a standard SpriteBatch would, you can not alter the points specifically but rotating should achive the effect you are after.

To change the the 3D location of the quad simply alter the basicEffect.World matrix.

Example:

basicEffect.View = Matrix.Identity * Matrix.CreateRotationY(.002);
ClassicThunder
  • 1,896
  • 16
  • 25
  • Yeah, this snippet achieves the default projection when the sprite directly faces the camera. The essense of my question was, how do I create a non-default projection matrix that tilts the sprite? – Impworks Jul 17 '13 at 09:23
  • I pasted your code, but it didn't seem to work. The only the right half of the sprite is drawn now, the left is invisible. I tried other numbers instead of 0.002, but it didn't work either. I got a vertical stripe of my sprite which still was facing the camera directly as ever, or no sprite at all. – Impworks Jul 17 '13 at 18:14
  • changing the view matrix results in exactly the same output. Have you actually tried running the code? – Impworks Jul 18 '13 at 15:24
2

Well it's certainly possible but there is a fair amount of math involved.

The TouchPanel.GetState() method will return you back all the screen touches and their state in pretty much the same way that you would use TouchLocations in Silverlight. Main different being is that you are already working at the pixel level so no need to browse XAML trees.

Basically it would be like this: * Get the current touch panel touch collection with GetState() * Itterate through the updates for your UI elements and test collision with the touch point. * Calculate which portion of your UI element has been touched (depending on how acurate you want to be, either in 4 corners or more precise) * Animate the UI element in the direction you want to tilt * Record that the UI element has been touched or track the animation * when a touch has been lost, ensure the UI element recognises this and animates back (or animate in another direction if the touch has moved.

For some cool animations and transitions you can use, the Reach demo (for phone) shows some great effects and how to implement them. Most of them are full page effects but you should be able to break out the necessary bits to get the kind of tile animation effect you are looking for: http://xbox.create.msdn.com/en-US/education/catalog/sample/reach_graphics_demo

Let me know if this helps

Darkside
  • 1,722
  • 14
  • 19
  • I'm particularly interested in how to transform the sprite when it is drawn. I have a feeling that it can be done by passing a correct `Matrix` to `SpriteBatch.Begin`. – Impworks Jul 08 '13 at 13:16
  • The matrix you pass to sprite batch is more about camera positioning. If you want to see that in action then check out the Tiled tutorial on xnaresources.com. Check the reach demo for more details on the above – Darkside Jul 08 '13 at 13:45