Войти
XNAСтатьи

Захват Скриншота средствами XNA

В этом уроке я покажу вам, как захватить скриншот в XNA 2.0. Тема эта короткая и сравнительно простая, так что давайте уже нырнём в неё с головой!

Автор: Nezerv
Перевод: Сергей Евсеев

Прежде всего давайте создадим новый XNA 2.0 Windows Game проект. Назовите его как хотите, свой я назвал ScreenshotTutorial.

Начнём с того, что сотрём все лишние комментарии, которые идут вместе с проектом, поскольку они нам не нужны. Это отнюдь не является необходимым шагом, но мне кажется так будет лучше, потому что это сделает код немного чище и яснее.

Теперь давайте объявим пару объектов под строчкой SpriteBatch spriteBatch;

// Объявления Скриншота
Texture2D Screenshot;
RenderTarget2D ScreenshotRenderTarget;

Ничего из того, что мы сделали здесь, не было сложным, мы просто объявили два объекта: Texture и RenderTarget, которые нужны нам для захвата нашего скриншота.

Теперь нам надо инициализировать наш RenderTarget. В конце нашего метода LoadContent() добавьте вот это:

// Инициализируем наш RenderTarget
ScreenshotRenderTarget = new RenderTarget2D(
    GraphicsDevice,
    this.Window.ClientBounds.Width,
    this.Window.ClientBounds.Height,
    0,
    SurfaceFormat.Rgba64);

Всё, что мы на данный момент сделали, так это инициализировали наш RenderTarget. Давайте пройдёмся по аргументам, которые  мы передали. Первое, что мы сделали, так это передали наш объект GraphicsDevice, чтобы ассоциировать его с нашим RenderTarget. Затем мы сообщили нашему RenderTarget, какого размера мы хотим его сделать (в пикселях). Поскольку мы планируем делать и полноэкранные скриншоты, мы предоставляем полные высоту и ширину нашего окна с помощью наших значений window.ClientBounds.Width и window.ClientBounds.Height. С помощью четвёртого аргумента мы просто сообщаем, сколько мы хотим иметь mipmap-уровней. В большинстве случаев подойдёт 0 (ноль). В последнем аргументе мы просто сообщаем нужный нам формат поверхности. Я рекомендую rgba64, похоже, что он работает лучше всего. Теперь давайте загрузим простую текстуру, чтобы у нас было, что нарисовать. Я загружу простую белую картинку 256х256, которую я сделал в Photoshop'е, а вы можете загрузить всё, что хотите. Чтобы добавить картинку или текстуру в ваш проект, просто щёлкните правой кнопкой на вашей папке 'Content' в Solution Explorer'е и выберете там Add -> Existing item и просто укажите файл, который вы хотите добавить.

Всё же, прежде, чем мы сможем её использовать, нам надо её объявить. Так что давайте добавим следующий код под нашими объявлениями скриншота:

// Content
Texture2D texPicture;

Теперь давайте загрузим нашу картинку/текстуру. Добавьте этот код в конце нашего метода LoadContent():

// Загружаем нашу текстуру
texPicture = Content.Load<Texture2D>("Rectangle");

Только вам надо изменить "Rectangle" на месторасположение вашей картинки/текстуры.

Теперь давайте создадим простой метод, который будет рисовать нашу сцену (игру): 

private void DrawScene()
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();

    spriteBatch.Draw(texPicture, 
            new Vector2((Window.ClientBounds.Width  / 2) - (texPicture.Width  / 2),
                        (Window.ClientBounds.Height / 2) - (texPicture.Height / 2)), 
            Color.Red);

    spriteBatch.End();
}

Здесь нам просто надо вызвать метод, чтобы отрисовать всю нашу сцену. Конечно, это будет гораздо сложнее в более крупных проектах, но для этого урока это сработает. Здесь нет ничего фантастического, мы просто очищаем цветом наш объект GraphicsDevice, и затем рисуем нашу картинку прямо в центре нашего окна с помощью объекта SpriteBatch.

Теперь давайте изменим метод Draw(). Сначала удалите эту строчку:

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

Нам это не нужно, так как мы уже очистили наш GraphicsDevice в методе DrawScene().

Теперь давайте вызовем метод DrawScene() из нашего метода Draw(). Теперь ваш метод Draw() должен выглядеть так:

DrawScene();
base.Draw(gameTime);

Теперь давайте создадим метод, который и будет непосредственно захватывать скриншот:

private void CaptureScreenshot()
{
    // Устанавливаем наш RenderTarget
    GraphicsDevice.SetRenderTarget(0, ScreenshotRenderTarget);

    // Рисуем нашу сцену
    DrawScene();

    // Сбрасываем наш RenderTarget
    GraphicsDevice.SetRenderTarget(0, null);

    // Получаем картинку/текстуру из нашего RenderTarget
    Screenshot = ScreenshotRenderTarget.GetTexture();

    // Теперь давайте просто сохраним наш скриншот!
    Screenshot.Save("Screenshot.jpg", ImageFileFormat.Jpg);
}

Как видно, всё достаточно просто. Мы начинаем с того, что сообщаем нашему GraphicsDevice какой RenderTarget мы хотим использовать, затем рисуем нашу сцену, и просто сбрасываем наш RenderTarget, передав 0 (ноль), как второй аргумент в метод GraphicsDevice.SetRenderTarget(). После этого мы просто извлекаем текстуру из RenderTarget и копируем её в наш объект Screenshot. Отсюда вызываем метод Save() и указываем имя файла, формат файла изображения и скриншот будет сохранён!

Теперь всё, что нам надо сделать, так это обновить наш метод Update():

KeyboardState kbState = Keyboard.GetState();

// функция Exit
if (kbState.IsKeyDown(Keys.Escape))
{
    this.Exit();
}

// функция Screenshot
if (kbState.IsKeyDown(Keys.PrintScreen))
{
    CaptureScreenshot();
}

Здесь нет ничего сверхестественного. Мы просто создаём объект KeyboardState и получаем текущее состояние клавиатуры, затем проверяем, нажаты ли выбранные нами клавиши, и если нажаты, то они вызывают CaptureScreenshot(), который непосредственно делает скриншот. Хотя я должен отметить, что текущая функция для проверки нажатия клавиши PrintScreen не идеальна, поскольку она вызовает CaptureScreenshot() лишнее количество раз. Так как это легко сделать, я не буду вдаваться в подробности в этом уроке.

Также я не уверен, что это будет работать на Xbox360. Я такового не имею, поэтому проверить работоспособность не могу.

Итак, мы всё сделали!

Исходная статья здесь. Перевод предоставлен мной в рамках проекта Russian Ziggyware.

#скриншот, #tutorial, #основы

26 августа 2009