Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Пространственные преобразования объектов
Настройка перемещения камеры: продвинутые приемы
Рассмотрим пример, иллюстрирующий работу с камерой в режиме от первого лица и в режиме вида от третьего лица. Для подготовки этого примера мы использовали справочные материалы по XNA.
Создадим новый проект P15_3. Наш проект выполняет следующие действия. Он выводит на экран плоскость и набор кубов, среди которых может двигаться шар. Причем, движение может осуществляться в двух режимах. В первом режиме демонстрируется работа камеры при виде от первого лица – шар в таком случае не выводится, сцена выглядит так, как будто мы смотрим на нее с позиции шара. Во втором режиме демонстрируется вид от третьего лица – камера находится выше объекта. В играх часто применяется следующий прием – главный игровой объект неподвижен, а игровой мир перемещается, создавая иллюзию движения этого объекта. В нашем случае все выглядит точно так же – шар неподвижно находится в центре экрана, но за счет перемещения игровой сцены создается иллюзия его движения по экрану и по сцене.
В листинге 20.4. вы можете найти код класса Game1, который содержит пример. Для перемещения используются клавиши-стрелки, для смены состояний камеры – клавиши A и S. Клавиша A переключает программу в режим камеры от первого лица, S – в режим вида от третьего лица. Клавиша R уменьшает поле зрения камеры, клавиша F – увеличивает.
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_3 { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; //Матрицы Matrix viewMatrix; Matrix projMatrix; //Модели Model ball, cube, plane; // Позиция объекта, поворот Vector3 avatarPosition = new Vector3(0, 0, -50); float avatarlRotation; // Положение камеры Vector3 cameraReference = new Vector3(0, 0, 10); Vector3 thirdPersonReference = new Vector3(0, 200, -200); // Скорости поворота и движения float rotationSpeed = 1f / 60f; float forwardSpeed = 50f / 60f; //Поле зрения камеры float viewAngle = MathHelper.ToRadians(45.0f); //Расстояние от камеры до переднего и заднего плана //static float nearClip = 5.0f; float nearClip = 1.0f; float farClip = 2000.0f; // Установка позиции камеры 2 - вид от третьего лица //1 - от первого лица int cameraState = 2; //Соотношение сторон экрана float aspectRatio; 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"); cube = Content.Load<Model>("cube"); plane = Content.Load<Model>("plane"); 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) { //обновить положение объекта UpdateAvatarPosition(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); //Если состояние камеры 1 - вызвать процедуру //обновлеие камеры от первого лица //если 2 - от третьего лица switch (cameraState) { case 1: UpdateCamera(); break; case 2: UpdateCameraThirdPerson(); break; } //вывести объекты сцены DrawScene(); //Если выбран вид от третьего лица - вывести объект if (cameraState == 2) { DrawModel(ball, Matrix.CreateRotationY(avatarlRotation) * Matrix.CreateTranslation(avatarPosition)); } base.Draw(gameTime); } //Обновляем состояние объекта void UpdateAvatarPosition() { KeyboardState keyboardState = Keyboard.GetState(); //Поворот влево if (keyboardState.IsKeyDown(Keys.Left)) { avatarlRotation += rotationSpeed; } //Поворот вправо if (keyboardState.IsKeyDown(Keys.Right) ) { avatarlRotation -= rotationSpeed; } //Движение вперед if (keyboardState.IsKeyDown(Keys.Up) ) { Matrix forwardMovement = Matrix.CreateRotationY(avatarlRotation); Vector3 v = new Vector3(0, 0, forwardSpeed); v = Vector3.Transform(v, forwardMovement); avatarPosition.Z += v.Z; avatarPosition.X += v.X; } //Движение назад if (keyboardState.IsKeyDown(Keys.Down) ) { Matrix forwardMovement = Matrix.CreateRotationY(avatarlRotation); Vector3 v = new Vector3(0, 0, -forwardSpeed); v = Vector3.Transform(v, forwardMovement); avatarPosition.Z += v.Z; avatarPosition.X += v.X; } //Переключить на режим камеры от первого лица if (keyboardState.IsKeyDown(Keys.A)) { cameraState=1; } //Переключить на режим камеры от третьего лица if (keyboardState.IsKeyDown(Keys.S)) { cameraState = 2; } //Уменьшение угла обзора камеры if (keyboardState.IsKeyDown(Keys.R)) { viewAngle -= MathHelper.ToRadians(1.0f); } //Увеличение угла обзора камеры if (keyboardState.IsKeyDown(Keys.F)) { 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); } //Обновляем состояние камеры при выбранном виде от первого лица void UpdateCamera() { //Текущая позиция камеры Vector3 cameraPosition = avatarPosition; //Поворот Matrix rotationMatrix = Matrix.CreateRotationY(avatarlRotation); // Направление камеры Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix); // Новая позиция камеры Vector3 cameraLookat = cameraPosition + transformedReference; //Матрица вида viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f)); //проекционная матрица projMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip); } //Обновляем положение камеры при выбранном виде от третьего лица void UpdateCameraThirdPerson() { //Поворот камеры Matrix rotationMatrix = Matrix.CreateRotationY(avatarlRotation); // Направление камеры Vector3 transformedReference = Vector3.Transform(thirdPersonReference, rotationMatrix); // Позиция камеры Vector3 cameraPosition = transformedReference + avatarPosition; //Матрица вида viewMatrix = Matrix.CreateLookAt(cameraPosition, avatarPosition, new Vector3(0.0f, 1.0f, 0.0f)); //Проецкионная матрица projMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip); } //Вывод объектов сцены void DrawScene() { //Вывести кубы, расположенные в пять рядов //по пять штук в трех уровнях for (int x = 0; x < 5; x++) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 5; z++) { DrawModel(cube, Matrix.CreateTranslation(x * 40, y * 3, z * 40)); } } } //Вывести плоскость - при выводе увеличиваем модель и поворачиваем соответствующим //образом DrawModel(plane, Matrix.CreateScale (100)*Matrix .CreateRotationY (MathHelper .ToRadians (90))* Matrix.CreateRotationZ(MathHelper.ToRadians(90))* Matrix .CreateTranslation (80,-2.5f,80)); } //Процедура вывода модели //Принимает мировую матрицу для позиционирования модели //и переменную модели void DrawModel(Model model, Matrix world) { foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.LightingEnabled = true; effect.EnableDefaultLighting(); effect.Projection = projMatrix; effect.View = viewMatrix; effect.World = world; } mesh.Draw(); } } } }Листинг 20.4. Код класса Game1