diff --git a/articles/getting_to_know/howto/graphics/HowTo_Animate_Sprite.md b/articles/getting_to_know/howto/graphics/HowTo_Animate_Sprite.md index da0e3ea7..02019bcd 100644 --- a/articles/getting_to_know/howto/graphics/HowTo_Animate_Sprite.md +++ b/articles/getting_to_know/howto/graphics/HowTo_Animate_Sprite.md @@ -35,100 +35,7 @@ Save the spritesheet to your content project and name it "**AnimatedCharacter**" 2. Create a new class called `AnimatedTexture.cs` in your project and replace its contents with the following: - ```csharp - using Microsoft.Xna.Framework; - using Microsoft.Xna.Framework.Content; - using Microsoft.Xna.Framework.Graphics; - - /// - /// A helper class for handling animated textures. - /// - public class AnimatedTexture - { - private int frameCount; - private Texture2D myTexture; - private float timePerFrame; - private int frame; - private float totalElapsed; - private bool isPaused; - - public float Rotation, Scale, Depth; - public Vector2 Origin; - - public AnimatedTexture(Vector2 origin, float rotation, float scale, float depth) - { - this.Origin = origin; - this.Rotation = rotation; - this.Scale = scale; - this.Depth = depth; - } - - public void Load(ContentManager content, string asset, int frameCount, int framesPerSec) - { - this.frameCount = frameCount; - myTexture = content.Load(asset); - timePerFrame = (float)1 / framesPerSec; - frame = 0; - totalElapsed = 0; - isPaused = false; - } - - public void UpdateFrame(float elapsed) - { - if (isPaused) - return; - totalElapsed += elapsed; - if (totalElapsed > timePerFrame) - { - frame++; - // Keep the Frame between 0 and the total frames, minus one. - frame %= frameCount; - totalElapsed -= timePerFrame; - } - } - - public void DrawFrame(SpriteBatch batch, Vector2 screenPos) - { - DrawFrame(batch, frame, screenPos); - } - - public void DrawFrame(SpriteBatch batch, int frame, Vector2 screenPos) - { - int FrameWidth = myTexture.Width / frameCount; - Rectangle sourcerect = new Rectangle(FrameWidth * frame, 0, - FrameWidth, myTexture.Height); - batch.Draw(myTexture, screenPos, sourcerect, Color.White, - Rotation, Origin, Scale, SpriteEffects.None, Depth); - } - - public bool IsPaused - { - get { return isPaused; } - } - - public void Reset() - { - frame = 0; - totalElapsed = 0f; - } - - public void Stop() - { - Pause(); - Reset(); - } - - public void Play() - { - isPaused = false; - } - - public void Pause() - { - isPaused = true; - } - } - ``` + [!code-csharp[](files/AnimatedTexture.cs)] 3. In your game's constructor, create an instance of the **AnimatedTexture** class. This example uses `(0,0)` as the origin of the texture, `no rotation`, a scale of `2`, and a depth of `0.5`. diff --git a/articles/getting_to_know/howto/graphics/HowTo_Draw_Sprite_Background.md b/articles/getting_to_know/howto/graphics/HowTo_Draw_Sprite_Background.md new file mode 100644 index 00000000..d3c156b3 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Draw_Sprite_Background.md @@ -0,0 +1,119 @@ +--- +title: Drawing a Masked Sprite over a Background +description: Demonstrates how to draw a foreground and background sprite using the SpriteBatch class, where only part of the foreground sprite masks the background. +requireMSLicense: true +--- + +## Overview + +In this example, you will draw a background texture, followed by another sprite on top of the background with its transparent elements not showing by using a [Blend State](xref:Microsoft.Xna.Framework.Graphics.BlendState) that supports alpha blending. + +### End result + +![The output of this tutorial](./images/HowTo_DrawSpriteBackground_Final.png) + +## Requirements + +The example assumes the texture you are loading contains multiple images, one for the background and one for the foreground ship texture. + +- ![starfield](images/starfield.png) +- ![ship texture](images/ship.png) + +Save the textures to your content project and name it "**AnimatedCharacter**" (this name will used to reference it in the project). + +> [!IMPORTANT] +> The foreground sprite in this example must include masking information, e.g. a PNG or DDS file that supports transparency / an alpha channel. + +## Drawing a Foreground and Background Sprite + +1. Follow the steps of [How To: Draw a Sprite](HowTo_Draw_A_Sprite.md). + A good first step to understanding the loading and drawing of textures and setting up your project. + +1. Add some variables and update the **LoadContent** method to load and initialize the content. + + ```csharp + // Position of foreground sprite on screen + private Vector2 ViperPos; + + // The texture for the ship + private Texture2D shipTexture; + + // The texture for the background + private Texture2D starTexture; + + protected override void LoadContent() + { + // Create a new SpriteBatch, which can be used to draw textures. + spriteBatch = new SpriteBatch(GraphicsDevice); + + starTexture = Content.Load("starfield"); + shipTexture = Content.Load("ship"); + Viewport viewport = graphics.GraphicsDevice.Viewport; + + ViperPos.X = viewport.Width / 2; + ViperPos.Y = viewport.Height - 100; + } + ``` + +1. In [Game.Draw](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Draw_Microsoft_Xna_Framework_GameTime_) method of your game class, call [SpriteBatch.Begin](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Begin_Microsoft_Xna_Framework_Graphics_SpriteSortMode_Microsoft_Xna_Framework_Graphics_BlendState_Microsoft_Xna_Framework_Graphics_SamplerState_Microsoft_Xna_Framework_Graphics_DepthStencilState_Microsoft_Xna_Framework_Graphics_RasterizerState_Microsoft_Xna_Framework_Graphics_Effect_System_Nullable_Microsoft_Xna_Framework_Matrix__) for the [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch). + +1. Specify [BlendState.Opaque](xref:Microsoft.Xna.Framework.Graphics.BlendState). + + > [!NOTE] + > This will tell the [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) to ignore alpha color values when drawing sprites. By default, the z-order of sprites is the order in which they are drawn. + +1. Call the [Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) method, passing in the `starTexture`. Then call [SpriteBatch.End](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_End). + + ```csharp + public override void Draw (GameTime game) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(blendState: BlendState.Opaque); + _spriteBatch.Draw (starTexture); + _spriteBatch.End(); + } + ``` + +1. After this code, call [SpriteBatch.Begin](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Begin_Microsoft_Xna_Framework_Graphics_SpriteSortMode_Microsoft_Xna_Framework_Graphics_BlendState_Microsoft_Xna_Framework_Graphics_SamplerState_Microsoft_Xna_Framework_Graphics_DepthStencilState_Microsoft_Xna_Framework_Graphics_RasterizerState_Microsoft_Xna_Framework_Graphics_Effect_System_Nullable_Microsoft_Xna_Framework_Matrix__) for the [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) again. This time, specify [BlendState.AlphaBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState). + + This will cause pixels on the sprite with an alpha value less than 255 to become progressively transparent based on the magnitude of the alpha value. An alpha of 0 will make the pixel completely transparent. + + > [!IMPORTANT] + > Calling [SpriteBatch.Begin](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Begin_Microsoft_Xna_Framework_Graphics_SpriteSortMode_Microsoft_Xna_Framework_Graphics_BlendState_Microsoft_Xna_Framework_Graphics_SamplerState_Microsoft_Xna_Framework_Graphics_DepthStencilState_Microsoft_Xna_Framework_Graphics_RasterizerState_Microsoft_Xna_Framework_Graphics_Effect_System_Nullable_Microsoft_Xna_Framework_Matrix__) with no parameters causes [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) to **default to [BlendState.AlphaBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState)**. + +1. Next in the [Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) method, we draw the `shipTexture`, `ViperPos` with [Color.White](xref:Microsoft.Xna.Framework.Color), finishing off with a call to [SpriteBatch.End](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_End). + + ```csharp + public override void Draw (GameTime game) + { + _spriteBatch.Begin(blendState: BlendState.Opaque); + _spriteBatch.Draw (starTexture); + _spriteBatch.End(); + + _spriteBatch.Begin(blendState: BlendState.AlphaBlend); + _spriteBatch.Draw (shipTexture, ViperPos, Color.White); + _spriteBatch.End(); + } + ``` + +The end result is a fixed / opaque background with a semi-transparent ship drawn on top for the player. You can of course experiment with layers / parallax transparent backgrounds behind the player too, the choice is up to you. + +### Extra Credit + +Try using this technique on top of the [How To Make A Scrolling Background](HowTo_Make_Scrolling_Background.md) guide for the beginnings of your very own space shooter :D + +## See Also + +- [Drawing a Sprite](HowTo_Draw_A_Sprite.md) +- [How To Make A Scrolling Background](HowTo_Make_Scrolling_Background.md) + +### Concepts + +- [What Is a Sprite?](../../whatis/graphics/WhatIs_Sprite.md) + +### Reference + +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) +- [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) +- [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Make_Scrolling_Background.md b/articles/getting_to_know/howto/graphics/HowTo_Make_Scrolling_Background.md new file mode 100644 index 00000000..c4189d0c --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Make_Scrolling_Background.md @@ -0,0 +1,169 @@ +--- +title: Making a Scrolling Background +description: Demonstrates how to draw a scrolling background sprite using the SpriteBatch class +requireMSLicense: true +--- + +## Overview + +In this example, you will draw a texture to the screen and then animate it vertically by scrolling it upwards in a wrapping motion. + +### End result + +![The output of this tutorial](images/HowTo_ScrollBackground_Final.gif) + +> [!NOTE] +> Textures that scroll, especially over the screen background are best if they use seamless or tileable textures, [For Example](https://www.myfreetextures.com/seamless-textures/). Essentially, textures that wrap around the edges to look like a single texture when joined together. + +## Requirements + +The example assumes the texture you are loading contains multiple frames of the same size in a texture whose size is uniform (also known as a spritesheet), for example, the following spritesheet contains 8 Images of a character in different phases of motion, when player together it looks like it is animated. + +![Starfield background](images/starfield.png) + +Save the texture to your content project and name it "**Starfield**" (this name will used to reference it in the project). + +> [!NOTE] +> The sample also uses a class named **ScrollingBackground**, which is included with the sample below. +> +> The `ScrollingBackground.cs` is a helper to simplify the scrolling of a texture in the vertical direction. Feel free to modify it to work in different directions. + +## Drawing a Scrolling Background Sprite + +1. Follow the steps of [How To: Draw a Sprite](HowTo_Draw_A_Sprite.md). + A good first step to understanding the loading and drawing of textures and setting up your project. + +2. Create a new class called `ScrollingBackground.cs` in your project and replace its contents with the following: + + [!code-csharp[](files/ScrollingBackground.cs)] + +3. Load the background texture. + + ```csharp + private ScrollingBackground myBackground; + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + // TODO: use this.Content to load your game content here + myBackground = new ScrollingBackground(); + Texture2D background = Content.Load("starfield"); + myBackground.Load(GraphicsDevice, background); + } + ``` + +4. Determine the size of the background texture and the size of the screen. + + The texture size is determined using the [Height](xref:Microsoft.Xna.Framework.Graphics.Texture2D.Height) and [Width](xref:Microsoft.Xna.Framework.Graphics.Texture2D.Width) properties, and the screen size is determined using the [Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.Viewport) property on the graphics device. + +5. Using the texture and screen information, set the origin of the texture to the center of the top edge of the texture, and the initial screen position to the center of the screen. + + ```csharp + // class ScrollingBackground + private Vector2 screenpos, origin, texturesize; + private Texture2D mytexture; + private int screenheight; + + public void Load(GraphicsDevice device, Texture2D backgroundTexture) + { + mytexture = backgroundTexture; + screenheight = device.Viewport.Height; + int screenwidth = device.Viewport.Width; + + // Set the origin so that we're drawing from the + // center of the top edge. + origin = new Vector2(mytexture.Width / 2, 0); + + // Set the screen position to the center of the screen. + screenpos = new Vector2(screenwidth / 2, screenheight / 2); + + // Offset to draw the second texture, when necessary. + texturesize = new Vector2(0, mytexture.Height); + } + ``` + +6. To scroll the background, change the screen position of the background texture in your [Game.Update](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Update_Microsoft_Xna_Framework_GameTime_) method. + + > [!NOTE] + > This example moves the background down 100 pixels per second by increasing the screen position's Y value. + + ```csharp + private float scrollingSpeed = 100; + + protected override void Update(GameTime gameTime) + { + if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) + Exit(); + + // The time since Update was called last. + float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; + + // TODO: Add your game logic here. + myBackground.Update(elapsed * scrollingSpeed); + + base.Update(gameTime); + } + ``` + + The `Y` value is kept no larger than the texture height, making the background scroll from the bottom of the screen back to the top. + + ```csharp + // class ScrollingBackground + public void Update(float deltaY) + { + screenpos.Y += deltaY; + screenpos.Y %= mytexture.Height; + } + ``` + +7. Draw the background using the origin and screen position calculated in [Game.LoadContent](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_LoadContent) and [Game.Update](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Update_Microsoft_Xna_Framework_GameTime_). + + ```csharp + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(); + myBackground.Draw(_spriteBatch, Color.White); + _spriteBatch.End(); + + base.Draw(gameTime); + } + ``` + + In case the texture does not cover the screen, another texture is drawn. This subtracts the texture height from the screen position using the **texturesize** vector created at load time. This creates the illusion of a loop. + + ```csharp + // class ScrollingBackground + public void Draw(SpriteBatch batch, Color color) + { + // Draw the texture, if it is still onscreen. + if (screenpos.Y < screenheight) + { + batch.Draw(mytexture, screenpos, null, + color, 0, origin, 1, SpriteEffects.None, 0f); + } + + // Draw the texture a second time, behind the first, + // to create the scrolling illusion. + batch.Draw(mytexture, screenpos - texturesize, null, + color, 0, origin, 1, SpriteEffects.None, 0f); + } + ``` + +## See Also + +- [Drawing a Sprite](HowTo_Draw_A_Sprite.md) +- [How to animate a sprite](HowTo_Animate_Sprite.md) +- [Drawing a Masked Sprite over a Background](HowTo_Draw_Sprite_Background.md) + +### Concepts + +- [What Is a Sprite?](../../whatis/graphics/WhatIs_Sprite.md) + +### Reference + +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) +- [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) +- [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md b/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md new file mode 100644 index 00000000..14fd4c71 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Tile_Sprites.md @@ -0,0 +1,92 @@ +--- +title: Tiling a Sprite +description: Demonstrates how to draw a sprite repeatedly in the x and y directions in one Draw call +requireMSLicense: true +--- + +## Overview + +This sample uses a texture addressing mode to duplicate a texture across the area defined by [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_). Other address modes, such as mirroring, can create interesting results. + +We will simply define an area ([Rectangle](xref:Microsoft.Xna.Framework.Rectangle)) in which to draw our texture, but in a [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) drawing mode that will keep tiling the texture until it fills the area. + +### End result + +![The output of this tutorial](images/HowTo_Tile_Sprites_Final.png) + +## Requirements + +![Sprite to Tile](images/MonoGame.png) + +## Drawing a Tiled a Sprite + +1. Follow the procedures of [Drawing a Sprite](HowTo_Draw_A_Sprite.md). +1. Setup some new variables to define how we want to draw the tiled area and with which Texture. + + ```csharp + // Tiling Texture + private Texture2D monoGameLogo; + // How many tiles wide + private int tileCountWidth = 2; + // How many tiles high + private int tileCountHeight = 2; + // Rectangle to draw tiles in + private Rectangle targetRectangle; + // Position to draw the tiled Rectangle at + private Vector2 position; + + ``` + +1. In the **LoadContent** method, we will load the Texture and then setup our drawing position and target based on the input graphics dimensions. Feel free to play with these values to alter how the tiling area is drawn. + + ```csharp + // Load the texture to tile. + monoGameLogo = Content.Load("MonoGame"); + + // Define a drawing rectangle based on the number of tiles wide and high, using the texture dimensions. + targetRectangle = new Rectangle(0, 0, monoGameLogo.Width * tileCountWidth, monoGameLogo.Height * tileCountHeight); + + // Get the drawable area of the screen. + Viewport viewport = GraphicsDevice.Viewport; + + // Center the rectangle on the screen, using both the screen center and the rectangle center. + position = new Vector2(-targetRectangle.Width / 2 + viewport.Width / 2, -targetRectangle.Height / 2 + viewport.Height / 2); + ``` + +1. In the [Game.Draw](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Draw_Microsoft_Xna_Framework_GameTime_) method, call [SpriteBatch.Begin](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Begin_Microsoft_Xna_Framework_Graphics_SpriteSortMode_Microsoft_Xna_Framework_Graphics_BlendState_Microsoft_Xna_Framework_Graphics_SamplerState_Microsoft_Xna_Framework_Graphics_DepthStencilState_Microsoft_Xna_Framework_Graphics_RasterizerState_Microsoft_Xna_Framework_Graphics_Effect_System_Nullable_Microsoft_Xna_Framework_Matrix__) to set the sprite state. + + The destination [Rectangle](xref:Microsoft.Xna.Framework.Rectangle) can be any size. In this example, the width and height of the destination rectangle are integer multiples of the source sprite. This will cause the sprite texture to be tiled, or drawn several times, to fill the destination area. + + The [Begin](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Begin_Microsoft_Xna_Framework_Graphics_SpriteSortMode_Microsoft_Xna_Framework_Graphics_BlendState_Microsoft_Xna_Framework_Graphics_SamplerState_Microsoft_Xna_Framework_Graphics_DepthStencilState_Microsoft_Xna_Framework_Graphics_RasterizerState_Microsoft_Xna_Framework_Graphics_Effect_System_Nullable_Microsoft_Xna_Framework_Matrix__) method is also using overrides to define the [SamplerState](xref:Microsoft.Xna.Framework.Graphics.SamplerState) and set it to Wrap (repeat). + + ```csharp + _spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.Opaque, SamplerState.LinearWrap, + DepthStencilState.Default, RasterizerState.CullNone); + ``` + +1. Call [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) with the sprite, the destination rectangle, and other relevant parameters. + + ```csharp + _spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.Opaque, SamplerState.LinearWrap, DepthStencilState.Default, RasterizerState.CullNone); + ``` + +1. Call [SpriteBatch.End](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_End) on your [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) object. + + ```csharp + spriteBatch.End(); + ``` + +## See Also + +- [Drawing a Sprite](HowTo_Draw_A_Sprite.md) + +### Concepts + +- [What Is a Sprite?](../../whatis/graphics/WhatIs_Sprite.md) + +### Reference + +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) +- [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) +- [SpriteSortMode](xref:Microsoft.Xna.Framework.Graphics.SpriteSortMode) +- [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) diff --git a/articles/getting_to_know/howto/graphics/files/AnimatedTexture.cs b/articles/getting_to_know/howto/graphics/files/AnimatedTexture.cs new file mode 100644 index 00000000..5d28dabf --- /dev/null +++ b/articles/getting_to_know/howto/graphics/files/AnimatedTexture.cs @@ -0,0 +1,106 @@ + using Microsoft.Xna.Framework; + using Microsoft.Xna.Framework.Content; + using Microsoft.Xna.Framework.Graphics; + + /// + /// A helper class for handling animated textures. + /// + public class AnimatedTexture + { + // Number of frames in the animation. + private int frameCount; + + // The animation spritesheet. + private Texture2D myTexture; + + // The number of frames to draw per second. + private float timePerFrame; + + // The current frame being drawn. + private int frame; + + // Total amount of time the animation has been running. + private float totalElapsed; + + // Is the animation currently running? + private bool isPaused; + + // The current rotation, scale and draw depth for the animation. + public float Rotation, Scale, Depth; + + // The origin point of the animated texture. + public Vector2 Origin; + + public AnimatedTexture(Vector2 origin, float rotation, float scale, float depth) + { + this.Origin = origin; + this.Rotation = rotation; + this.Scale = scale; + this.Depth = depth; + } + + public void Load(ContentManager content, string asset, int frameCount, int framesPerSec) + { + this.frameCount = frameCount; + myTexture = content.Load(asset); + timePerFrame = (float)1 / framesPerSec; + frame = 0; + totalElapsed = 0; + isPaused = false; + } + + public void UpdateFrame(float elapsed) + { + if (isPaused) + return; + totalElapsed += elapsed; + if (totalElapsed > timePerFrame) + { + frame++; + // Keep the Frame between 0 and the total frames, minus one. + frame %= frameCount; + totalElapsed -= timePerFrame; + } + } + + public void DrawFrame(SpriteBatch batch, Vector2 screenPos) + { + DrawFrame(batch, frame, screenPos); + } + + public void DrawFrame(SpriteBatch batch, int frame, Vector2 screenPos) + { + int FrameWidth = myTexture.Width / frameCount; + Rectangle sourcerect = new Rectangle(FrameWidth * frame, 0, + FrameWidth, myTexture.Height); + batch.Draw(myTexture, screenPos, sourcerect, Color.White, + Rotation, Origin, Scale, SpriteEffects.None, Depth); + } + + public bool IsPaused + { + get { return isPaused; } + } + + public void Reset() + { + frame = 0; + totalElapsed = 0f; + } + + public void Stop() + { + Pause(); + Reset(); + } + + public void Play() + { + isPaused = false; + } + + public void Pause() + { + isPaused = true; + } + } \ No newline at end of file diff --git a/articles/getting_to_know/howto/graphics/files/ScrollingBackground.cs b/articles/getting_to_know/howto/graphics/files/ScrollingBackground.cs new file mode 100644 index 00000000..452382a9 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/files/ScrollingBackground.cs @@ -0,0 +1,61 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +/// +/// A helper class to scroll a texture vertically +/// +public class ScrollingBackground +{ + // Screen Position to draw the background from. + private Vector2 screenpos; + + // The texture origin point. + private Vector2 origin; + + // The size of the texture in pixels (using ony the texture height). + private Vector2 texturesize; + + // The texture to draw as a background. + private Texture2D mytexture; + + // The height of the screen in pixels. + private int screenheight; + + public void Load(GraphicsDevice device, Texture2D backgroundTexture) + { + mytexture = backgroundTexture; + screenheight = device.Viewport.Height; + int screenwidth = device.Viewport.Width; + + // Set the origin so that we're drawing from the + // center of the top edge. + origin = new Vector2(mytexture.Width / 2, 0); + + // Set the screen position to the center of the screen. + screenpos = new Vector2(screenwidth / 2, screenheight / 2); + + // Offset to draw the second texture, when necessary. + texturesize = new Vector2(0, mytexture.Height); + } + + public void Update(float deltaY) + { + screenpos.Y += deltaY; + screenpos.Y %= mytexture.Height; + } + + public void Draw(SpriteBatch batch, Color color) + { + // Draw the texture, if it is still onscreen. + if (screenpos.Y < screenheight) + { + batch.Draw(mytexture, screenpos, null, + color, 0, origin, 1, SpriteEffects.None, 0f); + } + + // Draw the texture a second time, behind the first, + // to create the scrolling illusion. + batch.Draw(mytexture, screenpos - texturesize, null, + color, 0, origin, 1, SpriteEffects.None, 0f); + } +} \ No newline at end of file diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_DrawSpriteBackground_Final.png b/articles/getting_to_know/howto/graphics/images/HowTo_DrawSpriteBackground_Final.png new file mode 100644 index 00000000..7987a1f8 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_DrawSpriteBackground_Final.png differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_ScrollBackground_Final.gif b/articles/getting_to_know/howto/graphics/images/HowTo_ScrollBackground_Final.gif new file mode 100644 index 00000000..790ddcb2 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_ScrollBackground_Final.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png b/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png new file mode 100644 index 00000000..43ee8147 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_Tile_Sprites_Final.png differ diff --git a/articles/getting_to_know/howto/graphics/images/MonoGame.png b/articles/getting_to_know/howto/graphics/images/MonoGame.png new file mode 100644 index 00000000..43ee8147 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/MonoGame.png differ diff --git a/articles/getting_to_know/howto/graphics/images/ship.png b/articles/getting_to_know/howto/graphics/images/ship.png new file mode 100644 index 00000000..22ecaecc Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/ship.png differ diff --git a/articles/getting_to_know/howto/graphics/images/starfield.png b/articles/getting_to_know/howto/graphics/images/starfield.png new file mode 100644 index 00000000..140507cd Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/starfield.png differ diff --git a/articles/getting_to_know/howto/graphics/index.md b/articles/getting_to_know/howto/graphics/index.md index a5178acc..98fa0ba6 100644 --- a/articles/getting_to_know/howto/graphics/index.md +++ b/articles/getting_to_know/howto/graphics/index.md @@ -15,35 +15,47 @@ This section demonstrates several graphical concepts divided into the following ### 2D Sprite Rendering -[How To Draw A Sprite](HowTo_Draw_A_Sprite.md) +This section walks through several core concepts related to sprite rendering, including drawing text to the screen. -Demonstrates how to draw a sprite by using the SpriteBatch class. +- [How To Draw A Sprite](HowTo_Draw_A_Sprite.md) -[How To Tint A Sprite](HowTo_Tint_Sprite.md) + Demonstrates how to draw a sprite by using the SpriteBatch class. -Demonstrates how to tint a sprite using a Color value. +- [How To Draw A Sprite Background](HowTo_Draw_Sprite_Background.md) -[How To Rotate A Sprite](HowTo_Rotate_Sprite.md) + Demonstrates how to draw a foreground and background sprite using the SpriteBatch class, where only part of the foreground sprite masks the background. -Demonstrates how to rotate a sprite around its center. +- [How To Tint A Sprite](HowTo_Tint_Sprite.md) -[How To Rotate A Sprite Group](HowTo_Rotate_Sprite_Group.md) + Demonstrates how to tint a sprite using a Color value. -Demonstrates how to rotate a group of sprites around a single point. +- [How To Rotate A Sprite](HowTo_Rotate_Sprite.md) -[How To Scale A Sprite](HowTo_Scale_Sprite.md) + Demonstrates how to rotate a sprite around its center. -Demonstrates how to scale a sprite using a uniform scale. +- [How To Rotate A Sprite Group](HowTo_Rotate_Sprite_Group.md) -[How To Scale A Sprite using A Matrix](HowTo_Scale_Sprites_Matrix.md) + Demonstrates how to rotate a group of sprites around a single point. -Demonstrates how to scale sprites using a matrix that is created based on the viewport width. +- [How To Scale A Sprite](HowTo_Scale_Sprite.md) -This section walks through several core concepts related to sprite rendering, including drawing text to the screen. + Demonstrates how to scale a sprite using a uniform scale. + +- [How To Scale A Sprite using A Matrix](HowTo_Scale_Sprites_Matrix.md) + + Demonstrates how to scale sprites using a matrix that is created based on the viewport width. + +- [How To Tile Sprites](HowTo_Tile_Sprites.md) + + Demonstrates how to draw a sprite repeatedly in the x and y directions in one Draw call. + +- [How To Animate A Sprite](HowTo_Animate_Sprite.md) + + Demonstrates how to animate a sprite from a texture using a custom class. -[How To Animate A Sprite](HowTo_Animate_Sprite.md) +- [How To Make A Scrolling Background](HowTo_Make_Scrolling_Background.md) -Demonstrates how to animate a sprite from a texture using a custom class. + Demonstrates how to draw a scrolling background sprite using the SpriteBatch class. > More Coming soon