Навигация
· XNA FAQ
· С чего начать
· Конкурсы
· Обратная связь
· XNA Блоги
Сейчас на сайте
· Гостей: 1

· Пользователей: 0

· Всего пользователей: 3,684
· Новый пользователь: headron
Последние фото
Эх, чуть не проспал закрытие.
Эх, чуть не проспал ...
Альбом: XNA Engine

GB
GB
Альбом: XNA Engine

South Park Coon & Friends
South Park Coon & Fr...
Альбом: XNA Games

Блоги
yavshoke
» XboxOne - интерес...
dampirik
» Push уведомления ...
dampirik
» Реклама,статистик...
Chort
» XNA и StartCoroutine
Chort
» Curve Class
dampirik
» Реклама, статисти...
dampirik
» Увеличение скорос...
dampirik
» Реклама, статисти...
general
» Распаковка DxtCom...
general
» Как работать с XN...
Поддержка
microsoft.com
1gb.ru - Дом для вашего сайта
Статистика посещений:

Взаимодействие 3D объектов

Лабораторная работа №16. Взаимодействие объектов


Эта лабораторная работа посвящена обработке взаимодействия трехмерных объектов. Мы рассмотрим способы обработки столкновений объектов, поговорим о взаимодействии трехмерных объектов и указателя мыши.

Цель работы
  • Научиться обрабатывать столкновения трехмерных объектов
Задачи работы
  • Рассмотреть стандартные объекты XNA: BoundingBox, BoundingSphere, BoundingFrustum, Plane, Ray, которые можно использовать для обработки столкновений
  • Создать игровой пример, демонстрирующий взаимодействие объектов
  • Рассмотреть особенности взаимодействия указателя мыши с трехмерными объектами
  • Рассмотреть взаимодействие плоскостей с трехмерными объектами
Обработка столкновений объектов

В XNA есть несколько стандартных объектов, которые можно применять для обработки столкновений игровых объектов. Это структуры BoundingBox, BoundingSphere и BoundingFrustum.

Структура BoundingBox представляет собой прямоугольный «ящик», в который можно «упаковать» объект. Надо отметить, что объект класса Model может возвратить объект типа BoundingSphere для каждой своей сети – этот прием можно использовать при обработке столкновений нескольких объектов.

Структура BoundingSphere представляет собой сферу, в которой содержится объект.
Эти структуры подходят лишь для работы с простыми объектами – например – с трехмерными шарами и кубами. Если объект имеет более сложную форму – он либо обрабатывается как набор более простых объектов, каждый из которых можно заключить, например, в собственную BoundingSphere, либо для такого объекта создается отдельный контент-процессор (content pipeline processor), который предназначен для работы с данным объектом.

Структура BoundingFrustum представляет собой область игрового пространства, которая в данный момент видима с учетом параметров видовой и проекционной матриц.

Далее, для обработки столкновений объектов можно применять такие структуры, как Plane – эта структура представляет собой плоскость, Ray – луч.

Рассмотрим использование объекта класса BoundingSphere для обработки столкновений объектов. Выведем в пространство несколько шаров, используем в качестве игрового объекта еще один шар. Будем перемещать шар и проверять, не столкнулся ли он с каким-нибудь из объектов сцены в процессе перемещения. Если столкнулся – перемещение отменяется и расстояние между столкнувшимися объектами увеличивается до тех пор, пока они выйдут из состояния столкновения.

Для проверки столкновения объектов используется метод Intersects – его можно вызывать, например, для объекта BoundingSphere и передать в качестве параметра другой объект BoundingSphere, а так же – объекты других подходящих типов. Метод возвращает True, если объекты пересекаются (то есть – есть столкновение), и false – если не пересекаются.

Создадим новый игровой проект P16_1, на примере которого рассмотрим решение вышеописанной задачи. На рис. 16.1. вы можете видеть окно Project Explorer для этого проекта. Обратите внимание на две модели, которые мы будем использовать в примере, а так же – на наличие класса modCls. Объекты этого класса содержат информацию об игровых объектах и используются для их визуализации.


Рис. 16.1. Окно проекта P16_1

В листинге 16.1. приведен код класса modCls.
Листинг 16.1. Код класса modCls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
 
namespace P16_1
{
 
    public class modCls : Microsoft.Xna.Framework.DrawableGameComponent
    {
        //Модель
        public Model myModel;
        //Мировая матрица, матрицы вида и проекции
        public Matrix WorldMatrix;
        public Matrix ViewMatrix;
        public Matrix ProjectMatrix;
        //Соотношение сторон экрана
        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 Draw(GameTime gameTime)
        {
 
            foreach (ModelMesh mesh in myModel.Meshes)
            {
                //Для каждого эффекта в сети
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //Установить освещение по умолчанию
                    effect.LightingEnabled = true;
                    effect.EnableDefaultLighting();
                    //установить матрицы
                    effect.World = WorldMatrix;
                    effect.View = ViewMatrix;
                    effect.Projection = ProjectMatrix;
                }
                mesh.Draw();
            }
 
           base.Draw(gameTime);
        }
    }
}

 


В листинге 16.2. вы можете видеть код класса Game1.

Листинг 16.2. Код класса Game1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace P16_1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        //Матрицы
        Matrix viewMatrix;
        Matrix projMatrix;
        //Модели
        Model ball, ball2;
        // Позиция объекта, поворот
        Vector3 avatarPosition = new Vector3(0, 0, -10);
        float avatarlRotation;
 
        // Положение камеры
        Vector3 cameraReference = new Vector3(0, 0, 10);
        Vector3 thirdPersonReference = new Vector3(0, 200, -200);
 
        // Скорости поворота и движения
        float rotationSpeed = 1f / 60f;
        float forwardSpeed = 10f / 60f;
 
        //Поле зрения камеры
        float viewAngle = MathHelper.ToRadians(45.0f);
 
        //Расстояние от камеры до переднего и заднего плана
        float nearClip = 1.0f;
        float farClip = 2000.0f;
        //Массив моделей сцены
        modCls[] cls;
        //Игровой объект
        modCls ballObj;
 
        //Соотношение сторон экрана
        float aspectRatio;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
 
        }
 
        protected override void LoadContent()
        {
            //Загрузка моделей
            ball = Content.Load<Model>("ball");
            ball2 = Content.Load<Model>("ball2");
            aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /
  (float)graphics.GraphicsDevice.Viewport.Height;
            cls = new modCls[25];
        }
 
        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;
                //До тех пор, пока объект сталкивается
                //с другим объектом - изменять его положение
                //в направлении, противоположном перемещению
                //вызвавшему столкновение
                while (IsCollide())
                {
                    avatarPosition.Z -= v.Z/10;
                    avatarPosition.X -= v.X/10;
                }
            }
            //Движение назад
            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;
                while (IsCollide())
                {
                    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;
                while (IsCollide())
                {
                    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;
                while (IsCollide())
                {
                    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);
        }
        //Логическая функция, проверяющая столкновение игрового объекта и
        //объектов сцены
        bool IsCollide()
        {
            //Для объекта BoundingSphere, соответствующего
            //текущему объекту сцены 
            BoundingSphere b1;
            //Получить BoundingSpherer для игрового объекта
            BoundingSphere b = ball.Meshes[0].BoundingSphere;
            //Установить центр сферы в соответствии с положением
            //игрового объекта
            b.Center = avatarPosition;
            //Переменная для хранения вектора размера модели
            Vector3 scale;
            //Переменная для хранения информации о повороте модели
            Quaternion rotation;
            //Переменая для хранения информации о позиции модели
            Vector3 translation;
            //Цикл обхода объектов сцены
            for (int i = 0; i < 25; i++)
            {
                //Получить BoundingSphere для текущего объекта
                b1 = cls[i].myModel.Meshes[0].BoundingSphere;
                //Получить параметры - размер, поворот, позицию для объекта
                cls[i].WorldMatrix.Decompose(out scale, out rotation, out translation);
                //Установить центр сферы в соответствии с позицией объекта
                b1.Center = translation;
                //Если сферы игрового объекта и текущего объекта
                if (b1.Intersects(b))
                {
                    //Выведем в заголовок окна слово Collision!
                   //Возвратим True
                   this.Window.Title = "Collision!";
                   return true;
                }
            }
            //Если выполняется этот код - 
            //столкновения не было
            //выведем в окно программы соответствующее сообщение
            //и вернем false
            this.Window.Title = "No collision";
                return false;
        }
 
        //Вывод объектов сцены
        void DrawScene()
        {
            //очистить коллекцию компонентов
            Components.Clear();
            //Счетчик для элементов массива
            int i = 0;
            //Вывести шары, расположенные в пять рядов
            //по пять штук
            for (int x = 0; x < 5; x++)
            {
                   for (int z = 0; z < 5; z++)
                    {
                        //Добавляем в массив новый объект
                        cls[i] = new modCls(this, ball2, graphics);
                        //Устанавливаем его свойства
                        cls[i].WorldMatrix = Matrix.CreateTranslation(x * 40f, 0, z * 40f);
                        cls[i].ViewMatrix = viewMatrix;
                        cls[i].ProjectMatrix = projMatrix;
                        //Добавляем в коллекцию компонентов
                        Components .Add (cls[i]);
                        i++;
                    }
            }
            //выведем игровой объект
            ballObj = new modCls(this, ball, graphics);
            ballObj.WorldMatrix = Matrix.CreateRotationY(avatarlRotation) * Matrix.CreateTranslation(avatarPosition);
            ballObj.ViewMatrix = viewMatrix;
            ballObj.ProjectMatrix = projMatrix;
            Components.Add(ballObj);
        }
    }
}

 


На рис. 16.2. вы можете видеть игровой экран проекта P16_1.


Рис. 16.2. Игровой экран проекта P16_1

Взаимодействие указателя мыши и трехмерных объектов, объекты Ray и Plane

Разработаем следующую простую компьютерную игру. На экране видны несколько объектов. Игрок должен не допустить падения объектов «на пол», щелкая по ним мышью. После каждого щелчка объект «взлетает», но потом снова начинает «падать».

Для реализации этого проекта нам понадобится обрабатывать взаимодействие указателя мыши и трехмерных объектов, то есть – объекта, который находится в двумерной системе координат и объекта, который находится в трехмерной системе. Первая сложность, которая возникает при обработке подобного взаимодействия заключается в том, что каждый из объектов находится в собственной системе координат – прежде чем переходить к каким-либо действиям, нужно найти способ сопоставить эти системы. Далее, после того, как найдено соответствие систем, нужно создать объект Ray, который используется для проверки попадания мышью по объекту.
В случае с созданием «пола», на который будут падать объекты – можно отметить, что для его моделирования можно воспользоваться объектом Plane, представляющей плоскость.

В основу нашего примера мы положим пример, размещенный в справочной системе XNA. Он строит луч, исходящий из позиции курсора мыши. После получения луча мы проверяем, пересекается ли он со сферой, ограничивающей объект и по результатам проверки проводим определенные действия.

Так же в этом примере мы рассмотрели работу со структурой Plane. Она представляет собой плоскость. Плоскость можно задать различными способами, мы использовали способ, при котором конструктору плоскости передаются три точки, через которые проходит плоскость.

На рис. 16.3. вы можете видеть окно ProjectExplorer проекта P16_2.


Рис. 16.3. Окно Project Explorer проекта P16_2

В листинге 16.3. вы можете видеть код класса modCls.

Листинг 16.3. Код класса modCls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
 
namespace P16_2
{
 
    public class modCls : Microsoft.Xna.Framework.DrawableGameComponent
    {
        //Модель
        public Model myModel;
        //Мировая матрица, матрицы вида и проекции
        public Matrix WorldMatrix;
        public Matrix ViewMatrix;
        public Matrix ProjectMatrix;
        //Соотношение сторон экрана
        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 Draw(GameTime gameTime)
        {
 
            foreach (ModelMesh mesh in myModel.Meshes)
            {
                //Для каждого эффекта в сети
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //Установить освещение по умолчанию
                    effect.LightingEnabled = true;
                    effect.EnableDefaultLighting();
                    //установить матрицы
                    effect.World = WorldMatrix;
                    effect.View = ViewMatrix;
                    effect.Projection = ProjectMatrix;
                }
                mesh.Draw();
            }
 
            base.Draw(gameTime);
        }
    }
}

 


В листинге 16.4. вы можете видеть код класса Game1.

Листинг 16.4. Код класса Game1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace P16_2
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        //Матрицы
        Matrix viewMatrix;
        Matrix projMatrix;
        //Модели
        modCls[] cls;
        //Положение моделей в пространстве
        Vector3 [] offset;
        //Соотношение сторон окна вывода
        float aspectRatio;
        //Плоскость
        modCls plane;
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            //Отобразим указатель мыши
            IsMouseVisible = true;
            base.Initialize();
        }
 
        protected override void LoadContent()
        {
            //Три элемента в массиве объектов
            cls = new modCls[3];
            //Три элемента в массиве положений объектов
            offset = new Vector3[3];
            //Зададим начальные положения моделей
            offset[0] = new Vector3(0, 2, 0);
            offset[1] = new Vector3(-6, 3, -4);
            offset[2] = new Vector3(6, 4, -6);
            //Создадим модели
            cls[0] = new modCls(this, Content.Load<Model>("ball2"), graphics);
            cls[1] = new modCls(this, Content.Load<Model>("ball2"), graphics);
            cls[2] = new modCls(this, Content.Load<Model>("ball2"), graphics);
            //Вычислим соотношение сторон
            aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /
                (float)graphics.GraphicsDevice.Viewport.Height;
            //Матрица вида
            viewMatrix = Matrix.CreateLookAt(new Vector3(0, 10, 15),
                new Vector3(0, 0, 0),
                new Vector3(0.0f, 1.0f, 0.0f));
            //Матрица проекции
            projMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),
                aspectRatio, 1.0f, 1000.0f);
            //Задаем параметры матриц каждой из моделей
            for (int i = 0; i < 3; i++)
            {
                cls[i].WorldMatrix = Matrix.CreateTranslation(offset[i]);
                cls[i].ProjectMatrix = projMatrix;
                cls[i].ViewMatrix = viewMatrix;
                Components.Add(cls[i]);
            }
            //Создаем плоскость
            plane = new modCls(this, Content.Load<Model>("plane"), graphics);
            //Настраиваем параметры плоскости
            plane.WorldMatrix = Matrix.CreateScale(8) * Matrix.CreateRotationY(MathHelper.ToRadians(90)) *
    Matrix.CreateRotationZ(MathHelper.ToRadians(90)) *
    Matrix.CreateTranslation(0, -4, 0);
            plane.ViewMatrix = viewMatrix;
            plane.ProjectMatrix = projMatrix;
            Components.Add(plane);
        }
 
        protected override void Update(GameTime gameTime)
        {
            //В каждом проходе цикла
            //Смещаем каждую модель вниз на 0.04 единицы
            for (int i = 0; i < 3; i++)
            {
                offset[i].Y -= 0.04f;
                cls[i].WorldMatrix = Matrix.CreateTranslation(offset[i]);
            }
            //Проверяем попадание мыши по объекту
            CheckMouseClick();
            //Проверяем пересечение с плоскостью
            CheckPlane();
            base.Update(gameTime);
        }
 
        void CheckMouseClick()
        {
            //получим состояние мыши
            MouseState mouseState = Mouse.GetState();
            //если нажата левая кнопка
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                //Получим луч, идущий от позиции мыши на экране в пространство
                Ray pickRay = GetPickRay();
                //Переменная для хранения сферы, соответствующей объекту
                BoundingSphere b1;
                //Переменная для хранения вектора размера модели
                Vector3 scale;
                //Переменная для хранения информации о повороте модели
                Quaternion rotation;
                //Переменая для хранения информации о позиции модели
                Vector3 translation;
                for (int i = 0; i < 3; i++)
                {
                    //Получить BoundingSphere для текущего объекта
                    b1 = cls[i].myModel.Meshes[0].BoundingSphere;
                    //Получить параметры - размер, поворот, позицию для объекта
                    cls[i].WorldMatrix.Decompose(out scale, out rotation, out translation);
                    //Установить центр сферы в соответствии с позицией объекта
                    b1.Center = translation;
                    //Получить результат пересечения луча и сферы
                    Nullable<float> result = pickRay.Intersects(b1);
                    //Если луч и сфера пересеклись - "поднять" объект до позиции Y=4
                    if (result .HasValue)
                    {
                        offset[i].Y = 4;
                        cls[i].WorldMatrix = Matrix.CreateTranslation(offset[i]);
                    }
                }
 
 
            }
        }
        //Проверка на столкновение с плоскостью
        void CheckPlane()
        {
                //Создадим плоскость по трем точкам - она пересекает ось Y в точке -4 и не пересекает
                //другие оси
                Plane pl = new Plane(new Vector3(0, -4, 0), new Vector3(2, -4, 1), new Vector3(-1, -4, -2));
                //Переменная для хранения типа пересечения с плоскостью
                //Она может сигнализировать о нахождении объекта перед плоскостью (выше в нашем случае)
                //за плоскостью и о пересечении с плоскостью
                PlaneIntersectionType plType;
                //Сфера для объекта
                BoundingSphere b1;
                //Переменная для хранения вектора размера модели
                Vector3 scale;
                //Переменная для хранения информации о повороте модели
                Quaternion rotation;
                //Переменая для хранения информации о позиции модели
                Vector3 translation;
                for (int i = 0; i < 3; i++)
                {
                    //Получить BoundingSphere для текущего объекта
                    b1 = cls[i].myModel.Meshes[0].BoundingSphere;
                    //Получить параметры - размер, поворот, позицию для объекта
                    cls[i].WorldMatrix.Decompose(out scale, out rotation, out translation);
                    //Установить центр сферы в соответствии с позицией объекта
                    b1.Center = translation;
                    //Получить тип пересечения сферы объекта и плоскости
                   plType =pl.Intersects(b1);
                    //Если сфера пересекла плоскость
                   if (plType == PlaneIntersectionType .Intersecting)
                   {
                       //Удалить соответствующий игровой объект из коллекции
                       Components.Remove(cls[i]);
                    }
                }
 
        }
        //Функция для вычисления луча, исходящего из точки, в которой
        //находился указатель мыши в момент щелчка
        Ray GetPickRay()
        {
            //получить состояние мыши
            MouseState mouseState = Mouse.GetState();
            //Сохранить координаты
            int mouseX = mouseState.X;
            int mouseY = mouseState.Y;
            //Точки для вычисления направления луча - одна, соответствующая координате мыши
            //вторая - направленная по оси Z
            Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f);
            Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f);
            //Мировая матрица для вычислений
            Matrix world = Matrix.CreateTranslation(0, 0, 0);
            //Переведем координаты мыши в координаты трехмерного пространства
            Vector3 nearPoint = graphics.GraphicsDevice.Viewport.Unproject(nearsource, projMatrix, viewMatrix, world);
            Vector3 farPoint = graphics.GraphicsDevice.Viewport.Unproject(farsource, projMatrix, viewMatrix, world);
            // Получим направление луча
            Vector3 direction = farPoint - nearPoint;
            //Нормализуем его (преобразуем к единичному вектору)
            direction.Normalize();
            //Создадим новый луч, начинающийся в точке, соответствующей координате
            //указателя мыши в объектном пространстве, с направлением, 
            //соответствующим вычисленному направлению
            Ray pickRay = new Ray(nearPoint, direction);
            //возвратим луч в процедуру, вызывавшую данную функцию
            return pickRay;
        }
 
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
 
            // TODO: Add your drawing code here
 
            base.Draw(gameTime);
        }
    }
}

 


На рис. 16.4. вы можете видеть игровое окно проекта P16_2.


Рис. 16.4. Игровое окно проекта P16_2

Вопросы

1) Объект BoundingSphere представляет собой
  • a. Прямоугольный «ящик» вокруг объекта
  • b. Сферу, в которой содержится объект
  • c. Плоскость в пространстве
  • d. Луч в пространстве
2) Объект BoundingBox представляет собой
  • a. Прямоугольный «ящик» вокруг объекта
  • b. Сферу, в которой содержится объект
  • c. Плоскость в пространстве
  • d. Луч в пространстве
3) Объект Plane представляет собой
  • a. Прямоугольный «ящик» вокруг объекта
  • b. Сферу, в которой содержится объект
  • c. Плоскость в пространстве
  • d. Луч в пространстве
4) Объект Ray представляет собой
  • a. Прямоугольный «ящик» вокруг объекта
  • b. Сферу, в которой содержится объект
  • c. Плоскость в пространстве
  • d. Луч в пространстве
5) Какой метод объекта типа BoundingSphere позволяет проверять его на пересечение с другими подходящими объектами?
  • a. Transform
  • b. ToString
  • c. Intersects
  • d. GetType
6) Какое свойство объекта типа BoundingSphere можно использовать для установки его позиции в пространстве?
  • a. Center
  • b. Radius
  • c. Value
  • d. Distance
7) При тестировании пересечения объекта типа Plane и объекта типа BoundingSphere получена переменная типа PlaneIntersectionType, содержащая значение Intersecting. Это значит, что
  • a. BoundingSphere находится перед плоскостью
  • b. BoundingSphere пересекает плоскость
  • c. BoundingSphere находится за плоскостью
8) При тестировании пересечения объекта типа Plane и объекта типа BoundingSphere получена переменная типа PlaneIntersectionType, содержащая значение Front. Это значит, что
  • a. BoundingSphere находится перед плоскостью
  • b. BoundingSphere пересекает плоскость
  • c. BoundingSphere находится за плоскостью
9) Метод Decompose объектов типа Matrix позволяет:
  • a. Уничтожить объект
  • b. Создать копию объекта
  • c. Извлечь из объекта информацию о его пространственных параметрах
  • d. Создать новый объект

Материал публикуется с разрешения авторов - Ю.В. Дашко, А.А. Заика

Студенческий блог MS Russia
Интернет-Университет Информационных технологий - курс разработан по гранту от Microsoft и ИНТУИТ
сайт ИУБиП
Комментарии
#1 | Hale_32bit 21.03.2010 22:31:50
Хм. Незнал что в XNA есть такие классы.
Ну да ладно. Свои всё равно лучше.
Smile
#2 | general 21.03.2010 22:54:35
а вот это еще бабка на двое сказала.
Добавить комментарий
Пожалуйста, залогиньтесь для добавления комментария.
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Авторизация
Логин

Пароль



Вы не зарегистрированы?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Мини-чат
Вы должны авторизироваться, чтобы добавить сообщение.

27.08.2014
Я умею немного на asp.net + html и css

22.08.2014
на ASP mvc 3 есть пару проектов. Могу помочь, если нужно. Обидно, если закроется Frown

21.08.2014
я тоже ноль

21.08.2014
Я в вебе только с php занимался да и то на уровне чтоб работало.

21.08.2014
Я в вебе полный ноль…

21.08.2014
Переводить его надо, хоть на ту же азуру. И двиг менять на что-то современное. Если есть веб-разрабы - можем скооперироваться. Один делать не буду.

21.08.2014
не знаю всех нюансов по оплате и все хорошее когда нибудь заканчивается

21.08.2014
А что случилось?

21.08.2014
похоже сайт будет работать до 28го числа

09.08.2014
Апи пока не видел. Но есть приложение в магазине Live Lock Screen BETA, так что думаю скоро будет

08.08.2014
Я про API для Update1. На нем работает это

08.08.2014
А что именно нужно? Чтото и сейчас открыто http://msdn.micro.
...105).aspx

06.08.2014
Кто-нибудь слышал об открытии доступа к Lock Screen Api?

31.07.2014
VPDExpress на базе MVS 2012, ни в какую не ловит исключения. Даже если их сам создаешь. И всех так?

25.07.2014
С днем системного администратора причастных к этой профессии! По случаю - тортик от жены

RSS каналы сайта
XNA - Новости
XNA - Статьи
XNA - Форум
XNA - Галерея
XNA - Файлы
Время загрузки: 0,05 секунд 8,709,548 уникальных посетителей