вторник, 6 марта 2012 г.

Практическое применение XNA. Часть 3.

Сегодня мы продолжим осваивать 2D графику на XNA, и научимся использовать прозрачность и видео в наших приложениях.

Для начала несколько слов о видео в XNA. GameStudio 3.1 поддерживает воспроизведение видео, причем его можно использовать в качестве текстуры в трехмерных играх, например включенный телевизор по которому показывают кино. В ранних версиях XNA этой поддержки небыло. Важно отметить, что используемый формат видео файла – WMV (windows media video), который помимо хорошего качества изображения имеет еще и немалый размер, по сравнению с другими известными форматами. Так что в этом есть свои плюсы и минусы. Теперь рассмотрим пример позволяющий увидеть видео на нашем игровом экране.

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;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace myVideoSample
{
  public class Game1 : Microsoft.Xna.Framework.Game
  {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    VideoPlayer myPlayer;
    Video myVideo;
    public Game1()
    {
      graphics = new GraphicsDeviceManager(this);
      Content.RootDirectory = "Content";
    }
    protected override void Initialize()
    {
      myPlayer = new VideoPlayer();
      base.Initialize();
    }
    protected override void LoadContent()
    {
      spriteBatch = new SpriteBatch(GraphicsDevice);
      myVideo = Content.Load<Video>(@"video/xblcg");
      myPlayer.IsLooped = true;
      myPlayer.IsMuted = false;
      myPlayer.Volume = 1f;
      myPlayer.Play(myVideo);
    }
    protected override void UnloadContent()
    {
    }
    protected override void Update(GameTime gameTime)
    {
      if(Keyboard.GetState().IsKeyDown(Keys.Space))
      {
        if (myPlayer != null)
        {
          myPlayer.Stop();
          myPlayer = null;
        }
      }
      base.Update(gameTime);
    }
    protected override void Draw(GameTime gameTime)
    {
      GraphicsDevice.Clear(Color.CornflowerBlue);
      if (myPlayer != null)
      {
        spriteBatch.Begin();
        spriteBatch.Draw(myPlayer.GetTexture(),
                 new Rectangle(0,
                                          0,
                                         GraphicsDevice.Viewport.Width,
                                         GraphicsDevice.Viewport.Height),
                                         Color.White);       
       spriteBatch.End();
      }
      base.Draw(gameTime);
    }
  }
}
Здесь мы создаем екземпляр видео файла и видео плеера. Инициализируем и загружаем данные. С помощью известного нам SpriteBatch передаем на на рисование, предварительно создав папку video в нашем проекте, и скопировав в нее видео файл. Результат проделаной работы изображен на рисунке ниже

Как видите, минимум кода и все прекрасно работает.
Теперь попробуем совместить отображение 2D текстуры и видео. Сделаем это на примере мультяшного телевизора. Основываясь на предыдущих примерах, этот код практически не требует пояснений.

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;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace myTV
{
  public class Game1 : Microsoft.Xna.Framework.Game
  {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Video myVideo;
    VideoPlayer myPlayer;
    Texture2D myTexture;
    public Game1()
    {
      graphics = new GraphicsDeviceManager(this);
      Content.RootDirectory = "Content";
    }
    protected override void Initialize()
    {
      myPlayer = new VideoPlayer();
      base.Initialize();
    }
    protected override void LoadContent()
    {
      spriteBatch = new SpriteBatch(GraphicsDevice);
      myVideo = Content.Load<Video>(@"video/xblcg");
      myTexture = Content.Load<Texture2D>(@"textures/telek");
      myPlayer.IsLooped = true;
      myPlayer.IsMuted = false;
      myPlayer.Volume = 1f;
      myPlayer.Play(myVideo);
    }
    protected override void UnloadContent()
    {
    }
    protected override void Update(GameTime gameTime)
    {
      base.Update(gameTime);
    }
    protected override void Draw(GameTime gameTime)
    {
      GraphicsDevice.Clear(Color.CornflowerBlue);
      spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState);
      spriteBatch.Draw(myPlayer.GetTexture(), new Rectangle(125, 125, 500, 270), Color.White);
      spriteBatch.Draw(myTexture, new Rectangle(0, 0, 800, 600), Color.White);
      spriteBatch.End();
      base.Draw(gameTime);
    }
  }
}

Стоит сказать о единственной строке:

spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState);
При вызове метода Begin() мы передаем параметром SpriteBlendMode.AlphaBlend, для того что-бы прозрачная часть текстуры, та часть, в которой находится экран, стала действительно прозрачной. Для тех кто не знает, текстура состоит из четырех цветов - RGBA, где R - красный цвет, G - зеленый, B - синий, A - прозрачность.

В результате, мы имеем приложение, которое отображает телевизор, показывающий видео. Как всегда минимум кода, максимум удовольствия от проделанной работы.

3 комментария:

  1. А у меня в результате просто синее окно, не загружается видео. Использовал стандартное видео Wildlife, проверил запускается ли оно вообще, нет ли проблем в кодеках...но такого не обнаружил. Помогите, пожалуйста. Начинаю изучать XNA, очень интересно объясняете, но возникла вот такая проблема. В чем может быть причина?

    ОтветитьУдалить
  2. Это несколько странно. По идее должно работать. Ну для начала я бы проверил загружается ли видео в объект myVideo. Возможно все-таки дело именно в видеофайле. Попробуйте явно добавить в проект файл размером поменьше, как вариант для начала.

    ОтветитьУдалить
    Ответы
    1. О. теперь вышло) через киностудию windows сохранил в низком качестве и сработало!) теперь буду экспериментировать с достижением оптимального качества) спасибо!

      Удалить

Physically Based Rendering