Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Пространственные преобразования объектов
Настройка перемещения камеры: базовые приемы
Камера играет огромную роль в трехмерных играх. В играх от первого лица позиция камеры ассоциируется с позицией игрока. Примерами таких игр игры класса 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.
Шар, который мы видим в окне, искажен – угол обзора камеры увеличен, а расстояние от камеры до объекта сильно уменьшено.