Разработка компьютерных игр для Windows Phone 7 с использованием технологий Silverlight и XNA

Графика, управление объектами

Показывать лекцию целиком

Цель работы: Научиться работать с изображениями в Silverlight-проектах

31.1. Image – вывод растровых изображений

Обычно для удобства хранения изображений, которые включают в Silverlight-приложение, в проекте создают папку, называя её, например, Images. Делать это необязательно, но поступая так, вы создаете удобное хранилище для изображений. Создадим новый Silverlight-проект, P24_1, вызовем контекстное меню проекта в Обозревателе решений и выполним команду Добавить > Создать папку. Назовём папку Images.

После того, как папка создана, в неё можно добавлять графические файлы. Silverlight поддерживает изображения в формате PNG и JPEG. Добавим в папку несколько графических файлов командой контекстного меню Добавить > Существующий элемент. В итоге у нас получилось следующее, рис. 31.1.

(рис 31.1) Несколько изображений, добавленных в папку Images

Для вывода изображений используется элемент управления Image. Создадим новую Silverlight-страницу, назовем её Images.xaml, добавим на неё новый элемент управления Image. В свойствах элемента управления есть свойство Source, именно оно определяет то изображение, которое будет загружено и показано элементом. Причём, загружать можно не только изображения, которые, фактически, оказываются встроенными в проект, но и изображения из Интернета, и графические файлы, хранящиеся на устройстве.

Загружать изображения из Интернета (например, со специально созданного веб-сайта, хранящего изображения для вашей программы) – идея очень интересная, но нельзя забывать, что недоступность сайта в таком случае приведет к неправильной работе программы.

Мы собираемся загрузить одно из изображений, которое только что добавили в папку Images, поэтому, нажав кнопку с тремя точками в поле Source, выберем изображение. По умолчанию нам представляют для выбора те изображения, которые присутствуют в проекте (рис. 31.2). При необходимости можно добавить сюда и любое другое подходящее изображение из файловой системы компьютера, оно, в любом случае, будет включено в состав проекта, который разворачивается на устройстве. При выборе изображения автоматически заполняется поле Путь.

(рис 31.2) Выбор изображения для элемента управления Image

Наше изображение имеет размер 300х300 пикселей, добавленный Image – другой размер. Элемент управления автоматически масштабирует изображение, заполняя им себя, рис. 31.3.

(рис 31.3) Элемент управления автоматически масштабирует изображение

Если не задавать свойства Height (Высота) и Width (Ширина), Image примет размеры включённого в него изображения. Тем, каким образом модифицируется изображение, включённое в Image, размер которого не совпадает с его размером, можно управлять, задавая свойство Stretch. Так, оно может принимать одно из следующих значений:

None – изображение не изменяется, сохраняя исходный размер.

Fill – это значение установлено по умолчанию, его можно наблюдать на рис. 31.3. Изображение масштабируется, без сохранения пропорций, для заполнения элемента.

Uniform – изображение масштабируется с сохранением пропорций, часть элемента может оказаться незаполненной.

UniformToFill – изображение масштабируется с сохранением пропорций, но при этом заполняет элемент. Фактически, отображаться при такой настройке будет лишь часть изображения, если пропорции элемента управления не соответствуют пропорциям изображения (рис. 31.4).

(рис 31.4) Влияние параметра Stretch на отображение изображения

Выводимое изображение можно обрезать по заданной геометрической фигуре. Добавим в проект еще один элемент управления Image, зададим ему то же изображение и приведем его XAML-код в состояние, показанное в листинге 31.1

<image number="31." Height="200" 
                   Name="image2" 
                   Stretch="Uniform" 
                   Width="200" 
                   Source="/P24_1;component/Images/Sky300x300.jpg" 
                   Margin="26,254,230,153">
                <image number="31.".Clip>
                    <EllipseGeometry RadiusX="90" RadiusY="90" Center="100,100"/>
                </Image.Clip>
            </Image> 

Здесь мы задаем в качестве фигуры, по которой обрезается изображение, круг с центром в точке 100,100 (центр элемента управления Image, размеры которого 200х200) и с радиусом, равным 90. Если значения, записанные в RadiusX и RadiusY, не равны, мы получим эллипс. На рис. 31.5 вы можете видеть результаты обрезки изображения, для сравнения там же присутствует исходное изображение такого же размера.

(рис 31.5) Обрезка изображения

Изображение можно использовать в качестве заполнителя для символов текста, заданного в TextBlock. Реализовать эффект, показанный на рис. 31.6, нам поможет код, представленный в листинге 31.2.

(рис 31.6) Результат заполнения букв изображением
<TextBlock Height="177" 
           HorizontalAlignment="Left" 
           Margin="26,301,0,0" 
           Name="textBlock1" 
           Text="Небо" 
           VerticalAlignment="Top" 
           FontSize="150" 
           Width="381" 
           FontWeight="ExtraBold">
    <TextBlock.Foreground>
        <image number="31."Brush ImageSource="/P24_1;component/Images/Sky300x300.jpg"/>
    </TextBlock.Foreground>
</TextBlock>

Здесь мы задаем свойство ImageBrush, которое использует указанное изображение для заполнения текста.

31.2. Загрузка изображений из Интернета

Для загрузки изображения в элемент Image из Интернета достаточно задать полный адрес изображения при настройке его свойства Source. Например, так, как показано на рис. 31.7.

(рис 31.7) Указание адреса изображения в Интернете

Мы добавили это изображение на новую страницу Internet.xaml

Для того, чтобы загрузить изображение в элемент по какому-либо событию, нужно, для начала, создать соответствующую инфраструктуру. А именно, мы добавили на страницу новый текстовый блок с надписью "Коснитесь здесь для загрузки изображения" и определили для него обработчик события Tap. Кроме того, мы добавили новый элемент Image, в который планируем загружать изображение. В листинге 31.3 вы можете видеть XAML-код этих элементов.

           <image number="31." Height="226" HorizontalAlignment="Left" Margin="12,71,0,0" 
           Name="image2" Stretch="Fill" VerticalAlignment="Top" Width="262"/>
           <TextBlock Height="74" HorizontalAlignment="Left" Margin="9,26,0,0" 
           Name="textBlock1" Text="Коснитесь здесь для загрузки изображения" 
           VerticalAlignment="Top" Tap="textBlock1_Tap" />

Теперь нужно поработать над обработчиком события Tap. Прежде чем загрузить изображение в элемент Image, нам нужно создать объект типа BitmapImage, воспользовавшись ссылкой на изображение. Свойство Source объекта Image – это не обычная текстовая строка, поэтому просто присвоить ему адрес изображения не достаточно. Для работы с объектом BitmapImage нам понадобится подключить в файле Internet.xaml.cs пространство имен System.Windows.Media.Imaging;

Полный код файла приведен в листинге 31.4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;

namespace P24_1
{
    public partial class Internet : PhoneApplicationPage
    {
        public Internet()
        {
            InitializeComponent();
        }

      
        private void textBlock1_Tap(object sender, GestureEventArgs e)
        {
            Uri uri = new Uri("http://img-2004-09.photosight.ru/18/620518.jpg"); 
            BitmapImage bmp = new BitmapImage(uri); 
            image2.Source = bmp;
        }
    }
}

Вот как выглядит страница в процессе разработки, рис. 31.8. Обратите внимание на то, что изображение, заданное ссылкой в свойстве Source отображается и в процессе разработки.

(рис 31.8) Использование изображений из Интернета

31.3. Захват изображения с камеры

Рассмотрим методику захвата изображений с камеры телефона. Создадим новую страницу, назовём её Camera.xaml. Добавим на страницу кнопку с подписью Сделать фото и элемент управления Image. Код элементов представлен в листинге 31.5

<image number="31.4" Height="326" HorizontalAlignment="Left" Margin="0,50,0,0" 
Name="image1" Stretch="Uniform" VerticalAlignment="Top" Width="450" />
            <Button Content="Сделать фото" Height="80" HorizontalAlignment="Left" Margin="86,446,0,0"
             Name="button1" VerticalAlignment="Top" Width="283" Click="button1_Click" />

Мы собираемся вызывать подсистему управления камерой из обработчика события нажатия на кнопку.

Для выполнения операции по захвату изображения нам понадобится класс CameraCaptureTask, для работы с ним понадобится пространство имен Microsoft.Phone.Tasks. В листинге 31.5 показан код файла Camera.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;
using Microsoft.Phone.Tasks;

namespace P24_1
{
    public partial class Camera : PhoneApplicationPage
    {
        CameraCaptureTask camera = new CameraCaptureTask();
        public Camera()
        {
            InitializeComponent();
            camera.Completed += new EventHandler<PhotoResult>(camera_Completed);
        }

        void camera_Completed(object sender, PhotoResult e)
        {
            if (e.TaskResult == TaskResult.OK) 
            { 
                BitmapImage bmp = new BitmapImage(); 
                bmp.SetSource(e.ChosenPhoto); 
                image1.Source = bmp; 
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            camera.Show();
        }
    }
}

Здесь мы создаем новый объект camera типа CameraCaptureTask и пользуемся его методом Show() для того, чтобы отобразить подсистему управления камерой при нажатии на кнопку button1.

В конструкторе класса мы подключаем обработчик события Completed для объекта camera. Это событие происходит, когда мы завершаем съемку.

В обработчике, если изображение получено, мы создаем на его основе объект типа BitmapImage, после чего задаем свойство Source для изображения, что приводит, в итоге, к выводу изображения с камеры в элемент управления image1.

Этот пример можно испытать на эмуляторе, однако, лучше испытывать его на устройстве. Причем, после запуска приложения на устройстве его нужно отключить от компьютера, иначе, при запущенной программе Zune, интерфейс камеры не доступен, как и некоторые другие возможности). На рис. 31.9 вы можете видеть снимок, сделанный камерой. После нажатия на кнопку Принять он отобразится в нашем элементе управления (рис. 31.10.)

(рис 31.9) Результат съемки (рис 31.10) Отображение результатов съемки в приложении

Рассмотрим теперь методику манипуляции изображениями на экране.

31.4. Манипуляция изображениями на экране

В качестве основы для манипуляции объектами на экране добавим на страницу (Manipulation.xaml) два изображения, опишем их свойства RenderTransform и назначим обработчики событий ManipulationDelta. В листинге 31.6 вы можете видеть XAML-код элементов.

          <image number="31." Height="128" 
                   HorizontalAlignment="Left" 
                   Margin="185,298,0,0" 
                   Name="image2" 
                   Stretch="Fill" 
                   VerticalAlignment="Top"
                   Width="128" 
                   Source="/P24_1;component/Images/Wall.png" ManipulationDelta="image2_ManipulationDelta">
                <image number="31.".RenderTransform>
                    <TranslateTransform x:Name="translate_im2" />
                </Image.RenderTransform>
            </Image>
            <image number="31." Height="64" 
                   HorizontalAlignment="Left" 
                   Margin="185,138,0,0" 
                   Name="image1" 
                   Stretch="Fill" 
                   VerticalAlignment="Top"
                   Width="64" 
                   Source="/P24_1;component/Images/Bonus1.png" ManipulationDelta="image1_ManipulationDelta">
                    <image number="31.".RenderTransform>
                         <TranslateTransform x:Name="translate_im1" />
                     </Image.RenderTransform>
                </Image>

Событие ManipulationDelta происходит при изменении позиции касания при манипуляции. Есть еще несколько событий, которые происходят при манипуляции, так, это ManipulationStarted, сигнализирующее о начале манипуляции, и ManipulationCompleted, указывающее на окончание действия.

Теперь напишем код обработчиков в файле Manipulation.xaml.cs, листинг 31.7.

private void image1_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
          translate_im1.X += e.DeltaManipulation.Translation.X;
          translate_im1.Y += e.DeltaManipulation.Translation.Y;
        }

        private void image2_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            translate_im2.X += e.DeltaManipulation.Translation.X;
            translate_im2.Y += e.DeltaManipulation.Translation.Y;
        }

Прикоснувшись к изображению мы можем перемещать его по экрану.

На рис. 31.11 вы можете видеть экран приложения.

(рис 31.11) Экран приложения">

31.5. Выводы

В данной лабораторной работе мы рассмотрели различные варианты использования элемента управления Image для вывода изображений. В частности, вывод изображения, добавленного в проект на стадии разработки, загрузку изображений из Интернета, захват изображений с камеры, встроенной в телефон. Кроме того, мы рассмотрели методику манипуляции графическими объектами с использованием событий объекта Image

31.6. Задание

Изучите состав событий объекта Image, опишите возможные сценарии использования тех из них (вместе с подходящими вариантами трансформаций), которые, по вашему мнению, подходят для организации управления экранными объектами.

31.7. Дополнительные материалы

К данной лабораторной работе прилагается видеоурок

и демонстрационный проект.

Вернуться к учебному плану