Программирование простой игры в DirectX
Создание автомобиля
Имея движущуюся дорогу, приступим к программированию автомобиля. Для этого создадим отдельный класс, в котором разместим всю необходимую для управления автомобилем функциональность. В процессе рендеринга автомобиль должен оставаться неподвижным относительно перемещающейся сцены, за исключением перемещений влево-вправо, когда он будет объезжать препятствия, которые мы создадим позднее.
Добавление к проекту нового класса Car
-
Выполните
команду Project/Add Class и добавьте
к проекту файл с именем Car.cs нового
пустого класса
-
Удалите
из проекта лишние ссылки, автоматически добавленные оболочкой
при создании нового файла (хотя это и не обязательно!)
-
Скопируйте
из начала файла DodgerGame объявления using используемых
библиотечных пространств имен и разместите их также в начале
файла Car.cs, чтобы можно было использовать
короткие имена библиотечных классов
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace Dodger
{
class Car
{
}
}
Листинг
17.23.
Поключение библиотечных пространств имен в директивах using к файлу Car.cs
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace Dodger
{
class Car
{
#region Секция переменных-характеристик автомобиля
// Константы
public const float HEIGHT = 2.5f;// Высота автомобиля
public const float DEPTH = 3.0f;// Глубина автомобиля
public const float SPEED_INCREMENT = 0.1f;// Приращение скорости бокового перемещения
private const float SCALE = 0.85f; // Отношение размера автомобиля к ширине дороги
// Переменные
private float carLocation = DodgerGame.ROAD_LOCATION_LEFT;// Текущее положение слева
private float carDiameter;// Диаметр для расчета столкновений с препятствием
private float carSpeed = 10.0f;// Текущая боковая скорость автомобиля
private bool movingLeft = false;// Направление перемещения влево
private bool movingRight = false;// Направление перемещения вправо
// Ссылки для Mesh-объекта автомобиля
private Mesh carMesh = null;
private Material[] carMaterials = null;
private Texture[] carTextures = null;
#endregion
}
}
Листинг
17.24.
Создание секции переменных-членов класса Car
Данные константы и переменные представляют собой все характеристики, необходимые для управления автомобилем.
-
Добавьте
в класс Car конструктор
с параметрами, который при создании
автомобиля автоматически загружает или устанавливает все
его характеристики, необходимые для рендеринга
// Параметризованный конструктор класса
public Car(Device device)
{
// Создать и загрузить Mesh-объект "Автомобиль",
// используя ранее разработанный метод класса DodgerGame
carMesh = DodgerGame.LoadMesh(device, @".\car.x",
ref carMaterials, ref carTextures);
// Мы должны вычислить сферу ограничения для нашего автомобиля
VertexBuffer vb = carMesh.VertexBuffer;
try
{
// Замкнуть вершинный буфер перед вычислением
GraphicsStream stm = vb.Lock(0, 0, LockFlags.None);
Vector3 center; // Мы не будем использовать центр,
//но ссылка на него требуется
float radius = Geometry.ComputeBoundingSphere(stm,
carMesh.NumberVertices, carMesh.VertexFormat, out center);
// Вычислим диаметр автомобиля
carDiameter = (radius * 2) * SCALE;
}
finally
{
// Независимо от результата попытки
// отмыкаем и устанавливаем вершинный буфер
vb.Unlock();
vb.Dispose();
}
}
Листинг
17.25.
Параметризованный конструктор класса Car
Здесь мы использовали статический метод класса DodgerGame для создания объекта автомобиля и загрузки в него Mesh-информации из файла car.x, только с другими ссылками. Мы вычислили граничную сферу, которая полностью включает все точки автомобиля, полученные из вершинного буфера. При использовании вершинного буфера автомобиля его необходимо замкнуть - сделать недоступным другим потокам. В блоке finally, который будет выполнен всегда и последним, мы разблокируем и освобождаем вершинный буфер.
Далее необходимо добавить метод, выполняющий прорисовку нашего автомобиля. В качестве аргумента нужно передать в этот метод ссылку на устройство, которое должно быть одним для всей сцены.
// Функция прорисовки автомобиля
public void DrawCar(Device device)
{
// Автомобиль является слишком большим, предварительно уменьшим его
device.Transform.World = Matrix.Scaling(SCALE, SCALE, SCALE)
* Matrix.Translation(carLocation, HEIGHT, DEPTH);
for (int i = 0; i < carMaterials.Length; i++)
{
device.Material = carMaterials[i];
device.SetTexture(0, carTextures[i]);
carMesh.DrawSubset(i);
}
}
Листинг
17.26.
Функция DrawCar() отображения автомобиля
Здесь мы использовали такой-же код, как и при отображении дороги, но с предварительным масштабированием автомобиля.
Добавление свойств в класс Car
Ранее в секции #region объявления переменных класса Car мы создали ссылочные поля с доступом private, которые будут видны только внутри этого класса.
// Переменные
private float carLocation = DodgerGame.ROAD_LOCATION_LEFT;// Текущее полощение слева
private float carDiameter;// Диаметр для расчета столкновений с препятствием
private float carSpeed = 10.0f;// Текущая боковая скорость автомобиля
private bool movingLeft = false;// Направление перемещения влево
private bool movingRight = false;// Направление перемещения вправо
Листинг
17.27.
Созданные ранее ссылки с внутренним доступом
Но эти переменные являются управляемыми характеристиками автомобиля и должны изменяться внутри класса управления игрой DodgerGame. Поэтому упакуем их в общедоступные свойства, используя возможности языка C#.
#region Секция переменных-характеристик автомобиля
// Константы
public const float HEIGHT = 2.5f;// Высота автомобиля
public const float DEPTH = 3.0f;// Глубина автомобиля
public const float SPEED_INCREMENT = 0.1f;// Приращение скорости бокового перемещения
private const float SCALE = 0.85f; // Отношение размера автомобиля к ширине дороги
// Переменные
private float carLocation = DodgerGame.ROAD_LOCATION_LEFT;// Текущее положение слева
private float carDiameter;// Диаметр для расчета столкновений с препятствием
private float carSpeed = 10.0f;// Текущая боковая скорость автомобиля
private bool movingLeft = false;// Направление перемещения влево
private bool movingRight = false;// Направление перемещения вправо
// Ссылки для Mesh-объекта автомобиля
private Mesh carMesh = null;
private Material[] carMaterials = null;
private Texture[] carTextures = null;
// Общедоступные свойства для характеристик класса Car
public float Location // Текущее положение слева
{
get { return carLocation; }
set { carLocation = value; }
}
public float Diameter // Диаметр для расчета столкновений с препятствием
{
get { return carDiameter; }
}
public float Speed // Текущая боковая скорость автомобиля
{
get { return carSpeed; }
set { carSpeed = value; }
}
public bool IsMovingLeft // Направление перемещения влево
{
get { return movingLeft; }
set { movingLeft = value; }
}
public bool IsMovingRight // Направление перемещения вправо
{
get { return movingRight; }
set { movingRight = value; }
}
#endregion
Листинг
17.28.
Добавление общедоступных свойств в класс Car

