Таблиця висот будується так: для кожної з можливих відстаней висота=відстань/С, де С — коефіцієнт, що вибирається пробним шляхом.
Так ми малюємо один кадр нашої гри. Він залежить від двох параметрів — координат гравця та його кута зору. Змінюючи ці параметри та перемальовуючи екран знову можна отримати те що бачить гравець з новими координатами та/або кутом зору. А самі зміни координат та кута відбуваються в залежності від тих клавіш, що їх натиснув гракець на клавіатурі, або від перевування мишки. Чим більше кадрів малювати за одиницю часу, тим більш плавною і реалістичною буде гра.
Коротше кажучи, ось основні кроки:
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) {
long RememberTheTime=getTime();
int FramesPerSecond=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 3D computer graphics.
3. Дейв Робертс. Программирование игрушек. Основы.
4. Mark Feldman. Brezenham’s Line and Circle Algoriths.
5. Sebastien Loisel. A tutorial for 2D and 3D vector and texture mapped graphics. Version 0.60
6. Chris. Egerter. Texture mapped polygons.