I'm under the impression AS3 is a retained-mode API. You create a collection of objects - it draws and manages them for you. XNA, on the other hand, is an immediate-mode API. You are responsible for drawing things each frame, reading inputs each frame, keeping track of time, and so on.
Here is a complete game class to demonstrate what you want. Just paste it over the one in the default template, and add your own texture called "myTexture" to the content project.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
Texture2D texture;
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
texture = Content.Load<Texture2D>("myTexture");
}
bool animating;
const float totalTime = 1;
float time;
MouseState lastMouseState;
protected override void Update(GameTime gameTime)
{
MouseState mouseState = Mouse.GetState();
if(mouseState.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Released)
{
time = 0;
animating = true;
}
else if(animating)
{
time += (float)gameTime.ElapsedGameTime.TotalSeconds;
if(time > totalTime)
{
time = 0;
animating = false;
}
}
lastMouseState = mouseState;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
float alpha = time / totalTime; // from 0 to 1
Vector2 position = new Vector2(GraphicsDevice.Viewport.Width / 2f, GraphicsDevice.Viewport.Height / 2f);
Vector2 origin = new Vector2(texture.Width / 2f, texture.Height / 2f);
float rotation = MathHelper.TwoPi* alpha;
float scale = alpha < 0.5 ? MathHelper.SmoothStep(1, 2, alpha * 2f) : MathHelper.SmoothStep(2, 1, (alpha-0.5f) * 2f);
spriteBatch.Draw(texture, position, null, Color.White, rotation, origin, scale, SpriteEffects.None, 0);
spriteBatch.End();
}
}
(I've used Mouse
here, and tested on Windows, but the code should work on the phone too (where Mouse
is emulated). It should be easy enough to convert it to use actual touch inputs.)
On the one hand - this is an awful lot more code than you're probably used to. On the other hand - you get a lot more control and performance. Also - if you structure your code nicely and reuse things (admittedly this may take some practice) you can significantly reduce the amount of code you need to write in real-world situations, at least compared to the above.
And you could even go so far as to implement your own retained-mode style classes (eg: your own Sprite
class). You can do this on top of an immediate-mode API. Whereas it's practically impossible to do the inverse: an immediate-mode style code on a retained-mode API.
(Personally I recommend just embracing the immediate-mode API. Let your own game model retain things - eg: a Player
object that can draw itself, rather than a Player
object that owns a Sprite
object.)