Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Анимация, эффекты
Задачи работы
- Рассмотреть основы анимации трехмерных персонажей
- Рассмотреть применение графических эффектов в компьютерных играх, созданных на базе XNA
Анимация персонажей
Компьютерные игры наполнены анимированными персонажами. XNA содержит встроенные средства, поддерживающие базовые операции по анимации трехмерных персонажей. В частности, это средства для работы с так называемым скелетом персонажа. Скелет состоит из взаимосвязанных костей, управляя которыми можно анимировать модель. Создание анимированных моделей – это отдельная, достаточно трудоемкая задача, которая требует серьезных познаний в области 3D-моделирования. Для подготовки анимированных трехмерных моделей вы можете использовать практически любой 3D-редактор.
XNA содержит лишь базовые средства для управления скелетами объектов. Так, мы можем получить коллекцию костей объекта и проводить с ними какие-либо преобразования, вызывающие движение модели. Однако, такой подход ограничен – с его использованием весьма сложно создать реалистичное движение для сложных моделей. На основе базовых средств XNA разработаны библиотеки кода, которые содержат компоненты, позволяющие анимировать персонажи на более высоком уровне. В частности, одну из таких библиотек – XNAAnimation – можно найти на сайте http://www.codeplex.com/xnanimation.
Здесь мы рассмотрим базовый подход к анимации модели. Он заключается в следующем. Можно менять параметры отдельных костей модели и выводить ее на экран с учетом этих изменений. Мы использовали бесплатную модель Ballpen.fbx, взятую с сайта http://www.turbosquid.com.
Создадим новый проект P18_1. Загрузим в него модель Ballpen.fbx. На рис. 24.1. представлено окно Solution Explorer нашего нового проекта.
Код проекта сосредоточен в классе Game1.cs, его код вы можете найти в листинге 24.1.
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 P18_1 { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; //Матрицы Matrix viewMatrix; Matrix projMatrix; //Модель Model pen; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { //Загрузка модели pen = Content.Load<Model>("ballpen"); //Соотношение сторон float aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height; //Устанавливаем камеру viewMatrix = Matrix.CreateLookAt(new Vector3(0, 30, 80), new Vector3(-32, 0, 0), new Vector3(0, 1, 0)); //Устанавливаем проекционную матрицу projMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 1000.0f); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { //Перемещение частей ручки PenMove(); base.Update(gameTime); } //Процедура для перемещения частей ручки void PenMove() { //Получить состояние клавиатуры KeyboardState keyboardState = Keyboard.GetState(); //Поворот зажима - он представлен родительской костью сети №3 //Умножим его матрицу трансформации на матрицу поворота по оси X pen.Meshes[3].ParentBone.Transform = pen.Meshes[3].ParentBone.Transform * Matrix.CreateRotationX (MathHelper.ToRadians(-1.0f)); //Кнопка ручки перемещается по клавиатурным командам //При нажатии кнопки "Влево" //Она выходит из ручки if (keyboardState.IsKeyDown(Keys.Left)) { //Умножим матрицу трансформации родительской костью сети №1 //На матрицу трансляции, перемещающей ее на 2 позиции влево по оси Х pen.Meshes[1].ParentBone.Transform = pen.Meshes[1].ParentBone.Transform * Matrix.CreateTranslation (new Vector3(-2, 0, 0)); } //При нажатии кнопки "Вправо" //Кнопка входит в ручку if (keyboardState.IsKeyDown(Keys.Right)) { //Умножим матрицу трансформации родительской кости сети №1 //На матрицу трансляции, перемещающую ее на 2 позиции по оси X вправо pen.Meshes[1].ParentBone.Transform = pen.Meshes[1].ParentBone.Transform * Matrix.CreateTranslation (new Vector3(2, 0, 0)); } } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); //Новый массив матриц размером, соответствующим количеству //костей в скелете модели Matrix[] absoluteTransformations = new Matrix[pen.Bones.Count]; //Скопировать матрицы трансформации костей в массив матриц pen.CopyAbsoluteBoneTransformsTo(absoluteTransformations); foreach (ModelMesh mesh in pen.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.LightingEnabled = true; effect.EnableDefaultLighting(); effect.Projection = projMatrix; effect.View = viewMatrix; //Установим новую мировую матрицу для родительской кости текущей сети //это приводит к перемещению кнопки и к перемещению зажима //Так же здесь мы уменьшаем модель, применяя коэффициент масштабирования 0,13 effect.World = absoluteTransformations[mesh.ParentBone.Index] * Matrix.CreateScale(0.13f); } //Выводим подготовленную сеть mesh.Draw(); } base.Draw(gameTime); } } }Листинг 24.1. Код класса Game1
На рис. 24.2. вы можете видеть игровой экран проекта P18_1.