Визуализация / Разработка игр на Silverlight для начинающих

Теперь нам нужно отображать на экране нашу разработанную модель. А вот эта часть уже имеет самое прямое отношение к Silverlight.

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

В качестве контейнера будем использовать класс Canvas, внутрь которого будем помещать изображение класса Image.

Объявим необходимые параметры:

namespace MemoryCards.Views
{
public partial class GameBoard : Page
{
Models.GameBoard gameBoard;
Canvas[] arrCanvasImg;
Image[] arrImage;
int nWidthSprite;//ширина спрайта
int nHeightSprite;//высота спрайта
int nWidthSpace;//ширина пробела
int nHeightSpace;//высота пробела
int nLeftMargin;//отступ слева
int nTopMargin;//отступ справа

gameBoard - это модель нашей игровой доски. arrCanvasImg и arrImage массивы контейнеров и изображений. Оставшиеся шесть параметров — это размерные характеристики наших визуальных карточек-спрайтов, размеры карточки, расстояние между карточками, отступы от окна.
В конструкторе класса MemoryCards.Views.GameBoard — сделаем инициализацию:

public GameBoard()
{
InitializeComponent();

gameBoard = new Models.GameBoard(5, 4);

nWidthSprite = nHeightSprite = 50;
nWidthSpace = nHeightSpace = nWidthSprite / 2;
int nSpritesWidth = Convert.ToInt16(Sprites.GetValue(Canvas.WidthProperty));
int nSpritesHeight = Convert.ToInt16(Sprites.GetValue(Canvas.HeightProperty));
nLeftMargin = (nSpritesWidth - (nWidthSprite * gameBoard.nSizeWidth) - (nWidthSpace * (gameBoard.nSizeWidth - 1))) / 2;
nTopMargin = (nSpritesHeight - (nHeightSprite * gameBoard.nSizeHeight) - (nHeightSpace * (gameBoard.nSizeHeight - 1))) / 2;
prepareViewer();

Создаем объект gameBoard размерностью 5*4. Задаем размеры карточек, вычисляем расстояние между и отступы. И вызываем метод подготовки вида prepareViewer():

void prepareViewer()
{
int nCountCell = gameBoard.nCountCell;
arrCanvasImg = new Canvas[nCountCell];
arrImage = new Image[nCountCell];

Uri uri = new Uri("../Images/a_z.png", UriKind.Relative);

for (int ix = 0; ix < gameBoard.nSizeWidth; ix++)
{
for (int iy = 0; iy < gameBoard.nSizeHeight; iy++)
{
int nIndex = Helper.getListIndex(gameBoard.nSizeWidth, ix, iy);
//создание и загрузка изображения по uri
arrImage[nIndex] = new Image();
arrImage[nIndex].Height = nHeightSprite;
arrImage[nIndex].Width = nWidthSprite * gameBoard.nCountImages;
arrImage[nIndex].Stretch = Stretch.Uniform;
arrImage[nIndex].Source = new BitmapImage(uri);
//обрезка и смещение изображения до позиции нужной картинки
RectangleGeometry rg = new RectangleGeometry();
rg.Rect = new Rect((gameBoard.arrBoard[nIndex].nImageIndex * nWidthSprite), 0, nWidthSprite, nHeightSprite);
arrImage[nIndex].Clip = rg;
arrImage[nIndex].SetValue(Canvas.TopProperty, Convert.ToDouble(0));
arrImage[nIndex].SetValue(Canvas.LeftProperty, Convert.ToDouble(gameBoard.arrBoard[nIndex].nImageIndex * nWidthSprite * -1));
//создание контейнера для изображения
arrCanvasImg[nIndex] = new Canvas();
arrCanvasImg[nIndex].Width = nWidthSprite;
arrCanvasImg[nIndex].Height = nHeightSprite;
SolidColorBrush scb = new SolidColorBrush();
scb.Color = Color.FromArgb(255, 0, 0, 255);
arrCanvasImg[nIndex].Background = scb;
arrCanvasImg[nIndex].Children.Add(arrImage[nIndex]);
arrCanvasImg[nIndex].SetValue(Canvas.NameProperty, "Canvas_" + nIndex.ToString());
arrCanvasImg[nIndex].DataContext = nIndex;//передаем в canvas индекс карточки
//расстановка координат карточек
int nx = nLeftMargin + (ix * (nWidthSprite + nWidthSpace));
int ny = nTopMargin + (iy * (nHeightSprite + nHeightSpace));
arrCanvasImg[nIndex].SetValue(Canvas.TopProperty, Convert.ToDouble(ny));
arrCanvasImg[nIndex].SetValue(Canvas.LeftProperty, Convert.ToDouble(nx));
//установка обработки щелчка левой кнопки мыши по карточке
arrCanvasImg[nIndex].MouseLeftButtonDown += new MouseButtonEventHandler(GameBoard_MouseLeftButtonDown);
//добавляем карточку в специально созданный для карточек слой
Sprites.Children.Add(arrCanvasImg[nIndex]);
}
}
repaint();
}//prepareViewer

Определяем массивы arrCanvasImg и arrImage по размеру количества карточек (nCountCell) в модели. В двойном цикле по ширине и высоте игровой доски заполняем массивы arrCanvasImg и arrImage. Хочу обратить внимание на:
arrImage[nIndex].Source = new BitmapImage(uri) — загрузка изображения из файла заданного через класс Uri;
arrCanvasImg[nIndex].Background = scb цвет задается через класс SolidColorBrush;
arrCanvasImg[nIndex].Children.Add(arrImage[nIndex]) — в контейнер Canvas добавляем изображение Image;
arrCanvasImg[nIndex].MouseLeftButtonDown += new MouseButtonEventHandler(GameBoard_MouseLeftButtonDown) — на каждый динамически созданный контейнер (карточку) мы можем добавлять обработчики событий, а для того чтобы потом отличать карточки, записываем свойство DataContext , код обработки приведу в разделе про контроллер;
Sprites.Children.Add(arrCanvasImg[nIndex]) слой спрайтов прописывается в файле GameBoard.xaml


<Canvas x:Name="Sprites" Canvas.Left="50" Canvas.Top="50" Width="400" Height="400"></Canvas>
Очень удобно в программе напрямую обращаться к объекту по заданному имени (тег x:Name).
После подготовки сразу запускается перерисовка игровой доски:

void repaint()
{
for (int n = 0; n < gameBoard.nCountCell; n++)
{
Image image = arrCanvasImg[n].Children[0] as Image;
if (gameBoard.arrBoard[n].bOpen == false)
image.Visibility = Visibility.Collapsed;
else
image.Visibility = Visibility.Visible;
if (gameBoard.arrBoard[n].bComplit == true)
{
image.Visibility = Visibility.Visible;
image.Opacity = 0.5;
}
}
if (gameBoard.bEndGame)
{
textBlockState.Text = "Game The End";
}
textBlockTryOpen.Text = "Try: "+gameBoard.nCountTryOpen.ToString();
}//repaint

Эта же функция будет запускаться во время действий игрока. Собственно саму доску в этой функции мы уже не рисуем, так как нам не требуется добавлять новые карточки или перемещать существующие по доске. Мы только изменяем свойства видимости и прозрачности изображений в зависимости от свойств модели. А также выводим информацию в специальные текстовые блоки файла GameBoard.xaml:


<TextBlock x:Name="textBlockState" Text="" FontSize="20" TextAlignment="Center" Canvas.Left="100" Canvas.Top="460" Width="300"></TextBlock>
<TextBlock x:Name="textBlockTryOpen" Text="0" FontSize="20" TextAlignment="Center" Canvas.Left="415" Canvas.Top="460" Width="60"></TextBlock>


Комментариев нет:

Отправить комментарий

Да, я внимательно слушаю