Реферат: Створення гри типу DOOM, Wolf 3D

Створення гри типу DOOM, Wolf3D

План

1.   Створенняпростого тривимірного зображення кадру гри. Основи.

2.   Методвизначення швидкості роботи гри.

3.   Додатковіможливості.


Системарозробки: Pentium 150Mhz, 32M RAM, 1G HDD, S3 SVGA, Borland C++ 3.1

Мета: Створити гру, що зовнішньо схожа на  Wolfenstein 3D

Методы: Гра створена за методом, що зветься Ray Casting (проведення променя) — процес зображеннятривимірного світу за двовимірною інформацією. Ось основні принципи цьогометоду:

1. На основі двовимірної карти, що схожа на папір в клітинку, будуєтьсялабіринт, що складається з замальованих та чистих клітинок.

/>

2. Мапа створена з квадратів фіксованого розміру (в нашому випадку — 64 x 64), що дозволяє кожному об’єкту (гравцю) пересуватисяна 64 одиниці в будь-якому напрямі до переходу на інший квадрат. Весь лабіринтскладається з таких квадратів, що утворюють двовимірний масив.

3. Гравець визначається як місце на цій мапі, що має три характеристики:

· координату X

· координату Y

· кут зору

/>

4.  Так як ми знаємо,де знаходиться гравець та те, в який бік він дивиться, ми можемо взнати, що вінбачить в цей момент. Для початку нам треба вирішити яке поле зору має гравець.Нехай це буде 60°,для того щоб зображення було найбільш реалістичним. Це значить, що гравець будебачити всі предмети та стіни на 30° ліворуч та на 30° праворуч.

          0     1     2     3      4     5     6     7     8     9    10   11   12   13   14   15

/>/>

5. Тепер ми отримали поле зору, що включає в себе стіни попереду гравцяпри данному куті зору.

6. Ось що має бачити гравець в цьому випадку.

/>

7. Так як же все ж таки отримати таке тривимірне зображення з двовимірноїмапи? Просто вираховуючи висоту стін як функцію від відстані. Маючи поточнікоординати гравця, координати стіни та, використовуючи тригонометрію, ми можемовизначити відстань між гравцем та стіною. Проблема в тому, щоб виконати всі цірозрахунки настільки швидко, щоб гра виглядала реалістично. Але цим мизаймемося пізніше. Зараз нехай спрацює простий метод визначення відстані достіни. При цьому потрібно пам’ятати, що ми проводимо промінь для кожногостовпчика пікселей екрану, що для режиму VGA 13h (320x200x256) дає нам 320 стовпчиків по 200 пікселів. Тобто, 320променів буде проведено щоб намалювати 1 кадр.

8. Почнемо з заповнення початкових значень для гравця. Як ми вже сказали,кожний квадрат має розміри 64x64одиниці. Нехай гравець стоїть в клітинці (1, 1) десь на ¾ клітинки згорита на ¼ клітинки зліва. Значить координати гравця десь приблизно (80,112) (64 + 64 * ¼, 64 + 64 * ¾). Початковий кут зору буде 0°. Так як ми будемо використовуватитригонометричні функції з бібліотеки <math.h>мови C, ми будемо використовуватикоординатну систему, де кут збільшується за годинниковою стрілкою.

/>

9. Тому, як було сказано в пункті 4, ми починаємо проводити промені від30° зліва віднашого кута зору (=0°) (або з 330°) до 30°справа від нашого кута зору (або до 30°). Можна побачити правильний трикутник від того місцяде стоїть гравець до точки з кутом 330°.

/>

/>;       />;       />;

10. Зараз ми можемо намалювати (вигадану) лінію від гравця до якої-небудьточки на куті 330°. Але наскільки ж довгою має бути ця лінія? Настільки, щоб можна буловизначити що ми натрапили на стіну або вийшли за межі нашого лабіринту. Нехайнаш лабіринт має розміри 10x8 (x*y). Тоді у нас 80 квадратів. Тоді максимальна ширина (довжина)нашого лабіринту —64 * 10 = 640 на 64 * 8 = 512. Максимальна відстань, на якунам потрібно пускати промінь — />, />, що дорівнює 819.5999 або820 одиниць. Що ж, 820 це максимальна відстань, на яку ми можемо пуститипромінь, переглядаючи по дорозі чи не натрапили ми на стіну або чи не вийшли миза межі лабіринту. Ми звели проведення променя до малювання лінії. А длямалювання лінії у нас є алгоритм Брезенхама. Нам треба тільки визначитикоординати кінцевих точок лінії. Якщо ми маємо початкові координати гравця (X, Y), тоді використаємо вирази для точок кола щоб взнати кінцевікоординати.

/>

/>

Використавши числа з пунктів 8 та 10 отримуємо:

/>

/>

що дає: />. Передавшипараметри (80, 112, 790, -298) в процедуру проведення лінії, що перевіряєзіткнення з стінами. Для кожної точки вздовж лінії ми визнячаємо координати нанашій карті так:

/>

Поглянувши знову на малюнок 1 ми бачимо що наше перше зіткнення з стіноювідбувається у клітинці (2, 0). Тепер визначимо відстань до цієї стіни. Назвемоточку перетину з стіною W, щобне сплутати її з точкою кінця відрізка. Відстань визначається так: />, />. З малюнку видно, що стіназнаходиться десь в (128, 128) в квадраті (2, 0) тому: />, з чого виплаває, що відстань= 50.596 або приблизно 51 одиниці. Знаючи відстань ми, заглянувши в таблицювисот, можемо взнати висоту стіни і намалювати одну горизонтальну лінію наекрані визначеної висоти. Продовжуємо цей процес для всіх колонок на екрані(320), де кожна колонка відповідає віддалі до стіни, і заповнюємо весь екран.Як ви мабуть і здогадуєтесь, ми не будемо зменшувати наш кут по цілому градусу,а по />° що дорівнює 0,1875°. 320 стовпчиків по 0,1875° дає />нашого поля зору.

Таблиця висот будується так: для кожної з можливих відстанейвисота=відстань/С, де С — коефіцієнт, що вибирається пробним шляхом.

Так ми малюємо один кадр нашої гри. Він залежить від двох параметрів — координат гравця та його кута зору.Змінюючи ці параметри та перемальовуючи екран знову можна отримати те що бачитьгравець з новими координатами та/або кутом зору. А самі зміни координат та кутавідбуваються в залежності від тих клавіш, що їх натиснув гракець на клавіатурі,або від перевування мишки. Чим більше кадрів малювати за одиницю часу, тимбільш плавною і реалістичною буде гра.

Коротше кажучи, ось основні кроки:

1.  Візьміть кут зоругравця і відніміть 30° від нього щоб отримати напрям першого променя.

2.  Вирахуйтекоординати кінцевої точки використовуючи початкові координати гравця, напрямпроменя та максимальну відстань, на яку проводиться промінь.

3.  Використовуючиалгоритм лінії Брезенхама, в кожній точці лінії перевіряти, чи не втикнулися мизі стіною і чи не вийшли ми за межі лабіринту. Якщо знайшли стіну, повернутикоординати (Wx, Wy) точки перетину.

4.  Використувуючикоординати грвця та координати перетину з стіною визначити відстань до стіни.

5.  Використувуючивідстань, визначити з таблиці висот висоту стіни яку треба намалювати.

6.  Додати 0,1875 докута проведення променя і знову пройти пункти 1-6 доки не намалюємо всі 320ліній екрану.

11. Описаний вище алгоритм дає більш-менш нормальний результат, але маєдекілька недоліків:

1.  Швидкість.Проведення 320 ліній для кожного кадру просто дуже повільно. На екрані можебути видно як перемальовується кожен кадр зліва направо.

2.  Перетини. Немаєпростого способу визначити з якою саме чистиною стіни перетнувся наш промінь, атому важко на стіни накласти текстуру.

Для точнішого визначення швидкості роботи описаного алгоритму (в кадрахза секунду), були написані відповідні процедури. Ось основна схема визначеннякількості кадрів за секунду.

long getTime() {

  return peek(0,0x46E)*65535+peek(0, 0x46C);

int TimeCounter=0;

void main(void) {

  longRememberTheTime=getTime();

  intFramesPerSecond=0;

  while (TRUE) {

    TimeCounter++;

    if(getTime()-RememberTheTime>=18) {

     FramesPerSecond=TimeCounter;

      TimeCounter=0;

     RememberTheTime=getTime();

    }

  }

}

Функція getTime() повертає поточний час у вигладідовгого цілого. Це число збільшується на одиницю приблизно 18 разів на секунду.TimeCounter показує скільки разів виконавсяцикл. У функції main() організованосновний цикл програми, що збільшує TimeCounter на одиницю. На початку роботи програми час, що повертаєтьсяфункцією GetTime запам’ятовується у змінній RememberTheTime. Але якщо в ході роботи циклупройшла 1 секунда, то FramesPerSecond буде мати значення кількості проходів циклу за секунду. Приумові що за один цикл програми малюється один кадр, то FramesPerSecond можна вважати кількістю кадрів засекунду.

А ось що можна зробити для покращення та прискорення цієї гри.

1.  В першу чергупотрібно звільнитися від чисел з точкою, що плаває. Використавши числа зфіксованою точкою ми прискоримо весь алгоритм. Число з фіксованою точкоюприблизно дорівнює числу з плаваючою точкою побітово зсунутим дещо вліво, щобзберігати дробову частину. a = long( (float)b<< 8). Такі числа можна складати та віднімати без перетворень. Щоб ділитита множити потрібно виконати побітові зсуви — (a >> 8) * (b >>8).

2.  По-друге,потрібно всі значення, які можна, вирахувати заздалегідь і помістити в змінніта масиви. Наприклад значення сінусів та косінусів можна занести в таблицю з360 елементів, що відповідають кожному з 360°.

3.  Накладаннятекстури відбувається за методом інтерполяції. Знаючи верхню та нижню точки,можна пройти в циклі по всім точкам від верхньої до нижньої і взнати відповідніточки в текстурі. Але більш докладнепояснення виходить за рамки даного документу.

4.  Робота змонстрами майже нічим не відрізняється від роботи з самим гравцем. Він маєкоординати свого положення і кут зору. Переміщується до гравця якщо має доситьенергії і стріляє через рандомізований проміжок часу. Якщо енергії недостатньо,втікає.


Список літератури

1. Lary Myers. Animation Construction Kit 3D

2. Sebastien Loisel. Zed3D. A compact reference for 3Dcomputer graphics.

3.  Дейв Робертс.Программирование игрушек. Основы.

4.  MarkFeldman. Brezenham’s Line and Circle Algorithms.

5.  SebastienLoisel. A tutorial for 2D and 3D vector and texture mapped graphics. Version0.60

6.  Chris.Egerter. Texture mapped polygons.

еще рефераты
Еще работы по информатике, программированию