Спонсор: Microsoft
Опубликован: 10.04.2009 | Уровень: специалист | Доступ: платный
Самостоятельная работа 18:

Анимация, эффекты

Аннотация: В этой лабораторной работе мы поговорим о применении графических эффектов в играх и об анимации персонажей.

Примеры к лабораторной работе

Задачи работы

  • Рассмотреть основы анимации трехмерных персонажей
  • Рассмотреть применение графических эффектов в компьютерных играх, созданных на базе 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 нашего нового проекта.

Окно Project Explorer

Рис. 24.1. Окно Project 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.

Игровой экран проекта P18_1

увеличить изображение
Рис. 24.2. Игровой экран проекта P18_1
Alina Lasskaja
Alina Lasskaja

Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить.....

Дмитрий Кацман
Дмитрий Кацман
Израиль
Андрей Веденин
Андрей Веденин
Россия, Белгород