xna l09–2d graphics and particle engines
TRANSCRIPT
Mohammad Shakermohammadshaker.com
@ZGTRShaker2011, 2012, 2013, 2014
XNA Game DevelopmentL09 – 2D Graphics and Particle Engines
2D Graphics
2D Graphics Topics
• Introduction to 2D Graphics
• SpriteBatches
• Drawing Text with SpriteFonts
• Texure Atlases
• Rotating Sprites
• Additive Blending with Sprites
• 2D Particle Engines
2D World - Intro
SpriteBatch
SpriteBatch
• Create a Place to Store the Images In Game
private Texture2D background;
private Texture2D shuttle;
private Texture2D earth;
SpriteBatch
• Create a Place to Store the Images In Game
• LoadContent() method
private Texture2D background;
private Texture2D shuttle;
private Texture2D earth;
background = Content.Load<Texture2D>("stars");
shuttle = Content.Load<Texture2D>("shuttle");
earth = Content.Load<Texture2D>("earth");
Textures, Content
Textures, Content
SpriteBatch
• SpriteBatches Declaration
SpriteBatch spriteBatch;
SpriteBatch
• SpriteBatches Declaration
• Initializing in LoadContent()
SpriteBatch spriteBatch;
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
}
SpriteBatch
• Drawing with SpriteBatches
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.End();
SpriteBatch
• Drawing with SpriteBatches
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.End();
SpriteBatch
• A Few More Sprites
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.Draw(earth, new Vector2(400, 250), Color.White);
spriteBatch.Draw(shuttle, new Vector2(450, 250), Color.White);
spriteBatch.End();
SpriteBatch
• A Few More Sprites
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.Draw(earth, new Vector2(400, 250), Color.White);
spriteBatch.Draw(shuttle, new Vector2(450, 250), Color.White);
spriteBatch.End();
SpriteBatch
• A Few More Sprites
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.Draw(earth, new Vector2(400, 250), Color.White);
spriteBatch.Draw(shuttle, new Vector2(450, 250), Color.White);
spriteBatch.End();
You can find this in “App1-SimpleTextures”
Going on with 2D!
Acquiring Fonts
• Making a SpriteFont
Acquiring Fonts
• Down at about line 14 in the new created file you will see the following:
• You can use any font you want that’s installed in your system
• Fonts can be installed by dragging the font file to your Fonts folder, which is
located in C:/Windows/Fonts
<FontName>Segoe UI Mono</FontName>
Acquiring Fonts
• Down at about line 14 in the new created file you will see the following:
<FontName>Segoe UI Mono</FontName>
Acquiring Fonts
• Down at about line 14 in the new created file you will see the following:
• Also look down at line 20, where it says:
<FontName>Segoe UI Mono</FontName>
<Size>14</Size>
Acquiring Fonts – the using of
• Global Scope
private SpriteFont font;
private int score = 0;
Acquiring Fonts – the using of
• Global Scope
• LoadContent()
private SpriteFont font;
private int score = 0;
font = Content.Load<SpriteFont>("Score"); // Use the name of your font here instead of 'Score'.
Acquiring Fonts – the using of
• Global Scope
• LoadContent()
• Draw()
private SpriteFont font;
private int score = 0;
font = Content.Load<SpriteFont>("Score"); // Use the name of your font here instead of 'Score'.
spriteBatch.Begin();
spriteBatch.DrawString(font, "Score", new Vector2(100, 100), Color.Black);
spriteBatch.End();
Acquiring Fonts – the using of
Acquiring Fonts – the using of
• Enhancing visual with Update() method
Acquiring Fonts – the using of
• Enhancing visual with Update() method
score++;
Acquiring Fonts – the using of
• Enhancing visual with Update() method
• Now let's replace our original spriteBatch.DrawString() line with the following:
score++;
spriteBatch.DrawString(font, "Score: " + score, new Vector2(100, 100), Color.Black);
Acquiring Fonts – the using of
• “App2-ShowingText”
Texture Atlases
Texture Atlases
Texture Atlases
Texture Atlases
• Creating an AnimatedSprite Class
• Class scope members
public class AnimatedSprite
public Texture2D Texture { get; set; }
public int Rows { get; set; }
public int Columns { get; set; }
private int currentFrame;
private int totalFrames;
Texture Atlases
• Update() method
public void Update()
{
currentFrame++;
if (currentFrame == totalFrames)
currentFrame = 0;
}
Texture Atlases
• Draw() method
public void Draw(SpriteBatch spriteBatch, Vector2 location)
{
int width = Texture.Width / Rows;
int height = Texture.Height / Columns;
int row = (int)((float)currentFrame / (float)Columns);
int column = currentFrame % Columns;
Rectangle sourceRectangle = new Rectangle(width * column, height * row, width, height);
Rectangle destinationRectangle = new Rectangle((int)location.X, (int)location.Y, width, height);
spriteBatch.Begin();
spriteBatch.Draw(Texture, destinationRectangle, sourceRectangle, Color.White);
spriteBatch.End();
}
Texture Atlases
• Draw() method
public void Draw(SpriteBatch spriteBatch, Vector2 location)
{
int width = Texture.Width / Rows;
int height = Texture.Height / Columns;
int row = (int)((float)currentFrame / (float)Columns);
int column = currentFrame % Columns;
Rectangle sourceRectangle = new Rectangle(width * column, height * row, width, height);
Rectangle destinationRectangle = new Rectangle((int)location.X, (int)location.Y, width, height);
spriteBatch.Begin();
spriteBatch.Draw(Texture, destinationRectangle, sourceRectangle, Color.White);
spriteBatch.End();
}
Texture Atlases
• Draw() method
public void Draw(SpriteBatch spriteBatch, Vector2 location)
{
int width = Texture.Width / Rows;
int height = Texture.Height / Columns;
int row = (int)((float)currentFrame / (float)Columns);
int column = currentFrame % Columns;
Rectangle sourceRectangle = new Rectangle(width * column, height * row, width, height);
Rectangle destinationRectangle = new Rectangle((int)location.X, (int)location.Y, width, height);
spriteBatch.Begin();
spriteBatch.Draw(Texture, destinationRectangle, sourceRectangle, Color.White);
spriteBatch.End();
}
Texture Atlases
• Now, in Game1 Class there’s just two calls!
Texture Atlases
• Now, in Game1 Class there’s just two calls!
Texture Atlases
• Now, in Game1 Class there’s just two calls!
Texture Atlases
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
animatedSprite.Update();
base.Update(gameTime);
}
Texture Atlases
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
animatedSprite.Update();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
animatedSprite.Draw(spriteBatch, new Vector2(400, 200));
base.Draw(gameTime);
}
Texture Atlases
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
animatedSprite.Update();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
animatedSprite.Draw(spriteBatch, new Vector2(400, 200));
base.Draw(gameTime);
}
Texture Atlases
• “App3-AnimatedSprite”
Rotating Sprites
Rotating Sprites
• Preparing the Content
private Texture2D arrow;
private float angle = 0;
Rotating Sprites
• Preparing the Content
private Texture2D arrow;
private float angle = 0;
Rotating Sprites
• Preparing the Content
• In LoadContent() method
• In Update() method
private Texture2D arrow;
private float angle = 0;
// use the name of your texture here, if you are using your own
arrow = Content.Load<Texture2D>("arrow");
angle += 0.01f;
Rotating Sprites
• Draw() Method
spriteBatch.Begin();
Vector2 location = new Vector2(400, 240);
Rectangle sourceRectangle = new Rectangle(0, 0, arrow.Width,
arrow.Height);
Vector2 origin = new Vector2(0, 0);
spriteBatch.Draw(arrow, location, sourceRectangle, Color.White,
angle, origin, 1.0f, SpriteEffects.None, 1);
spriteBatch.End();
Rotating Sprites
• Draw() Method
Rotating Sprites
• Compile and run and c it!
• “App3-RotatingSpriteV0.1”
Rotating Sprites
• It’s not what we need!
Rotating Sprites
• It’s not what we need!
• We need a“Center Point Rotation”!
Using a Center Point for Rotation
• In Draw(), change
Vector2 origin = new Vector2(0, 0);
Vector2 origin = new Vector2(arrow.Width / 2, arrow.Height);
• To
Using a Center Point for Rotation
• Compile and run
Using a Center Point for Rotation
• Compile and run
Particle EnginesThe Concept
2D Particle Engine
2D Particle Engine
• Introduction
2D Particle Engine
2D Particle Engine
• images
2D Particle Engine
• Anatomy of a Particle Engine
2D Particle Engine
• Anatomy of a Particle Engine
– particles,
2D Particle Engine
• Anatomy of a Particle Engine
– particles,
– particle emitter,
2D Particle Engine
• Anatomy of a Particle Engine
– particles,
– particle emitter,
– the engine itself
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity
– particle emitter,
– the engine itself
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity, Angles
– particle emitter,
– the engine itself
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity, Angles
– particle emitter
• Location that the particles are coming from
– the engine itself
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity, Angles
– particle emitter
• Location that the particles are coming from
• Responsible for determining how many particles will be created at any given time
– the engine itself
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity, Angles
– particle emitter
• Location that the particles are coming from
• Responsible for determining how many particles will be created at any given time
– the engine itself
• Manages the state of the previous two components
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity, Angles
– particle emitter
• Location that the particles are coming from
• Responsible for determining how many particles will be created at any given time
– the engine itself
• Manages the state of the previous two components
• Responsible for removing dead particles from the system
2D Particle Engine
• Anatomy of a Particle Engine
– particles
• Velocity, Angles
– particle emitter
• Location that the particles are coming from
• Responsible for determining how many particles will be created at any given time
– the engine itself
• Manages the state of the previous two components
• Responsible for removing dead particles from the system.
2D Particle Engine
• Particle
Public class Particle
2D Particle Engine
• Particle
• ParticleEngine2D
Public class Particle
Public class ParticleEngine2D
2D Particle Engine
• Particle
Public class Particle
2D Particle Engine
• Particle
• The Particle's Properties
Public class Particle
2D Particle Engine
Public class Particle
public Texture2D Texture { get; set; }
public Vector2 Position { get; set; }
public Vector2 Velocity { get; set; }
public float Angle { get; set; }
public float AngularVelocity { get; set; }
public Color Color { get; set; }
public float Size { get; set; }
public int TTL { get; set; }
• Particle
• The Particle's Properties
2D Particle Engine
• Particle
• The Particle's Properties
Public class Particle
public Texture2D Texture { get; set; }
public Vector2 Position { get; set; }
public Vector2 Velocity { get; set; }
public float Angle { get; set; }
public float AngularVelocity { get; set; }
public Color Color { get; set; }
public float Size { get; set; }
public int TTL { get; set; }
2D Particle Engine
• Particle
• The Particle's Properties
Public class Particle
public Texture2D Texture { get; set; }
public Vector2 Position { get; set; }
public Vector2 Velocity { get; set; }
public float Angle { get; set; }
public float AngularVelocity { get; set; }
public Color Color { get; set; }
public float Size { get; set; }
public int TTL { get; set; }
2D Particle Engine
• Update()
2D Particle Engine
• Update()
public void Update()
{
TTL--;
Position += Velocity;
Angle += AngularVelocity;
}
2D Particle Engine
• Update()
public void Update()
{
TTL--;
Position += Velocity;
Angle += AngularVelocity;
}
2D Particle Engine
• Draw()
public void Draw(SpriteBatch spriteBatch)
{
Rectangle sourceRectangle = new Rectangle(0, 0, Texture.Width, Texture.Height);
Vector2 origin = new Vector2(Texture.Width / 2, Texture.Height / 2);
spriteBatch.Draw(Texture, Position, sourceRectangle, Color,
Angle, origin, Size, SpriteEffects.None, 0f);
}
2D Particle Engine
• Particle
• ParticleEngine2D
Public class Particle
Public class ParticleEngine2D
2D Particle Engine
Public class ParticleEngine2D
2D Particle Engine
Public class ParticleEngine2D
• Propertiesprivate Random random;
public Vector2 EmitterLocation { get; set; }
private List<Particle> particles;
private List<Texture2D> textures;
2D Particle Engine
public void Update()
{
int total = 10;
for (int i = 0; i < total; i++)
{
particles.Add(GenerateNewParticle());
}
for (int particle = 0; particle < particles.Count; particle++)
{
particles[particle].Update();
if (particles[particle].TTL <= 0)
{
particles.RemoveAt(particle);
particle--;
}
}
}
2D Particle Engine
public void Update()
{
int total = 10;
for (int i = 0; i < total; i++)
{
particles.Add(GenerateNewParticle());
}
for (int particle = 0; particle < particles.Count; particle++)
{
particles[particle].Update();
if (particles[particle].TTL <= 0)
{
particles.RemoveAt(particle);
particle--;
}
}
}
2D Particle Engine
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
for (int index = 0; index < particles.Count; index++)
{
particles[index].Draw(spriteBatch);
}
spriteBatch.End();
}
2D Particle Engine
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
for (int index = 0; index < particles.Count; index++)
{
particles[index].Draw(spriteBatch);
}
spriteBatch.End();
}
2D Particle Engine
• Game1 calling
2D Particle Engine
• In Update()
• In Draw()
2D Particle Engine
• In Update()
• In Draw()
particleEngine.EmitterLocation = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
particleEngine.Update();
2D Particle Engine
• In Update()
• In Draw()
particleEngine.EmitterLocation = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
particleEngine.Update();
particleEngine.Draw(spriteBatch);
2D Particle Engine
• In Update()
• In Draw()
particleEngine.EmitterLocation = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
particleEngine.Update();
particleEngine.Draw(spriteBatch);
2D Particle Engine
• Test it, Very nice!
• Can easily be ported to windows phone!
– Visit my mobile crash course on slideshare / Windows Phone slide:http://www.slideshare.net/ZGTRZGTR/mobile-software-engineering-crash-course-c06-windowsphone/
• App-2DParticleEngines
• You can test it on Windows Mobile!