Спонсор: Microsoft
Опубликован: 10.04.2009 | Доступ: свободный | Студентов: 3248 / 243 | Оценка: 4.49 / 4.39 | Длительность: 17:21:00
Специальности: Программист
Самостоятельная работа 15:

Пространственные преобразования объектов

Настройка перемещения камеры: базовые приемы

Камера играет огромную роль в трехмерных играх. В играх от первого лица позиция камеры ассоциируется с позицией игрока. Примерами таких игр игры класса simulator, shooter. В играх от третьего лица (strategy) камера расположена выше игрока и сдвинута назад – играющий может видеть своего персонажа и часть карты.

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

Создадим новый проект – P15_2. Рассмотрим на его примере вышеописанные операции с камерой.

В листинге 20.3. вы можете найти код класса Game1, реализующего демонстрацию работы с камерой.

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace P15_2
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        //соотношение сторон окна вывода
        float aspectRatio;

        //Матрицы
        Matrix viewMatrix;
        Matrix projMatrix;
        Matrix worldMatrix;
        //Модель
        Model ball;
        
        // Позиция и вращение камеры
        Vector3 camPos = new Vector3(0, 0, -50);
        float camRotation;

        // Направление камеры
        Vector3 cameraDirection = new Vector3(0, 0, 1);

        // Установка скорости поворота и передвижения
        float rotationSpeed = 0.01f;
        float forwardSpeed = 1.0f;

        //Угол зрения камеры
        float viewAngle = MathHelper.ToRadians(45.0f);
        GraphicsDeviceManager graphics;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        protected override void LoadContent()
        {
            //Загрузка модели
            ball = Content.Load<Model>("ball");
            //Установка мировой матрицы
            worldMatrix = Matrix.Identity;
            //Соотношение сторон
            aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /
(float)graphics.GraphicsDevice.Viewport.Height;
     
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            //Получить состояние клавиатуры
            KeyboardState keyboardState = Keyboard.GetState();

            //Поворот влево
            if (keyboardState.IsKeyDown(Keys.Left))
            {
                 camRotation += rotationSpeed;
            }
            //Поворот вправо
            if (keyboardState.IsKeyDown(Keys.Right))
            {
                camRotation -= rotationSpeed;
            }

            //Переедвижение вперед
            if (keyboardState.IsKeyDown(Keys.Up))
            {
                //Создаем матрицу поворота
                Matrix forwardMov = Matrix.CreateRotationY(camRotation);
                //Создаем новый вектор, содержащий скорость движения
                Vector3 v = new Vector3(0, 0, forwardSpeed);
                //Трансформируем матрицу в вектор
                v = Vector3.Transform(v, forwardMov);
                //модифицируем позицию таким образом, чтобы
                //она соответствовала новым данным
                camPos.Z += v.Z;
                camPos.X += v.X;
            }
            //Передвижение назад
            if (keyboardState.IsKeyDown(Keys.Down))
            {
                Matrix forwardMovement = Matrix.CreateRotationY(camRotation);
                Vector3 v = new Vector3(0, 0, -forwardSpeed);
                v = Vector3.Transform(v, forwardMovement);
                camPos.Z += v.Z;
                camPos.X += v.X;
            }

            //Уменьшение угла обзора камеры
            if (keyboardState.IsKeyDown(Keys.W))
            {
                viewAngle -= MathHelper.ToRadians(1.0f);
            }
            //Увеличение угла обзора камеры
            if (keyboardState.IsKeyDown(Keys.S))
            {
                viewAngle += MathHelper.ToRadians(1.0f);
            }
            //Если новый угол обзора вышел за дозволенные пределы
            //изменяем его
            if (viewAngle > MathHelper.ToRadians(180.0f)) viewAngle = MathHelper.ToRadians(179.9f);
            if (viewAngle < MathHelper.ToRadians(0.0f)) viewAngle = MathHelper.ToRadians(0.1f);

            Matrix rotationMatrix = Matrix.CreateRotationY(camRotation);

            // Вектор направления камеры
            Vector3 cameraTransformed = Vector3.Transform(cameraDirection, rotationMatrix);

            // Вычисляем положение камеры
            Vector3 cameraLookat = camPos + cameraTransformed;

            // Устанавливаем матрицу вида
            viewMatrix = Matrix.CreateLookAt(camPos, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
            //Устанавливаем проекционную матрицу
            projMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, 1.0f, 1000.0f);

            base.Update(gameTime);
        }
        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            foreach (ModelMesh mesh in ball.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.LightingEnabled = true;
                    effect.EnableDefaultLighting();
                    effect.Projection = projMatrix;
                    effect.View = viewMatrix;
                    effect.World = worldMatrix;

                }
                mesh.Draw();
            }

            base.Draw(gameTime);
        }
    }
}
Листинг 20.3. Код класса Game1

На рис. 20.2. вы можете видеть изображение игрового экрана проекта P15_2.

Экран проекта P15_2

увеличить изображение
Рис. 20.2. Экран проекта P15_2

Шар, который мы видим в окне, искажен – угол обзора камеры увеличен, а расстояние от камеры до объекта сильно уменьшено.

Alina Lasskaja
Alina Lasskaja

Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить.....