|
Быть может кто-то из Вас знает игру 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.

