|
Быть может кто-то из Вас знает игру 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.
Шар, который мы видим в окне, искажен – угол обзора камеры увеличен, а расстояние от камеры до объекта сильно уменьшено.
