Skip to content

New articles plus updates #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 1 addition & 94 deletions articles/getting_to_know/howto/graphics/HowTo_Animate_Sprite.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// A helper class for handling animated textures.
/// </summary>
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<Texture2D>(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`.
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Texture2D>("starfield");
shipTexture = Content.Load<Texture2D>("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)
Original file line number Diff line number Diff line change
@@ -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<Texture2D>("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)
Loading