단일 이미지의 단순 화면 출력을 해봤으니, 이번에는 여러 장의 이미지를 연속으로 보여줌으로써 연속된 동작처럼 보이게 하는 스프라이트 애니메이션(Sprite-based Animation)을 시도해보겠습니다.
스프라이트(sprite)는 연속된 이미지의 변화로 캐릭터 등에 애니메이션 효과를 나타낼 때 사용합니다.
2D 아케이드 게임 속에 등장하는 캐릭터 동작의 대부분은 스프라이트 애니메이션입니다.
XNA에는 감히! 스프라이트 처리를 위해 준비된 별도의 클래스가 없기 때문에스프라이트 처리르 위한클래스를 직접 만들어야 된다고 합니다.(What!!? -_- )
당연히, 한번만 쓰고 끝낼 기능이 아니기 때문에 별도의 클래스를 제작해둬야겠네요.
아무튼 시키는대로 해봅니다.
이번 프로젝트는 크게 아래와 같이 3개의 클래스와 불러들일 이미지들로 구성됩니다.
Program.cs
프로그램 구동시 제일 먼저 불려와서 게임을 Run을 시킵니다.
Game1.cs
게임 화면의 크기, 배경색을 비롯한 게임 전반적인 환경 설정 및 초기 이니셜라이즈(Initialize() 함수)를 시킵니다. 실제적인 게임 진행에 필요한 것들을 정의하고, 이번 포스팅에서 사용하고자 하는 이미지를 로드(LoadContent())하고, 그리기 명령(Draw())을 포함하고 있습니다.
Sprite.cs
앞서 말했듯이, XNA 자체에서는 스프라이트 효과를 주는 함수가 지원되지 않기 때문에, sprite()함수를 별도로 만들고, Game1.cs에서 Upload된 컨텐츠(이미지)를 연속해서 불러서 그리는 Draw() 함수를 정의 해 둡니다.
Sprite.cs 코딩
Sprite.cs 함수에 들어가 있는 핵심 내용은, 이미지 정보(이미지 텍스처의 개수, 테스처의 가로, 세로 크기)를 불러와서, i 번째 이미지를 출력하는 것입니다.
[ Sprite.cs 코드 보기 ]
###csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; // for Texture 2D
using Microsoft.Xna.Framework.Content; // for Content;
namespace WindowsGame1
{
class Sprite
{
// 선언
private List<Texture2D> m_lstTex = new List<Texture2D>();
private Point m_size;
private int m_cnt;
public int Count() { return m_cnt; }
public int Width() { return m_size.X; }
public int Height() { return m_size.Y; }
위 코딩에서 TotalMilliseconds / (숫자) 이 부분의 숫자를 바꾸면 이미지를 그리는 시간 간격을 조절할 수 있으므로, 애니메이션 속도를 조절할 수 있습니다. Vector2( , )는 이미지를 출력할 위지(position)을 나타냅니다. 그리고 Color.(White)에서 색깔 부분을 바꾸면 이미지에 지정한 색을 입히게 됩니다.
왼쪽 부터, Color.White / Color.Aqua / Color.Pink
[ Game1.cs 코드 보기 ]
### csharp
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Sprite sp = new Sprite();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 600;
graphics.PreferredBackBufferWidth = 800;
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
sp.Load(Content, "비행", 15); // 16장의 이미지를 로드한다. (비행0000~비행0015)
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);