Опубликован: 12.02.2013 | Уровень: для всех | Доступ: платный
Лекция 8:

Создание приложений XNA

19.2. Создание игрового мира

Создание игровых объектов

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

Игровой объект "Платформа"

Рис. 19.2. Игровой объект "Платформа"

Текстура для платформы загружается и отрисовывается на экране точно так же, как и шар. В игре будут использоваться две платформы: одна — для левого игрока, другая — для правого. Пусть левой платформой будет управлять игрок, а правой — компьютер. На экране должны отображаться три спрайта, каждый из которых использует переменную для хранения текстуры и переменную для хранения положения соответствующей текстуры на экране.

// игровой мир
Texture2D ballTexture;
Rectangle ballRectangle;
float ballX;
float ballY;
float ballXSpeed = 3;
float ballYSpeed = 3;


Texture2D lPaddleTexture;
Rectangle lPaddleRectangle;
float lPaddleSpeed = 4;
float lPaddleY;

Texture2D rPaddleTexture;
Rectangle rPaddleRectangle;
float rPaddleY;

// значение отступа платформ от краёв экрана
int margin;  

Эти переменные представляют игровой мир. Метод Update должен обновлять значения переменных, а метод Draw использует их для вывода платформ и шара на экран в нужном месте.

При запуске игры метод LoadContent загружает изображения с помощью контент-менеджера и настраивает начальное положение для элементов на экране:

protected override void LoadContent()
{
    // создание группы спрайтов, которая можно использовать для отрисовки текстур
    spriteBatch = new SpriteBatch(GraphicsDevice);  

    ballTexture = Content.Load<Texture2D>("ball");
    lPaddleTexture = Content.Load<Texture2D>("lpaddle");
    rPaddleTexture = Content.Load<Texture2D>("rpaddle");

    ballRectangle = new Rectangle(
        GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2,
        GraphicsDevice.Viewport.Width / 20, GraphicsDevice.Viewport.Width / 20);

    margin = GraphicsDevice.Viewport.Width / 20;

    lPaddleRectangle = new Rectangle(margin, 0,
        GraphicsDevice.Viewport.Width / 20, GraphicsDevice.Viewport.Height / 5);

    rPaddleRectangle = new Rectangle(
        GraphicsDevice.Viewport.Width - lPaddleRectangle.Width - margin, 0,
        GraphicsDevice.Viewport.Width / 20, GraphicsDevice.Viewport.Height / 5);

    lPaddleY = lPaddleRectangle.Y;
    rPaddleY = rPaddleRectangle.Y;
}

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

Игровые объекты на экране

Рис. 19.3. Игровые объекты на экране

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

Управление объектами с помощью сенсорного экрана

Для управления движением платформы можно использовать сенсорный экран Windows Phone. Использовать сенсорный экран для управления игровыми объектами можно по-разному. В нашем примере будет применяться следующий принцип: если игрок коснётся верхней части экрана, то его платформа будет двигаться вверх, а если коснётся нижней части экрана — то вниз.

Для взаимодействия с сенсорным экраном используется класс TouchPanel. Его метод GetState возвращает коллекцию объектов, которые описывают точки касания:

TouchCollection touches = TouchPanel.GetState();

Каждый элемент коллекции является экземпляром класса TouchLocation и содержит много свойств, которые хранят информацию о месте экрана, к которому прикоснулся пользователь. Можно использовать свойство Y этого класса, чтобы управлять движением платформы.

if (touches.Count > 0)
{
    if (touches[0].Position.Y > GraphicsDevice.Viewport.Height / 2)
    {
        lPaddleY = lPaddleY + lPaddleSpeed;
    }
    else
    {
        lPaddleY = lPaddleY - lPaddleSpeed;
    }
}

Первая строка этого блока программы проверяет, был ли сенсорный ввод. Если да, то проверяется, в какой части экрана пользователь коснулся экрана — выше или ниже середины экрана — и в соответствии с этим изменяется положение левой платформы.

Также можно использовать расширенные возможности сенсорного ввода, среди которых — несколько одновременных прикосновений, отслеживание местоположение и движения особого типа сенсорных жестов.

Обнаружение столкновений. В настоящее время платформа и шар никак не взаимодействуют друг с другом. Необходимо, чтобы шар отскакивал от платформы. Для этого необходимо определить, пересекаются ли два прямоугольника.

Для этого можно использовать метод Intersects класса Rectangle:

if (ballRectangle.Intersects(lPaddleRectangle))
{
    ballXSpeed = -ballXSpeed;
}

Этот код проверяет, коснулся ли шар левой платформы, и если да — направление движения шара по горизонтали меняется на противоположное.

Ведение счёта. Часто в играх ведётся счёт, который выводится на экран. В нашем примере очки будет зарабатывать противник игрока, который пропустил шар, и в этом случае шар касается боковой границы экрана. Для этого можно использовать существующий код, который изменяет направление движения шара по горизонтали при касании боковой границы экрана, и добавить переменную для ведения счёта для каждого игрока, увеличивая её каждый раз, когда забит "гол". Кроме этого, необходимо, чтобы текущий счёт отображался на экране. Для этого необходимо рассмотреть, как на экран вывести произвольный текст.

Вывод текста на экран

Среда XNA не предоставляет прямой доступ к выводу текста. Чтобы вывести текст на экран, игра должна загрузить символьный шрифт и использовать это для рисования символов. Используемый шрифт является элементом игрового контента, который нужно добавить в игру и настроить его размер и начертание. При построении проекта игры контент-менеджер создаёт набор символьных изображений и добавит их в игру. После этого игра сможет рисовать текст на экране наряду с другими игровыми элементами.

Чтобы добавить в игру шрифт, нужно в контент-менеджере добавить новый файл Шрифт спрайта. Файл шрифта имеет формат XML, который можно редактировать в Visual Studio:

<?xml version="1.0" encoding="utf-8"?>
<!--
Этот файл содержит XML-описание шрифта и будет считываться конвейером контента
платформы XNA. Следуйте комментариям, чтобы настроить внешний вид
шрифта в игре и изменить символы, которыми можно
рисовать.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
  <Asset Type="Graphics:FontDescription">

    <!--
    Измените эту строку, чтобы сменить импортируемый шрифт.
    -->
    <FontName>Segoe UI Mono</FontName>

    <!--
    Size — это вещественное значение, задаваемое в пунктах. Измените его,
    чтобы поменять размер шрифта.
    -->
    <Size>14</Size>

    <!--
    Spacing — это вещественное значение, задаваемое в пикселях. Измените его,
    чтобы поменять расстояние между символами.
    -->
    <Spacing>0</Spacing>

    <!--
    UseKerning задает кернинг шрифта. Если это значение равно "true", сведения
    о кернинге будут использованы при размещении символов.
    -->
    <UseKerning>true</UseKerning>

    <!--
    Style задает стиль шрифта. Допустимые значения: "Regular", "Bold", "Italic"
    и "Bold, Italic", регистр учитывается.
    -->
    <Style>Regular</Style>

    <!--
    Если снять знак комментария с этой строки, символ по умолчанию будет подставляться
    при отрисовке или измерении текста вместо символов, не включенных в шрифт.
    -->
    <!-- <DefaultCharacter>*</DefaultCharacter> -->

    <!--
    CharacterRegions указывает, какие буквы доступны в шрифте. Все символы
    от Start до End будут построены и доступны для отрисовки. Диапазон
    по умолчанию: от 32 (пробел ASCII) до 126 ("~"), что покрывает базовый набор
    символов латиницы. Символы упорядочены согласно Юникоду.
    Дополнительные сведения см. в документации.
    -->
    <CharacterRegions>
      <CharacterRegion>
        <Start>&#32;</Start>
        <End>&#126;</End>
      </CharacterRegion>
    </CharacterRegions>
  </Asset>
</XnaContent>

В этом файле выбран шрифт Segoe UI Моно размером 14 пт. После добавления шрифта в контент-менеджер его можно загружать в программу так же, как и другие ресурсы:

SpriteFont font;

font = Content.Load<SpriteFont>("MessageFont");

После этого в программе можно использовать загруженный шрифт для вывода текста на экран:

spriteBatch.DrawString(font, "Hello", new Vector2(50, 100), Color.White);

Метод DrawString принимает четыре параметра: шрифт, выводимый на экран текст, положение текста на экране и цвет текста. Позиция на экране задаётся с помощью класса Vector2.

park mr
park mr
Таиланд, thai
An Nguyen
An Nguyen
Вьетнам, 30/9 Thong Nhat street, ward 13, Go Vap district