Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Пространственные преобразования объектов
Задачи работы
- Освоить технику перемещения объектов
- Освоить технику масштабирования объектов
- Освоить технику перемещения камеры
Пространственные преобразования объектов
Создадим новый проект P15_1 и на его примере рассмотрим следующие пространственные преобразования объектов
- Перемещение
- Вращение
- Масштабирование
Для выполнения этих операций нам понадобится модификация мировой матрицы. Модификации, соответствующие перемещению объекта мы выполним по клавиатурным командам, остальные модификации будут выполняться автоматически в цикле обновления.
Для этого примера мы создали несколько простых трехмерных моделей в редакторе Blender. В частности – это два разноцветных шара и куб. Вот как выглядит игровой экран проекта P15_1 (рис. 20.1.).
Для упрощения работы с несколькими игровыми объектами мы создадим игровой компонент - modCls, который будет отвечать за хранение параметров, соответствующих этим объектам и за их визуализацию. В листинге 20.1. вы можете видеть код этого объекта.
using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using Microsoft.Xna.Framework.Content; namespace P15_1 { public class modCls : Microsoft.Xna.Framework.DrawableGameComponent { //Модель Model myModel; //Мировая матрица public Matrix WorldMatrix; //Соотношение сторон экрана public float aspectRatio; //Для управления графическим устройством GraphicsDeviceManager graphics; //Конструктор получает на вход //игровой класс, модель, объект для управления графическим устройством public modCls(Game game, Model mod, GraphicsDeviceManager grf) : base(game) { myModel = mod; graphics = grf; aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height; } public override void Initialize() { // TODO: Add your initialization code here base.Initialize(); } public override void Update(GameTime gameTime) { foreach (ModelMesh mesh in myModel.Meshes) { //Для каждого эффекта в сети foreach (BasicEffect effect in mesh.Effects) { //Установить освещение по умолчанию effect.LightingEnabled = true; effect.EnableDefaultLighting(); //установить матрицы effect.World = WorldMatrix; effect.View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 10.0f), Vector3.Zero, Vector3.Up); effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 1000.0f); } } base.Update(gameTime); } public override void Draw(GameTime gameTime) { foreach (ModelMesh mesh in myModel.Meshes) { mesh.Draw(); } base.Draw(gameTime); } } }Листинг 20.1. Код класса modCls
Управление объектами возложено на основной игровой класс – его метод Update используется для вычисления новых позиций объектов и обновления информации объектов. Код этого класса вы можете видеть в листинге 20.2. Шар, расположенный сверху, автоматически циклически изменяет размер, куб вращается вокруг осей X и Y, шар, расположенный ниже, можно перемещать. Клавиши-стрелки используются для перемещения по осям X и Y (вверх, вниз, влево и вправо), клавиши W и S перемещают объект вперед и назад по оси Z.
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_1 { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; //Мировая матрица Matrix WorldMatrixM, WorldMatrixM1, WorldMatrixM2; //Направление движения для модели modelCls1 Vector3 directM1; //Модели - //modelCls вращается //modelCls1 перемещается по клавиатурным командам //modelCls2 изменяет размер modCls modelCls, modelCls1, modelCls2; //Переменные для текущего размера и //текущего приращения размера модели modelCls2 float size, sizeDelta; 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() { //загрузка моделей и создание объектов, используемых для //хранения информации о моделях и их вывода на экран modelCls = new modCls(this, Content.Load<Model>("cube"), graphics); modelCls1 = new modCls(this, Content.Load<Model>("ball"), graphics); modelCls2 = new modCls(this, Content.Load<Model>("ball2"), graphics); //Добавляем объекты в коллекцию Components - для их //автоматического вывода на экран Components.Add(modelCls); Components.Add(modelCls1); Components.Add(modelCls2); //Значения для приращения размера и текущего размера sizeDelta = 0.01f; size = 0.5f; //Установка исходного положения для модели modelCls1 directM1 = new Vector3(2.0f, -1.0f, 1.0f); //Установка матриц, которые используются для управления объектами WorldMatrixM = Matrix.Identity; WorldMatrixM1 = Matrix.CreateTranslation(directM1); WorldMatrixM2 = Matrix.CreateScale(size); } protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } protected override void Update(GameTime gameTime) { KeyboardState kb = Keyboard.GetState(); //По нажатии клавиши-стрелки "вверх" перемещаем модель //modelCls1 вверх if (kb.IsKeyDown(Keys.Up)) { directM1.Y=directM1 .Y +0.1f; WorldMatrixM1 = Matrix.CreateTranslation(directM1); } //Нажатие клавиши "вниз" - перемещение вниз if (kb.IsKeyDown(Keys.Down)) { directM1.Y = directM1.Y - 0.1f; WorldMatrixM1 = Matrix.CreateTranslation(directM1); } //Нажатие клавиши "влево" - перемещение влево if (kb.IsKeyDown(Keys.Left)) { directM1.X = directM1.X - 0.1f; WorldMatrixM1 = Matrix.CreateTranslation(directM1); } //Нажатие клавиши "вправо" - перемещение вправо if (kb.IsKeyDown(Keys.Right)) { directM1.X = directM1.X + 0.1f; WorldMatrixM1 = Matrix.CreateTranslation(directM1); } //Нажатие клавиши "W" - перемещение вперед if (kb.IsKeyDown(Keys.W)) { directM1.Z = directM1.Z - 0.1f; WorldMatrixM1 = Matrix.CreateTranslation(directM1); } //Нажатие клавиши "S" - перемещение назад if (kb.IsKeyDown(Keys.S)) { directM1.Z = directM1.Z + 0.1f; WorldMatrixM1 = Matrix.CreateTranslation(directM1); } //Если текущий размер меньше 0.5 - //устанавливаем приращение, равное 0.01 //Если текущий размер больше 1.5 - //устанавливаем приращение -0.01 if (size < 0.5) sizeDelta = 0.01f; if (size > 1.5) sizeDelta = -0.01f; size += sizeDelta; //Матрица для объекта modelCls1 устанавливается для поворота его вокруг //осей X и Y на один градус WorldMatrixM = WorldMatrixM * Matrix.CreateRotationY(MathHelper.ToRadians(1))* Matrix .CreateRotationX (MathHelper .ToRadians (1)); //Установка матрицы для объекта modelCls2 WorldMatrixM2 = Matrix.CreateScale(size) * Matrix.CreateTranslation(new Vector3(-5.0f, 2.0f, -3.0f)); //Передаем матрицы объектам modelCls.WorldMatrix = WorldMatrixM; modelCls1.WorldMatrix = WorldMatrixM1; modelCls2.WorldMatrix = WorldMatrixM2; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); base.Draw(gameTime); } } }Листинг 20.2. Код класса Game1
Рассмотрев способы модификации объектов, поговорим об особенностях настройки камеры.