Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Игровой мир, освещение, тени
Задачи работы
- Рассмотреть подходы к созданию игрового мира
- Научиться использовать в качестве игрового мира готовые модели
- Ознакомиться с управлением освещением и с выводом теней в трехмерных играх
Подходы к созданию игрового мира
Для создания игрового мира трехмерной игры используют несколько подходов.
- Игровой мир можно конструировать из отдельных объектов. Например, для того, чтобы создать комнату, можно использовать плоскости для строительства стен, пола и потолка, различные объекты для создания предметов, находящихся в комнате. При таком подходе для обработки взаимодействия игрового объекта и окружения можно применить уже знакомый вам подход проверки столкновений объектов. Этот подход мы использовали в предыдущих проектах – в примере с передвижением объекта среди группы других объектов, в примере, где нужно было щелкать мышью по объектам для того, чтобы не допустить их падения.
- Игровой мир можно сконструировать в трехмерном редакторе – например – ту же комнату, или целое здание, или ландшафт – и загрузить в игру в виде отдельной модели.
- Мир можно сконструировать средствами XNA
Рассмотрим работу с игровым миром, который представлен в виде отдельной модели, содержащей все его элементы.
Загрузка игрового мира
В качестве объекта игрового мира, который мы использовали для демонстрации, применен готовый игровой объект – House – взятый с сайта http://www.turbosquid.com.
Создадим новый игровой проект P17_1. На рис. 22.1. вы можете видеть его окно Project Explorer.
В качестве игрового объекта мы используем модель ball.fbx, для построения игрового мира применим модель дома house1.x и плоскость plane.fbx. В этом проекте мы используем уже знакомый вам по предыдущим проектам класс modCls – он применяется для вывода моделей.
В листинге 22.1. вы можете видеть код класса Game1.
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 P17_1 { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; //Матрицы Matrix viewMatrix; Matrix projMatrix; //Модели Model ball, house, plane; // Позиция объекта, поворот Vector3 avatarPosition = new Vector3(0, 0, -10); float avatarlRotation; // Положение камеры Vector3 cameraReference = new Vector3(0, 0, 10); Vector3 thirdPersonReference = new Vector3(0, 20, 100); // Скорости поворота и движения float rotationSpeed = 1f / 60f; float forwardSpeed = 10f / 60f; //Поле зрения камеры float viewAngle = MathHelper.ToRadians(45.0f); //Расстояние от камеры до переднего и заднего плана float nearClip = 1.0f; float farClip = 2000.0f; //Объекты modCls ballObj; modCls mHouse; modCls mPlane; //Соотношение сторон экрана float aspectRatio; 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() { //Загрузка моделей ball = Content.Load<Model>("ball"); house = Content.Load<Model>("house1"); plane = Content.Load<Model>("plane"); aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height; } protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } protected override void Update(GameTime gameTime) { //обновить положение объекта UpdateAvatarPosition(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); UpdateCameraThirdPerson(); //вывести объекты сцены DrawScene(); base.Draw(gameTime); } //Обновляем состояние объекта void UpdateAvatarPosition() { KeyboardState keyboardState = Keyboard.GetState(); //Поворот влево if (keyboardState.IsKeyDown(Keys.Left)) { avatarlRotation += rotationSpeed; } //Поворот вправо if (keyboardState.IsKeyDown(Keys.Right)) { avatarlRotation -= rotationSpeed; } //Движение вперед if (keyboardState.IsKeyDown(Keys.Up)) { Matrix forwardMovement = Matrix.CreateRotationY(avatarlRotation); Vector3 v = new Vector3(0, 0, -forwardSpeed); v = Vector3.Transform(v, forwardMovement); avatarPosition.Z += v.Z; avatarPosition.X += v.X; } //Движение назад if (keyboardState.IsKeyDown(Keys.Down)) { Matrix forwardMovement = Matrix.CreateRotationY(avatarlRotation); Vector3 v = new Vector3(0, 0, forwardSpeed); v = Vector3.Transform(v, forwardMovement); avatarPosition.Z += v.Z; avatarPosition.X += v.X; } //Движение вверх if (keyboardState.IsKeyDown(Keys.W)) { Matrix forwardMovement = Matrix.CreateRotationY(avatarlRotation); Vector3 v = new Vector3(0, forwardSpeed, 0); v = Vector3.Transform(v, forwardMovement); avatarPosition.Y += v.Y; } //Движение вниз if (keyboardState.IsKeyDown(Keys.S)) { Matrix forwardMovement = Matrix.CreateRotationY(avatarlRotation); Vector3 v = new Vector3(0, -forwardSpeed, 0); v = Vector3.Transform(v, forwardMovement); avatarPosition.Y += v.Y; } //Уменьшение угла обзора камеры if (keyboardState.IsKeyDown(Keys.R)) { viewAngle -= MathHelper.ToRadians(1.0f); } //Увеличение угла обзора камеры if (keyboardState.IsKeyDown(Keys.F)) { viewAngle += MathHelper.ToRadians(1.0f); } //Если новый угол обзора вышел за дозволенные пределы //изменяем его if (viewAngle > MathHelper.ToRadians(180.0f)) viewAngle = MathHelper.ToRadians(179.9f); if (viewAngle < MathHelper.ToRadians(0.0f)) viewAngle = MathHelper.ToRadians(0.1f); } //Обновляем положение камеры при выбранном виде от третьего лица void UpdateCameraThirdPerson() { //Поворот камеры Matrix rotationMatrix = Matrix.CreateRotationY(avatarlRotation); // Направление камеры Vector3 transformedReference = Vector3.Transform(thirdPersonReference, rotationMatrix); // Позиция камеры Vector3 cameraPosition = transformedReference + avatarPosition; //Матрица вида viewMatrix = Matrix.CreateLookAt(cameraPosition, avatarPosition, new Vector3(0.0f, 1.0f, 0.0f)); //Проецкионная матрица projMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip); } //Вывод объектов сцены void DrawScene() { //очистить коллекцию компонентов Components.Clear(); //Вывести дом mHouse = new modCls(this, house, graphics); mHouse .WorldMatrix = Matrix.CreateTranslation(0, 0, -5)*Matrix .CreateScale (5f); mHouse .ViewMatrix = viewMatrix; mHouse .ProjectMatrix = projMatrix; Components .Add (mHouse ); //выведем игровой объект ballObj = new modCls(this, ball, graphics); ballObj.WorldMatrix = Matrix.CreateRotationY(avatarlRotation) * Matrix.CreateTranslation(avatarPosition); ballObj.ViewMatrix = viewMatrix; ballObj.ProjectMatrix = projMatrix; Components.Add(ballObj); //Вывести плоскость mPlane = new modCls(this, plane, graphics); mPlane.WorldMatrix = Matrix.CreateScale(700) * Matrix.CreateRotationY(MathHelper.ToRadians(90)) * Matrix.CreateRotationZ(MathHelper.ToRadians(90)) * Matrix.CreateTranslation(0, -2, 0); mPlane.ViewMatrix = viewMatrix; mPlane.ProjectMatrix = projMatrix; Components.Add(mPlane); } } }Листинг 22.1. Код класса Game1
На рис. 22.2. вы можете видеть игровой экран проекта P17_1.