Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 17:

Программирование простой игры в 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
  • Создайте в начале класса Car секцию #region для размещения переменных-членов этого класса
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, который будет выполнен всегда и последним, мы разблокируем и освобождаем вершинный буфер.

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

  • Добавьте в класс Car файла Car.cs функцию DrawCar() рисования автомобиля
// Функция прорисовки автомобиля
        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 класса 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;
    
        // Общедоступные свойства для характеристик класса 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
Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000