|
Быть может кто-то из Вас знает игру 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
Рассмотрев способы модификации объектов, поговорим об особенностях настройки камеры.
