Возможно вы искали: 'Ishar 3: The Seven Gat...'

May 12 2025 01:23:27
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96030355
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18346
• Обзор The Walking ... 18789
• Обзор DMC: Devil M... 19864
• Обзор на игру Valk... 15867
• Обзор на игру Stars! 17754
• Обзор на Far Cry 3 17935
• Обзор на Resident ... 16012
• Обзор на Chivalry:... 17495
• Обзор на игру Kerb... 17970
• Обзор игры 007: Fr... 16604
Превью о играх
• Превью к игре Comp... 17946
• Превью о игре Mage... 14451
• Превью Incredible ... 14706
• Превью Firefall 13462
• Превью Dead Space 3 16325
• Превью о игре SimC... 14717
• Превью к игре Fuse 15432
• Превью Red Orche... 15532
• Превью Gothic 3 16334
• Превью Black & W... 17345
Главная » Статьи » Всё о XNA » Уровни в играх

Уровни в играх

В предыдущих работах мы занимались созданием примеров компьютерных игр, которые состояли из одного игрового уровня. Реальные же игры обычно состоят из нескольких уровней. В этой лабораторной работе мы займемся разработкой многоуровневых игр и вопросами, связанными с созданием конструктора игровых уровней.

Цель работы

  • Научиться создавать многоуровневые игры

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

  • Создать игру, игровой процесс которой делится на несколько уровней
  • Разработать конструктор уровней

Организация многоуровневой игры

В рамках этой лабораторной работы мы создадим игру – клон популярной игры Arkanoid. Наша игра будет обладать следующим набором характеристик.

  1. Имеется 2 вида блоков – один из них уничтожается при попадании в него мяча, причем, мяч отскакивает, второй – не уничтожается.
  2. При уничтожении всех блоков текущего уровня осуществляется переход на следующий уровень.
  3. Ппосле того, как мяч выйдет за пределы поля – игра окончится и произойдет загрузка первого уровня.
  4. Игрок может играть в стандартном режиме и в режиме пользовательского уровня. Пользовательский уровень создается игроком самостоятельно с помощью конструктора уровней.


Здесь мы создадим каркас игры и конструктор уровней для создания пользовательских уровней.
Создадим новый проект – P11_1. На рис. 11.1. вы можете видеть окно Project Explorer этого проекта.


Рис. 11.1. Окно Project Explorer для проекта P11_1

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

Классы Ball, Bat, Brick1, Brick2 – это игровые компоненты, соответственно, для мяча (Ball), биты (Bat), и двух видов блоков – обычного, который уничтожается при попадании в него мяча (Brick1), и неуничтожимого (Brick2).
Класс BrickBuilder используется для создания указателя, который применяется в конструкторе уровней.

На рис. 11.2. вы можете видеть изображения графических ресурсов, примененных в игре.


Рис. 11.2. Игровые ресурсы

Изображения BrickBuild используются в конструкторе уровней. Указатель с изображением BrickBuild0.png очищает ячейку игрового поля, расположенную под ней. Указатель с BrickBuild1.png устанавливает в текущую позицию игрового поля объект Brick1, указатель с изображением BrickBuild2.png устанавливает в текущую ячейку объект Brick2.

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


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

На рис. 11.4 представлен экран в режиме конструктора уровней.


Рис. 11.4. Конструктор уровней

Рассмотрим коды классов, которые используются в игре.

В листинге 11.1. приведен код класса Game1.

Листинг 11.1. Код класса 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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
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 P11_1
{
 
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //Текстуры
        Texture2D txtBack, txtBrick1, txtBrick2, txtBat, txtBall;
        Texture2D txtBrBuild1, txtBrBuild2, txtBrBuild0;
        //Массивы для хранения данных об уровнях
        public byte[,] Layer1, Layer2, Layer3, UserLayer;
        //Прямоугольник для фона
        Rectangle recBack = new Rectangle(0, 0, 512, 640);
        //Прямоугольник для "блока"
        Rectangle recBrick = new Rectangle(0, 0, 64, 16);
        //Прямоугольник для "мяча"
        Rectangle recBall = new Rectangle(0, 0, 10, 10);
        //Прямоугольник для биты
        Rectangle recBat = new Rectangle(0, 0, 96, 16);
        //Номер текущего уровня
        //1 - первый
        //2 - второй
        //3 - третий
        //-1 - пользовательский
        int currentLayer;
        //Установлена в false, если программа находится в 
        //режиме игры, при установке в True включается режим конструктора
        bool IsBuild;
        //Позиция указателя в режиме конструктора
        Vector2 PositionBuild;
        //Тип блока, который будет добавлен на игровое поле
        //при нажатии соответствующей клавиши в режиме конструктора
        byte typeOfBuildBlock;
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
 
        protected override void Initialize()
        {
            //Программа находится в игровом режиме
            IsBuild = false;
            //Позиция для указателя в режиме конструктора (0,0)
            PositionBuild = new Vector2(0, 0);
            //Тип блока по умолчанию в режиме конструктора - 1
            typeOfBuildBlock = 1;
            //пользовательский уровень по умолчанию пуст - ячейки
            //заполнены нулями
            UserLayer = new byte[40, 8]; 
            //Заполняем массивы для разных уровней
            //0 - пустая ячейка
            //1 - блок первого типа (уничтожимый)
            //2 - блок второго типа (неуничтожимый)
            Layer1 = new byte[40, 8]{
            {1,1,1,1,1,1,1,1},
            {0,1,0,1,0,1,0,1},
            {1,0,1,0,1,0,1,0},
            {0,1,0,1,0,1,0,1},
            {1,0,1,0,1,0,1,0},
            {0,1,0,1,0,1,0,1},
            {0,0,0,0,0,0,0,0},
            {2,0,0,2,0,0,2,0},
            {0,1,0,0,0,0,0,1},
            {0,0,1,0,0,0,1,0},
            {0,0,0,1,0,1,0,0},
            {0,0,0,0,1,0,0,0},
            {1,1,1,1,1,1,1,1},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0}
            };
 
            Layer2 = new byte[40, 8]{
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,1,2,1,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0}
            };
 
            Layer3 = new byte[40, 8]{
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,1,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,1,0,1,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,2,0,1,0,2,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,1,0,0,0,1,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0}
            };
 
            //Текущий уровень - 1
            currentLayer = 1;
            //Устанавливаем разрешение игрового окна 640х512
            graphics.PreferredBackBufferWidth = 512;
            graphics.PreferredBackBufferHeight = 640;
            graphics.ApplyChanges();
            base.Initialize();
        }
 
        /// 
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// 
        protected override void LoadContent()
        {
            // Загружаем ресурсы
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), spriteBatch);
            txtBack = Content.Load<Texture2D>("Back");
            txtBrick1 = Content.Load<Texture2D>("Brick1");
            txtBrick2 = Content.Load<Texture2D>("Brick2");
            txtBall = Content.Load<Texture2D>("Ball");
            txtBat = Content.Load<Texture2D>("Bat");
            txtBrBuild0 = Content.Load<Texture2D>("BrickBuild0");
            txtBrBuild1 = Content.Load<Texture2D>("BrickBuild1");
            txtBrBuild2 = Content.Load<Texture2D>("BrickBuild2");
            //Создаем уровень
            AddSprites(Layer1);
            //Добавляем биту и мяч
            addBallAndBAts();
 
        }
        //Процедура создания уровня
        //расставляет элементы в соответствии с массивом
        void AddSprites(byte [,] RenderLayer)
        {
            //Просматриваем массив
            for (int i = 0; i < 40; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    if (RenderLayer[i, j] == 1)
                        Components.Add(new Brick1(this, ref txtBrick1, new Vector2(j, i), recBrick, 64, 16));
                    if (RenderLayer[i, j] == 2)
                        Components.Add(new Brick2(this, ref txtBrick2, new Vector2(j, i), recBrick, 64, 16));
                }
            }
        }
        //Процедура для установки биты и мяча
        void addBallAndBAts()
        {
            Components.Add(new Ball(this, ref txtBall, new Vector2(300, 550), recBall, 1, 1));
            Components.Add(new Bat(this, ref txtBat, new Vector2(300, (640 - 16)), recBat, 1, 1));
        }
 
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
 
        protected override void Update(GameTime gameTime)
        {
            //получим состояние клавиатуры
            KeyboardState kb = Keyboard.GetState();
            //если IsBuild = false и нажата клавиша A
            //переходим в режим конструктора уровней
            if (kb.IsKeyDown (Keys .A)&!IsBuild)
            {
                IsBuild = true;
                builder();
            }
            //Если находимся в режиме конструктора уровней
            if (IsBuild)
            {
                //При нажатой клавише "вверх" уменьшить текущую позицию Y
                //указателя на 1 если позиция больше 0
                if (kb.IsKeyDown(Keys.Up))
                {
                    if (PositionBuild.Y > 0) PositionBuild.Y--;
                }
                //При нажатой клавише "вниз" увеличить позицию
                //Y если она меньше 39
                if (kb.IsKeyDown(Keys.Down))
                {
                    if (PositionBuild.Y < 39) PositionBuild.Y++;
                }
                //При нажатой клавише "влево"
                //уменьшить позицию X если текущая позиция
                //больше 0
                if (kb.IsKeyDown(Keys.Left))
                {
                    if (PositionBuild.X >0) PositionBuild.X--;
                }
                //При нажатой клавише "вправо"
                //увеличить позицию X если текущая позиция меньше 7
                if (kb.IsKeyDown(Keys.Right))
                {
                    if (PositionBuild.X < 7) PositionBuild.X++;
                }
                //Нажатие клавиши Z устанавливает тип блока в 0
                //этот блок предназначен для "стирания"
                //других блоков, то есть - для установки элемента 
                //массива, соответствующего текущему состоянию 
                //конструируемого уровня, в 0
                if (kb.IsKeyDown(Keys.Z))
                {
                    typeOfBuildBlock = 0;
                }
                //При нажатии клавиши X установим 1-й тип блока
                if (kb.IsKeyDown(Keys.X))
                {
                    typeOfBuildBlock = 1;
                }
                //При нажатии клавиши С установим 2-й тип блока
                if (kb.IsKeyDown(Keys.C))
                {
                    typeOfBuildBlock = 2;
                }
                //При нажатии клавиши W запишем в 
                //ячейку массива, соответствующую позиции указателя
                //текущий тип блока
                                if (kb.IsKeyDown (Keys .W ))
                {
                     UserLayer[(int)PositionBuild.Y, (int)PositionBuild.X] = typeOfBuildBlock; 
                }
                    //очищаем массив компонентов
                    Components.Clear();
                //выводим пользовательский уровень
                    AddSprites(UserLayer);
                //уничтожаем указатель и изменяем его в соответствии с типом выбранного блока
                    BrickBuilder br = null;
                    if (typeOfBuildBlock == 1)
                        br = new BrickBuilder(this, ref txtBrBuild1, PositionBuild, recBrick, 64, 16);
                    if (typeOfBuildBlock == 2)
                        br = new BrickBuilder(this, ref txtBrBuild2, PositionBuild, recBrick, 64, 16);
                    if (typeOfBuildBlock == 0)
                        br = new BrickBuilder(this, ref txtBrBuild0, PositionBuild, recBrick, 64, 16);
                    Components.Add(br);
                    //При нажатии клавиши W
                    //отключаем режим конструктора
                    //выводим пользовательский уровень и начинаем игру
                    if (kb.IsKeyDown(Keys.E))
                    {
                        IsBuild = false;
                        Components.Clear();
                        AddSprites(UserLayer);
                        addBallAndBAts();
                        currentLayer = -1;
                    }
            }
            //Если находимся в режиме игры
            //проверим - завершен ли текущий уровень
            //признак завершения уровня
 
            if (!IsBuild)
            {
                IsLayerCompleted();
            }
            base.Update(gameTime);
        }
        //Процедура старта конструктора уровней
        //очищаем набор компонентов Создаем и выводим указатель
        public void builder()
        {
            Components.Clear();
            BrickBuilder br = new BrickBuilder (this, ref txtBrBuild1,PositionBuild, recBrick, 64, 16);
            Components.Add(br);
        }
 
        //Процедура проверки на завершенность текущего уровня
        //Если на поле отсутствует мяч - игра начинается сначала
        //если на поле нет ни одного блока типа Brick1 - 
        //переход на следующий уровень или переход на первый уровень
        //с выводом надписи "Вы выиграли"
 
        public void IsLayerCompleted()
        {
            //Предположим, что на поле нет ни одного блока
            //типа Brick1
            bool f = false;
            //Предположим, что на поле нет мяча
            bool Ball = false;
            foreach (gBaseClass spr in this.Components)
            {
                //Если найден хотя бы один блок типа 1
                //установим F в True
                if (spr.GetType() == (typeof(Brick1)))
                {
                    f = true;
                }
                //Если найден мяч - установим Ball в True
                if (spr.GetType() == (typeof(Ball)))
                {
                    Ball = true;
                }
            }
            //Если мяч не обнаружен игра начинается сначала
            if (!Ball)
            {
                Components.Clear();
                currentLayer = 1;
                AddSprites(Layer1);
                addBallAndBAts();
             }
                //иначе
            else
            {
                //Если не было найдено ни одного блока типа Brick1
                if (!f)
                {
                    //Очистим набор компонентов
                    Components.Clear();
                    //Увеличим номер уровня
                    currentLayer++;
                    //в зависимости от номера
                    //запустим соответствующий уровень
                    if (currentLayer == 2)
                    {
                        AddSprites(Layer2);
                        addBallAndBAts();
                    }
                    if (currentLayer == 3)
                    {
                        AddSprites(Layer3);
                        addBallAndBAts();
                    }
                    //4 - если был пройден 3-й уровень
                    //0 - при прохождении пользовательского уровня
                    if (currentLayer == 4 | currentLayer == 0)
                    {
                        currentLayer = 1;
                        AddSprites(Layer1);
                        addBallAndBAts();
                        this.Window.Title = "Вы выиграли!";
                    }
                }
            }
        }
 
        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();
            //выведем фоновое изображение
            spriteBatch.Draw(txtBack, recBack, Color.White);
            //Выведем игровые объекты
            base.Draw(gameTime);
            spriteBatch.End();
        }
    }
}
Листинг 11.2. Код класса gBaseClass
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
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 P11_1
{
    public class gBaseClass : Microsoft.Xna.Framework.DrawableGameComponent
    {
        Texture2D sprTexture;
        public Vector2 sprPosition;
        public Rectangle sprRectangle;
        public gBaseClass(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int X_Coord, int Y_Coord)
            : base(game)
        {
            sprTexture = _sprTexture;
            //Здесь производится перевод индекса элемента массива
            //в координаты на игровом экране
            //Так как спрайты имеют различные размеры, для их размещения на экране
            //используются коэффициенты X_Coord и Y_Coord
            sprPosition.X = _sprPosition.X * X_Coord;
            sprPosition.Y = _sprPosition.Y * Y_Coord;
            sprRectangle = _sprRectangle;
        }
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch sprBatch =
                (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            sprBatch.Draw(sprTexture, sprPosition, Color.White);
            base.Draw(gameTime);
        }
    }
}

В листинге 11.3. приведен код класса Bat. Он занимается обработкой перемещений биты по горизонтали и контролем за пересечением битой левой и правой границ экрана.

Листинг 11.3. Код класса Bat
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 P11_1
{
    public class Bat : gBaseClass
    {
        Rectangle scrBounds;
        //True для движения биты влево и False - вправо
        public bool direction;
 
        public Bat(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            scrBounds = new Rectangle(0, 0,
              game.Window.ClientBounds.Width,
              game.Window.ClientBounds.Height);
            direction = true;
        }
 
        public override void Update(GameTime gameTime)
        {
            //Нажатия клавиш-стрелок влево и вправо
            //вызывают перемещение объекта в соответствующем направлении
            KeyboardState kb = Keyboard.GetState();
            if (kb.IsKeyDown(Keys.Left))
            {
                sprPosition.X -= 2;
                direction = true;
            }
            if (kb.IsKeyDown(Keys.Right))
            {
                sprPosition.X += 2;
                direction = false;
            }
            //проверка на столкновение с границами экрана
            Check();
 
            base.Update(gameTime);
        }
        //Процедура проверки столкновения с левой
        //и правой границами экрана
        void Check()
        {
            if (sprPosition.X < scrBounds.Left)
            {
                sprPosition.X = scrBounds.Left;
 
            }
            if (sprPosition.X > scrBounds.Width - sprRectangle.Width)
            {
                sprPosition.X = scrBounds.Width - sprRectangle.Width;
 
            }
        }
    }
}

 

В листинге 11.4. вы можете видеть код класса Ball. Этот класс отвечает за перемещение мяча и за обработку столкновений мяча и других объектов.

Листинг 11.4. Код класса Ball
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
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 P11_1
{
    public class Ball : gBaseClass
    {
        //для хранения границ экрана
        Rectangle scrBounds;
        //скорость мяча
        public Vector2 speed;
        Random rand = new Random();
        public Ball(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            speed = new Vector2(1, -1);
            scrBounds = new Rectangle(0, 0,
              game.Window.ClientBounds.Width,
              game.Window.ClientBounds.Height);
        }
 
 
        //Проверка на столкновение с границами экрана
        void Check()
        {
            if (sprPosition.X < scrBounds.Left)
            {
                sprPosition.X = scrBounds.Left;
                RandomiseSpeed();
                speed.X *= -1;
            }
            if (sprPosition.X > scrBounds.Width - sprRectangle.Width)
            {
                sprPosition.X = scrBounds.Width - sprRectangle.Width;
                RandomiseSpeed();
                speed.X *= -1;
            }
            if (sprPosition.Y < scrBounds.Top)
            {
                sprPosition.Y = scrBounds.Top;
                RandomiseSpeed();
                speed.Y *= -1;
            }
            if (sprPosition.Y > scrBounds.Height - sprRectangle.Height)
            {
                this.Dispose();
            }
 
        }
 
        //Проверка на столкновение с объектом
        bool IsCollideWithObject(gBaseClass spr)
        {
            return (this.sprPosition.X + this.sprRectangle.Width > spr.sprPosition.X &&
                        this.sprPosition.X < spr.sprPosition.X + spr.sprRectangle.Width &&
                        this.sprPosition.Y + this.sprRectangle.Height > spr.sprPosition.Y &&
                        this.sprPosition.Y < spr.sprPosition.Y + spr.sprRectangle.Height);
 
 
        }
        //Процедуры случайного изменения скорости при контакте с объектами
        //Для всех объектов - скорость может либо возрасти, либо упасть
        void RandomiseSpeed()
        {
            speed.Y += (float)((rand.NextDouble() - rand.NextDouble())*0.2 );
            speed.X += (float)((rand.NextDouble() - rand.NextDouble())*0.2 );
        }
        //Для объектов типа Brick1 скорость лишь растет
        void RandomiseSpeedB1()
        {
            speed.Y += (float)(0.3*Math.Sign(speed.Y) * Math.Abs(((rand.NextDouble() - rand.NextDouble()))));
            speed.X += (float)(0.3*Math.Sign(speed.X) * Math.Abs(((rand.NextDouble() - rand.NextDouble()))));
        }
        //Проверка на столкновения
       public void IsCollide()
        {
            gBaseClass FindObj=null;
            Bat FindedBat;          
            foreach (gBaseClass spr in Game.Components)
            {
                    if (IsCollideWithObject(spr))
                    {
                        //Если столкнулись с блоком Brick1
                        if (spr.GetType() == (typeof(Brick1)))
                        {
                            //сохраним найденный объект
                            FindObj = spr;
                            //Изменим скорость
                            RandomiseSpeedB1();
                            //Обратим скорость
                            speed *= -1;
                        }
                        //Если столкнулись с блоком 2
                        //обращаем скорость
                        if (spr.GetType() == (typeof(Brick2)))
                        {
                            speed *= -1;
                        }
                        //если столкнулись с битой
                        if (spr.GetType() == (typeof(Bat)))
                        {
                            FindedBat =(Bat) spr;
                            RandomiseSpeed();
                            //Если бита двигалась влево
                            //Мяч отразится от нее влево
                            if (FindedBat.direction)
                            {
                                speed.Y = Math.Abs(speed.Y);
                                speed.X = Math.Abs(speed.X);
                                speed *= -1;
                            }
                            //Если двигалась вправо
                            //отразится вправо
                            else
                            {
                                speed.Y = Math.Abs(speed.Y);
                                speed.X = Math.Abs(speed.X);
                                speed.Y *= -1;
                            }
 
 
                        }
 
                    }
            }
            //Если был найден блок Block1
            if (FindObj != null)
            {
               //Уничтожить его
                FindObj.Dispose();
                FindObj = null;
            }
        }
 
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            //Переместить мяч в соответствии со скоростью
            this.sprPosition += this.speed;
            //Ограничить скорость мяча 1.5 пикселями
            if (speed.Y > 2) speed.Y = (float)2;
            if (speed.Y < -2) speed.Y = (float)-2;
            if (speed.X > 2) speed.X = (float)2;
            if (speed.X < -2) speed.X = (float)-2;
            //Проверить столкновение с границами
            Check();
            //проверить столкновение с объектами
            IsCollide();
            base.Update(gameTime);
        }
    }
}

 


Листинг 11.5. содержит коды классов Brick1, Brick2 и BrickBuilder. Эти классы наследованы от gBaseClass и не вносят в его функциональность никаких дополнений.


Листинг 11.5. Коды классов Brick1, Brick2 и BrickBuilder
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
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 P11_1
{
    public class Brick1 : gBaseClass
    {
        public Brick1(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            // TODO: Construct any child components here
        }
    }
 
    public class Brick2 : gBaseClass
    {
        public Brick2(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            // TODO: Construct any child components here
        }
    }
 
    public class BrickBuilder : gBaseClass
    {
        public BrickBuilder(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            // TODO: Construct any child components here
        }
    }
}


Выводы

В этой лабораторной работе мы создали игру, предусматривающую несколько игровых уровней и конструктор уровней для пользователя. Как правило, разработка реальных игр включает в себя создание конструктора уровней, с помощью которого разработчик создает игровые уровни. Этот конструктор можно включить в поставку игры, предоставив пользователю возможность самостоятельно создавать новые уровни к игре. Конструкторы уровней так же разнообразны, как сами игры.

Задание

В этой лабораторной работе мы создали макет игры, допускающей использование нескольких уровней и содержащей конструктор уровней. Доработайте этот макет. А именно, выполните следующие улучшения исходного проекта:

  1. Переработайте процедуры обработки столкновений мяча с блоками. Мяч должен отскакивать от блоков точно так же, как он отскакивает от границ экрана.
  2. Создайте интерфейс игры – меню, системусправки.
  3. Предусмотрите сохранение пользовательского уровня в файл (с помощью сериализации специально созданного объекта) и загрузку его из файла.
  4. Создайте систему подсчета очков, предусмотрите сохранение данных о набранных очках в файле.
  5. Улучшите процесс прохождения игры – разработайте дополнительные уровни, сделайте игровой процесс разнообразнее, разработав бонусные объекты, которые появляются при уничтожении некоторых из блоков. Игрок должен «поймать» бонусный объект битой для того, чтобы активировать соответствующий бонус.

 



1271 Прочтений •  [Уровни в играх] [08.08.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• Уровни в играх Ukraine Vova 08.08.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка