On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение
администратор




Сообщение: 300
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:19. Заголовок: РУКОВОДСТВО ПО СОЗДАНИЮ 3D-ИГР Дарк бейсик 3Д


РУКОВОДСТВО ПО СОЗДАНИЮ 3D-ИГР
I. ОСНОВЫ
1. Набор команд "sync"
Цель урока: познакомиться с командами обновления экрана DarkBASIC и уяснить их важность.
Давайте начнем урок с программы, которая рисует на экране 3D-сферу.

Sync On
Make Object Sphere 1,100
Do
Sync
Loop
А теперь объясним, как команды рисуют и выводят на экран сферу.
Sync on
Команда "Sync on" дает указание DarkBASIC обновить изображение на экране, когда будет вызвана команда "Sync". Вам не обойтись без этих команд ни в одной программе на DarkBASIC.
Make Object Sphere 1,100
Как и большинство команд DarkBASIC, "Make Object Sphere" очень легко понять - конечно, если вы знаете английский язык. Она дает указание DarkBASIC создать объект в форме сферы. А каково назначение двух цифр в конце команды? Первая цифра "1" обозначает номер объекта, который нужно ввести в программу. Числа в DarkBASIC выполняют ту же функцию, что и имена. Они сообщают программе, какой именно объект нужно переместить по экрану, изменить или, как в нашем случае, создать. Второе число, "100", - это радиус вашей сферы.
Do
Loop
Команды "Do" и "Loop" используются для создания в программе цикла. Любые команды, помещенные вами между "Do" и "Loop", будут выполняться непрерывно, пока, находясь в редакторе, вы не нажмете клавишу "ESC" или "F12". Почти во всех программах, которые вы напишите, будет подобный цикл. Обычно его называют "основным" или "игровым" циклом. В нашем случае мы вставили между "Do" и "Loop" команду "Sync".
Sync
"Sync" означает "синхронизировать" . Когда программа меняет положение объекта, значения нового положения записываются в память, но не влияют на изображение 3D-сцены. Если синхронизацию отключить, экран будет обновляться всякий раз, когда меняются какие-либо значения, а иногда он не будет обновляться вовсе. В результате ваша программа станет выполняться медленно, но может случиться так, что экран останется пустым. Команду "Sync" можно сравнить с занавесом в театре. Когда подходит время поменять что-либо на 3D-сцене, "занавес" опускается, "декорации" меняются, и команда "Sync" снова поднимает "занавес". Она, как правило, вызывается только один раз в конце основного цикла программы, но бывают исключения. Надеемся, что вы уяснили предназначение команды "Sync". Добавим теперь к ней команду "Sync Rate".
Let's complete our discussion of the sync command set with the addition of the "Sync Rate" command.
Sync On
Sync Rate 30
Make Object Sphere 1,100
Do
Sync
Loop
Команда "Sync Rate" позволяет установить постоянную частоту обновления экрана. Частота обновления - это то, сколько раз в секунду поднимается и опускается "занавес" перед вашей сценой. Постоянная частота обновления нужна для согласованности работы программы на разных компьютерах. Если на вашем компьютере экран обновляется со скоростью 40 кадров в секунду, то на более производительном компьютере вашего друга он может обновляться со скоростью 120 кадров в секунду, а это слишком быстро. Установив постоянную частоту обновления (в нашем примере - "30"), вы добьетесь того, что экран будет обновляться с одной и той же скоростью на всех компьютерах. Человеческий глаз устроен так, что способен воспринимать скорость обновления экрана до определенных пределов, поэтому если вы установите слишком большую частоту, то будете зря расходовать ресурсы компьютера. А если частота обновления окажется слишком низкой, то движения на экране будут прерывистыми и медленными. Есть одно исключение: частоту обновления можно установить равной "0". Тогда DarkBasic будет обновлять экран с максимально доступной скоростью.
Итак, мы познакомили вас с набором команд синхронизации. Теперь вы сами сможете установить частоту обновления экрана, понимая, как и когда это нужно делать. Вы также узнали простейшие команды DarkBASIC, которые работают с объектами. Попробуйте изменить или добавить в программу следующие команды. Также попробуйте поменять значения ширины, высоты и глубины и посмотрите, как они влияют на изображения создаваемых вами объектов. В команде "Make Object Triangle" задайте различные значения "x", "y" и "z" и посмотрите, какие удивительные треугольники у вас получатся. Убедитесь, что каждому объекту присвоен уникальный номер. Для этого вместо слов "Номер объекта" поставьте физическое число, соответствующее конкретному объекту. (Это относится ко всем случаям, где рядом с именем команды присутствуют слова "Номер объекта".)
MAKE OBJECT CUBE Номер объекта, Значение размера
MAKE OBJECT BOX Номер объекта, Ширина, Высота, Глубина
MAKE OBJECT CYLINDER Номер объекта, Значение размера
MAKE OBJECT CONE Номер объекта, Значение размера
MAKE OBJECT PLAIN Номер объекта, Значение ширины, Значение высоты
MAKE OBJECT TRIANGLE Номер объекта, X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3
2. Ввод данных с клавиатуры и преобразование объектов.
Цель урока: показать, как можно изменять положение объекта на экране с помощью клавиш.
Начнем урок с знакомства с командной "Rem" - прекрасным инструментом для создания собственных записей ("комментариев") в программе. Эта команда дает указание DarkBASIC пропускать все, что находится в строке после слова "Rem". Со временем ваши программы будут становиться все сложнее и сложнее, и вы будете тратить все больше времени на их написание, и вскоре начнете забывать, для чего предназначена та или иная переменная, и что именно делает тот или иной блок исходного кода. Именно для таких случаев служит команда "Rem" и вставленные комментарии, которые будут обо всем этом напоминать. Этот инструмент удобен также, если в процессе работы над проектом вы передаете исходный код своей программы коллегам и друзьями или когда одновременно работаете над несколькими разными проектами.
Rem Устанавливаем частоту обновления экрана
Sync On
Sync Rate 30
Rem Создаем сферу
Make object cube 1,100
Rem Основной цикл
Do
Rem Сохраним вертикальный угол (по оси Y) объекта в переменной aY#
aY# = Object angle Y(1)
Rem Управление вводом данных
If Upkey()=1 then Move object 1,2
If Leftkey()=1 then aY# = Wrapvalue(aY#+5)
If Rightkey()=1 then aY# = Wrapvalue(aY#-5)
Rem Вращаем сферу
Yrotate object 1,aY#
Rem Обновляем экран
Sync
Loop
Вы, вероятно, узнали часть кода из предыдущего урока. Не удивляйтесь, если в последующих уроках вам будут встречаться знакомые блоки кода. Если какая-либо команда покажется вам незнакомой и останется в уроке без объяснений, вернитесь к предыдущим урокам, чтобы освежить память, или обратитесь к справочной системе DarkBASIC.
А сейчас поговорим о переменных. Переменная - это величина, способная принимать разные значения и используемая для их хранения. В DarkBASIC применяется несколько типов переменных, различаемых по расширению. Взгляните на эту строку из нашего примера.
aY# = Object angle Y(1)
В переменной "aY#" мы сохранили значение угла "Y" объекта "1". Обратите внимание на символ "#" в конце выражения "aY#". Он сообщает DarkBASIC, что нам нужно сохранить в переменной значение с плавающей точкой, то есть, число с десятичным знаком, например, 3.5, -5.5 и 0.00001. Такая переменная (она называется вещественной) позволяет хранить дробные числа, ее можно использовать для хранения координат или значения угла. Другие типы переменных в DarkBASIC - это символьные переменные, переменные для хранения массивов данных и переменные целого типа. Для обозначения символьных переменных используется символ "$", например, "A$ = "Здравствуй, мир" ". Данные, которые вы хотите сохранить в символьных переменных, должны заключаться в кавычки. В переменных для хранения массивов данных хранятся наборы данных одного и того же типа. Мы рассмотрим массивы в последующих уроках. Переменные целого типа хранят целые числа, как положительные, так и отрицательные, например, -5, 5, 2112, -10000. Для обозначения таких переменных расширение не используется. Как назвать переменные, решайте сами, но помните, что лучше давать им имя, близкое по смыслу к тому, что эти переменные хранят. Это окажется полезным при отладке программы и обсуждении вашего исходного кода с друзьями. Мы назвали переменную "aY#", чтобы ее имя напоминало нам о том, что в ней хранится значение угла "Y" объекта "1". Обратите внимание, что мы не используем полное название "AngleY#" (Угол Y#). По мере роста исходного кода вам придется много раз набирать на клавиатуре имена переменных. Сокращая имена, вы делаете свой код более легким для чтения и облегчаете себе работу.
Object angle Y(1)
Команда "Object Angle Y" возвращает значение угла объекта, если он поворачивается по оси Y. Ось Y, по которой вращается объект, - это вертикальная линия, проходящая снизу вверх. Можно сравнить ее с земной осью, вокруг которой вращается наша планета. Ось X - это горизонтальная линия, проходящая слева направо. По горизонтальной оси вращаются колеса автомобиля. Ось Z - это направление от вас вдаль, вращение по этой оси можно сравнить с вращением автомобильного руля. В команде "Object Angle Y" в скобках указывается номер объекта, данные о вращении которого (по оси Y) вы хотите узнать. Помните, что команду нужно писать точно так, как она указана в справке. В этой команде пробела между "Y" и первой скобкой нет. Если команду написать неправильно, DarkBASIC не узнает ее и примет за ошибку.
If Upkey()=1 then Move object 1,2
Выражение "If then" - очень мощная команда DarkBASIC, выполняющая функцию сравнения. Переменная, значение которой нужно проверить, помещается после "If". Если переменная имеет значение "Истина", то выполняются команды, стоящие после "Then". Если оно имеет значение "Ложь", то команды после "Then" не выполняются. В этом примере после "If" стоит команда "Upkey()". Она проверяет, нажата ли клавиша-стрелка вверх на клавиатуре и возвращает "1", если клавиша была нажата, и "0", если не была. Если клавиша нажата, выполняется команда "Move Object", перемещающая объект в том направлении, куда он "повернут лицом". Вслед за именем команды стоят числа, называемые параметрами. Первое число после команды "Move Object" - это номер перемещаемого объекта. Второе число обозначает количество единиц пространства сцены, на которые необходимо переместить объект каждый раз, когда выполняется эта команда.
If Leftkey()=1 then aY# = Wrapvalue(aY#+5)
If Rightkey()=1 then aY# = Wrapvalue(aY#-5)
Эти два выражения "If Then" проверяют, нажаты правая или левая клавиша-стрелка. Результаты нажатия этих двух клавиш разные. Используя эти выражения, мы также сохраняем значение в переменной "aY#". Команда "Wrapvalue" позволяет нам сэкономить целый блок программного кода. Дело в том, что команды вращения в DarkBASIC принимают значения только от 0 до 360. Этот диапазон чисел используется для вычисления угла поворота, а команда "Wrapvalue" отслеживает, чтобы значение не выходило за границы этого диапазона. Значение 365 будет преобразовано в 5. Внутри скобок команды "Wrapvalue" мы поместили нашу переменную угла по оси Y и оператор сложения или вычитания. Если нажата левая клавиша, к значению "aY#" прибавляется 5, а затем новое значение сохраняется в "aY#". То же самое происходит, если нажата правая клавиша, только в этом случае значение переменной "aY#" уменьшается на 5.
Yrotate object 1,aY#
Команда "Yrotate object" поворачивает объект по оси Y на указанное число градусов. Первое число после команды обозначает номер объекта, второе - угол, на который нужно повернуть этот объект. Обратите внимание, что во втором параметре вместо числа использована переменная. В параметрах большинства команд DarkBASIC числа можно заменять переменными.
Затем мы используем команду "Sync", чтобы открыть занавес вашей сцены и вывести на экран новое положение объектов.
Попробуйте изменить значение, прибавляемое или вычитаемое из переменной в команде "Wrapvalue", чтобы ускорить или замедлить вращение.
Попробуйте также поменять значение второго параметра в команде "Move Object", чтобы увеличить количество пространственных единиц, на которые перемещается объект. Можно использовать значения с плавающей точкой, например, 0.5 или 1.5. Если число меньше единицы, то перед десятичным знаком лучше всегда ставить "0".
Попробуйте поменять команду "YRotate Object" на команду "ZRotate Object" или "XRotate Object", чтобы посмотреть, как будут поворачиваться объекты.
РУКОВОДСТВО ПО СОЗДАНИЮ 3D-ИГР
I. ОСНОВЫ
3. Перемещение камеры
Цель урока: показать, как нужно изменять положение и угол поворота камеры с помощью ввода с клавиатуры.
Rem Устанавливаем синхронизацию
Sync On
Sync Rate 30
Rem Создаем 5 кубиков и расставляем их в случайном порядке
For x = 1 to 5
Make object cube x,100
Position object x,Rnd(2000),0,Rnd(2000)
Next x
Rem Основной цикл
Do
Rem Сохраняем угол поворота камеры
caY#= Camera angle Y()
Rem Управление камерой с клавиатуры
If Upkey()=1 then Move camera 10
If Leftkey()=1 then Yrotate Camera Wrapvalue(caY#-5)
If Rightkey()=1 then Yrotate Camera Wrapvalue(caY#+5)
Rem Обновляем экран
Sync
Loop
Для начала познакомимся с циклом "For Next".
For x = 1 to 5
Make object cube x,100
Position object x,Rnd(2000),0,Rnd(2000)
Next x
Цикл "For Next" применяется для выполнения одной или нескольких команд заданное число раз. Чтобы указать, сколько раз этот цикл должен выполняться, мы используем переменную "x". В выражении "For Next" для этого всегда нужно ставить слово "To". В нашем случае мы выполняем цикл 5 раз - от 1 до 5. Необходимые команды помещаются в тело цикла. Оператор "Next" с переменной "x", которая подсчитывает число проходов по циклу, обозначает его завершение и увеличивает значение "x" на единицу. Внутри цикла мы создаем объекты в форме куба, присваивая им номер с помощью той же переменной "x". Затем команда "Position Object" помещает на сцене объект в соответствии со значениями 3D-координат. Первое число в команде "Position Object" - это номер помещаемого в сцену объекта. Мы заменили его переменной "x". Три значения после номера объекта обозначают координаты X, Y и Z. Вместо чисел мы поставили команду "Rnd", которая создает случайное число от 0 до значения, находящегося в скобках. Каждый раз при вызове команды "Position Object" новый объект помещается в случайных координатах X и Z с координатой Y, равной 0.
If Upkey()=1 then Move camera 10
Следующая наша команда - "Move Camera". Она похожа на команду "Move Object" за исключением того, что не нужно указывать номер объекта. Число после команды обозначает количество единиц, на которое требуется переместить камеру при каждом проходе основного цикла, если нажата клавиша-стрелка вверх.
If Leftkey()=1 then Yrotate Camera Wrapvalue(caY#-5)
If Rightkey()=1 then Yrotate Camera Wrapvalue(caY#+5)
Команда "YRotate Camera" выполняет ту же функцию, что и "YRotate Object", только она поворачивает по оси Y не объект, а камеру.
Таким образом, вы получили представление, как нужно перемещать камеру и изменять ее положение. Чтобы лучше понять все команды, попробуйте изменить текст исходной программы.
Измените значения в команде "Rnd", чтобы посмотреть, как меняется положение объектов относительно друг друга.
Измените значения в командах "Move Camera" и "Yrotate Camera", чтобы посмотреть, как можно замедлить или ускорить перемещение и поворот камеры.
РУКОВОДСТВО ПО СОЗДАНИЮ 3D-ИГР
I. ОСНОВЫ
4. Вид от третьего лица
Цель урока: показать, как нужно вводить вид от третьего лица.
Rem Устанавливаем синхронизацию
Sync On
Sync Rate 30
Rem Создаем 5 кубиков и расставляем их в случайном порядке
For x = 1 to 5
Make object cube x,100
Position object x,Rnd(2000),0,Rnd(2000)
Next x
Rem Создаем сферу
Make object sphere 10,50
Rem Основной цикл
Do
Rem Сохраняем вертикальный угол объекта в переменной aY#
aY# = Object angle Y(10)
Rem Управление камерой с клавиатуры
If Upkey()=1 then Move object 10,10
If Leftkey()=1 then Yrotate object 10,Wrapvalue(aY#-5)
If Rightkey()=1 then Yrotate object 10,Wrapvalue(aY#+5)
Rem Устанавливаем положение игрока и сохраняем его в переменных X# и Z#
X# = Object position x(10)
Z# = Object position z(10)
Rem Получаем новое положение камеры и сохраняем его в переменных cZ# и cX#
cZ# = Newzvalue(Z#,aY#-180,100)
cX# = Newxvalue(X#,aY#-180,100)
Rem Устанавливаем положение камеры
Position Camera cX#,100,cZ#
Rem Направляем камеру на объект "Игрок"
Point camera X#,50,Z#
Rem Обновляем экран
Sync
Loop
В этом уроке мы познакомимся с тем, как применить в игре вид от третьего лица. Вид от третьего лица можно определить, как вид из камеры, которая находится позади игрока и чуть выше него. Большую часть кода этого урока, мы уже описывали в предыдущих уроках. Давайте сосредоточимся на новых строках кода и новых командах.
X# = Object position x(10)
Z# = Object position z(10)
Команды "Object Position X" и "Object Position Z" похожи на команду "Object Angle" за исключением того, что они возвращают не угол поворота объекта, а положение объекта в относительных координатах. В скобках ставится номер объекта, координаты которого нужно получить. Значения координат сохраняем в переменных X# и Z#.
cZ# = Newzvalue(Z#,aY#-180,100)
cX# = Newxvalue(X#,aY#-180,100)
Команды "NewZValue" и "NewXValue" помогают вам избежать сложных математических функций, таких как синус и косинус. Они вычисляют новое положение объекта на основании старого. Мы используем эти команды, чтобы вычислить точку, находящуюся в 100 единицах пространственных координат позади объекта "Игрок". Первый параметр - это относительная координата, в которой расположен игрок в данный момент. Помните, что мы сохранили положение этого объекта в переменных X# и Z#. Второй параметр - угол оси новых координат. Мы взяли значение вертикального угла объекта, сохранили значение в переменной Y# и вычли из него 180 градусов. Этот угол направлен точно за объект. Третий параметр обозначает точку, удаленную от объекта на указанное количество единиц пространственных координат. Мы задали значение 100. Другими словами, мы сделали следующее: нашли точку, находящуюся позади объекта "Игрок" и удаленную от него на 100 единиц, и сохранили ее координаты в переменных cZ# и cX#, обозначающих положение нашей камеры.
Position camera cX#,100,cZ#
Команда "Position Camera" работает так же, как и команда "Position Object", за исключением того, что не нужно указывать номер объекта - только значения координат. Для координат X и Z мы используем вновь созданные значения, а для координаты Y - значение 100. Поскольку вертикальная координата Y объекта-игрока равна 0, а его радиус 50, значение 100 координаты помещает камеру над объектом.
Point camera X#,50,Z#
Наша камера направлена поверх объекта-игрока. С помощью команды "Point Camera" мы направим камеру на объект. Параметры этой команды - это координаты X, Y и Z той точки, на которую нужно направить камеру. Мы используем переменные X# и Z#, хранящие значения положения объекта по осям X и Z. В качестве значения по оси Y будем использовать 50. Теперь камера направлена в центр нашего объекта-игрока.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 10 [только новые]


администратор




Сообщение: 301
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:20. Заголовок: Re:


Попробуйте изменить количество повторений цикла, чтобы создать больше кубиков. Не забудьте поменять номер объекта-игрока, чтобы это число было больше, чем число кубиков, иначе программа выведет сообщение об ошибке "Объект уже существует".
В командах "NewXValue" и "NewYValue" попробуйте поменять значение 180 на другое, меньше 360, чтобы посмотреть, как оно влияет на положение камеры. Измените также последний параметр в этих командах, чтобы переместить камеру ближе или дальше к объекту.
Попробуйте изменить значение 50 в команде "Point Camera", чтобы изменить высоту камеры.
5. Обнаружение столкновений
Цель урока: объяснить, как обнаруживать столкновения.
Rem Устанавливаем синхронизацию
Sync On
Sync Rate 30
Rem Создаем кубики в случайном порядке
For x = 1 to 5
Make object cube x,100
Position object x,Rnd(2000),0,Rnd(2000)
Set object collision to boxes x
Next x
Rem Создаем сферу
Make object sphere 10,50
Position object 10,-100,0,-100
Set object collision to spheres 10
Rem Основной цикл
Do
Rem Сохраняем значение вертикального угла в aY#
aY# = Object angle Y(10)
Rem Управление камерой с клавиатуры
If Upkey()=1 then Move object 10,10
If Leftkey()=1 then Yrotate object 10,Wrapvalue(aY#-5)
If Rightkey()=1 then Yrotate object 10,Wrapvalue(aY#+5)
Rem Обнаруживаем столкновение
If Object collision(10,0)>0 then position object 10,X#,0,Z#
Rem Сохраняем положение игрока в X# и Z#
X# = Object position x(10)
Z# = Object position z(10)
Rem Получаем новое положение камеры и сохраняем его в cZ# и cX#
cZ# = Newzvalue(Z#,aY#-180,100)
cX# = Newxvalue(X#,aY#-180,100)
Rem Устанавливаем камеру
Position Camera cX#,75,cZ#
Rem Направляем камеру на объект
Point camera X#,25,Z#
Rem Обновляем экран
Sync
Loop

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 302
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:21. Заголовок: Re:


В этом уроке мы покажем, как использовать команды DarkBASIC для обнаружения столкновений. Мы добавили их в исходный код предыдущего урока.
Set object collision to boxes x
В цикл, где создаются и размещаются кубические объекты, мы вставили команду "Set Object Collision To Boxes". Она устанавливает тип обнаружения столкновений с объектами в форме куба, то есть соответствующий форме наших объектов. Чтобы передать команде "Set Object Collision To Boxes" номера объектов, мы используем переменную цикла "х".
Set object collision to spheres 10
Эта команда тоже устанавливает тип обнаружения столкновений с объектами, но не в форме куба, а в форме сферы, такой, как у нашего объекта-игрока. Выбор типа столкновений зависит от вас. Старайтесь только, чтобы он лучше всего подходил для игры, которую вы создаете.
If Object collision(10,0)>0 then position object 10,X#,0,Z#
Эта строка кода определяет столкновение объектов. Если наш объект-игрок сталкивается с каким-либо другим объектом, он перемещается в место, где находился перед столкновением. Эти координаты хранятся в переменных X# и Z#. Обратите внимание, что мы определяем столкновение после перемещения объекта и перед тем, как сохраняем новые значения его координат. Этим мы обеспечиваем возвращение объекта-игрока на старое место, где он не может столкнуться с каким-нибудь другим объектом. Команда "Object Collision" используется для проверки столкновения. Первый параметр в скобках - это номер вашего объекта-игрока, для которого определяется столкновение. Второе значение - номер объекта, столкновение с которым вашего объекта-игрока нужно проверить. Здесь мы применяем значение 0, чтобы DarkBASIC обнаруживал столкновение с любым объектом. В этом случае команда "Object Collision" возвращает номер объекта, с которым столкнулся объект под номером 10, и значение 0, если столкновения не произошло. Если эта команда возвратит значение больше 0, то столкновение обнаружено, и мы помещаем объект-игрок в то место, где он находился перед столкновением.
Еще один тип столкновений - полигонный. Он используется при обнаружении столкновений с крупными объектами, такими как здания, построенными вами в 3D-сцене. Теперь, после знакомства с новыми командами, вы можете применять обнаружение столкновений в своих программах. Чтобы научиться свободно пользоваться ими, попробуйте внести в них следующие изменения.
Попробуйте поменять значение второго параметра в команде "Object Collision" на 3. Перемещаясь по 3D-сцене и сталкиваясь с кубическими объектами, попытайтесь найти объект под номером 3.
Измените тип столкновений, чтобы обнаруживать столкновения объекта-игрока с объектами не в форме сферы, а в форме куба, и посмотрите, как это отражается на столкновениях с объектами в форме куба.
6. Текстурирование объектов
Цель урока: научиться накладывать текстуры на объекты.
Rem Устанавливаем синхронизацию
Sync On
Sync Rate 30
Rem Загружаем текстуры
Load image "cottag02.bmp",1
Load image "barry.bmp",2

Rem Создаем кубики в случайном порядке
For x = 1 to 5
Make object cube x,100
Position object x,Rnd(2000),0,Rnd(2000)
Set object collision to boxes x
Texture object x,1
Next x
Rem Создаем сферу
Make object sphere 10,50
Position object 10,-100,0,-100
Set object collision to spheres 10
Texture object 10,2
Rem Основной цикл
Do
Rem Сохраняем вертикальный угол в aY#
aY# = Object angle Y(10)
Rem Управление камерой с клавиатуры
If Upkey()=1 then Move object 10,10
If Leftkey()=1
Yrotate object 10,Wrapvalue(aY#-5)
Endif
If Rightkey()=1
Yrotate object 10,Wrapvalue(aY#+5)
Endif
Rem Обнаруживаем столкновение
If Object collision(10,0)>0
Position object 10,X#,0,Z#
Endif
Rem Сохраняем положение объекта-игрока в X# и Z#
X# = Object position x(10)
Z# = Object position z(10)
Rem Получаем новое положение камеры и сохраняем его в cZ# and cX#м
cZ# = Newzvalue(Z#,aY#-180,100)
cX# = Newxvalue(X#,aY#-180,100)
Rem Устанавливаем камеру
Position Camera cX#,75,cZ#
Rem Направляем камеру на объект "Игрок"
Point camera X#,25,Z#
Rem Прокручиваем текстуру на кубических объектах
Scroll object texture 1,0.005,0
Scroll object texture 2,0,0.005
Rem Масштабируем текстуру на кубических объектах
Scale object texture 3,0.998,0.998
Scale object texture 4,1.001,1.001
Rem Обновляем экран
Sync
Loop

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 303
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:21. Заголовок: Re:


В этом уроке мы научимся текстурировать объекты. В DarkBASIC текстуры загружаются из файлов растровых изображений с расширением ".bmp". Советуем создавать текстуры с размерами кратными степени 2, так как некоторые графические карты не могут обрабатывать текстуры, размеры которых выражены нечетными числами и не кратны степени 2. Это означает, что размеры ваших изображений должны быть 256x256, 32x128, 256x16 или любых других размеров кратными степени 2. Можно загружать текстуры и большего размера, чем 256x256, но в этом случае убедитесь, что ваша графическая карта может обрабатывать такие большие текстуры.
Load image "cottag02.bmp",1
Load image "barry.bmp",2
Команда "Load Image" дает DarkBASIC указание загрузить изображение из файла растрового изображения. Первый параметр команды - это имя загружаемого файла растрового изображения. Имя файла нужно заключить в кавычки, иначе произойдет ошибка. В этом параметре можно использовать имена каталогов, например, "C:\Darkbasic\Images\mybitmap.bmp". Если вы храните изображения в подкаталоге проекта, в параметре необходимо указать его имя. Мы советуем создавать отдельный подкаталог, если в вашей программе много мультимедийных файлов. Второй параметр - это уникальный номер (или идентификатор) изображения, который используется так же, как при создании объекта. Нельзя присваивать один и тот же номер двум разным изображениям.
Texture object x,1
Texture object 10,2
Эти две строки стоят перед основным циклом. Первая строка находится в теле цикла "For Next" и служит для создания кубических объектов. Вторая внесена после того, как мы создали объект "Игрок". Команда "Texture Object" предназначена для наложения изображения на объект. Первый параметр - номер объекта, на который нужно наложить текстуру. Второй параметр - номер накладываемого на объект изображения.
Scroll object texture 1,0.005,0
Scroll object texture 2,0,0.005
Команда "Scroll Object Texture" перемещает (прокручивает) наложенную на объект или полигон текстуру вверх и вниз или вправо и влево. Первый параметр - номер объекта, чья текстура будет прокручиваться. Следующие два параметра - это U и V координаты. Вы можете представить их как координаты X и Y двумерной текстуры. Если присвоить этим параметрам значения, отличные от 0, текстура будет прокручиваться при каждом вызове этой команды. Можно использовать как положительные, так и отрицательные значения, в зависимости от того, в каком направлении вы хотите прокрутить текстуру на объекте. В нашем примере используется очень маленькое значение с плавающей точкой. Значения прокрутки U и V можно представить как процент от размера текстуры. Если бы мы установили значение, равное "0.5", что означает 50 процентов, текстура на кубе передвинулась бы ровно наполовину, а это - слишком быстро.
Scale object texture 3,0.998,0.998
Scale object texture 4,1.001,1.001
Команда "Scale Object Texture" похожа на предыдущую, только эта команда увеличивает или уменьшает масштаб текстуры на объекте. Первый параметр - это номер объекта, текстура которого изменяет масштаб (масштабируется). Следующие два параметра являются U и V координатами текстуры. Изменение этих значений на любую величину, кроме 0, увеличит или уменьшит размер текстуры. Когда эти значения равны 0, никакого изменения размеров не произойдет. Если присвоить параметрам значение меньше 1, масштаб текстуры уменьшится, и наоборот, если присвоить им значение больше 1, масштаб текстуры увеличится.
Теперь вы умеете загружать изображение из файла и накладывать его на объект, а также масштабировать и прокручивать текстуру объекта. Попробуйте внести следующие изменения, чтобы посмотреть, как они повлияют на текстурированные кубики.
Измените значения U и V в команде "Scroll Object Texture", чтобы посмотреть, как это повлияет на скорость прокрутки текстур объектов.
Измените значения U и V в команде " Scale Object Texture", чтобы посмотреть, как это отразится на масштабе текстур.


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 304
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:22. Заголовок: Re:


II. МАТРИЦА
1. Создание матрицы
Цель урока: ознакомление с командами, создающими матрицу.
Rem Устанавливаем синхронизацию
Sync On
Sync Rate 30
Rem Создаем матрицу
Make Matrix 1,2000,2000,50,50
Rem mY - переменная для хранения высоты матрицы
mY=100
Rem Помещаем камеру над матрицей
Position Camera 0,1000,0
Rem Основной цикл
Do
Rem Управление камерой с клавиатуры
If Upkey()=1 then Move camera 10
If Downkey()=1 then Move camera -10
Rem Ввод для заполнения матрицы случайными значениями
If Spacekey()=1 then randomize matrix 1,mY
If Leftkey()=1 then mY=mY+1
If Rightkey()=1 then mY=mY-1
If mY < 1 then mY =1
Rem Направляем камеру в центр матрицы
Point Camera 1000,0,1000
Rem Обновляем экран
Sync
Loop


Этот урок познакомит вас с командами, создающими матрицу. Матрица часто используется для создания объекта местности. Вы можете легко создавать горы, пологие холмы, пещеры и океаны при помощи нескольких строк кода. Помните, если вы встретите незнакомую команду без объяснений в данном руководстве, просмотрите предыдущие руководства или обратитесь за помощью к справочной системе DarkBASIC. Приведенная выше простая программа создает матрицу и позволяет вам масштабировать ее в изометрический проекции с использованием клавиш "стрелка вверх" и "стрелка вниз". Клавиши-стрелки и пробел позволяют вам управлять высотой и видом матрицы.
Make Matrix 1,2000,2000,50,50
Первая новая команда, которую мы обсудим - это команда Make Matrix. Она создает объект "Матрица" в вашей 3D-сцене. Что означают параметры этой команды? Первое число после команды - это номер создаваемой матрицы. Этот номер, как и в командах управления объектами и изображениями, является уникальным идентификатором. Он позволяет вам создавать и манипулировать многочисленными матрицами в 3D-сцене. Последующие два числа - это размеры матрицы, которую вы хотите создать, в пространственных координатах сцены. Они представляют значения координат X и Y. В большинстве случаев эти два значения будут одинаковыми, но мы уверены, что вы сможете найти применение для матриц различных размеров. Следующие два числа - это количество сегментов матрицы. В этом примере матрица размером 2000х2000 разделена в каждом направлении на 50 сегментов (размер ячейки получается 40x40).
If Spacekey()=1 then Randomize Matrix 1,mY
Эта строка кода знакомит нас с командой Randomize Matrix. При нажатии на пробел осуществляется вызов этой команды, которая задает случайное значение высоты каждой из вершин матрицы в диапазоне между 0 и числом, содержащимся в переменной mY. Первое число после команды -- это номер изменяемой матрицы. Второе число - это диапазон случайного значения для изменения высоты матрицы. В программе вы можете изменить значение переменной mY, нажимая клавиши "стрелка вверх" и "стрелка вниз". Нажатие на клавишу "пробел" позволяет изменить матрицу, что дает вам возможность создавать крутые пики гор или пологие холмы.
Попытайтесь изменять значения параметров в команде Make Matrix и посмотреть, каким образом они влияют на величину и размеры матрицы.
2. Текстурирование матрицы
Цель урока: научиться накладывать текстуры на матрицу.
Мы начнем с программы, которая создает рельефную местность и текстурирует каждую ячейку матрицы случайным образом.
Sync On
Sync Rate 30

Rem Создаем матрицу
Make matrix 1,10000,10000,20,20
Rem Текстурируем матрицу
Load image "grass09.bmp",1
Prepare matrix texture 1,1,2,2
rem Заполняем матрицу случайными значениями высоты
randomize matrix 1,250
rem Накладываем текстуру случайным образом на каждый тайл матрицы
For x = 0 to 19
For z = 0 to 19
t= rnd(3)+1
Set Matrix Tile 1,x,z,t
Next z
Next x
Rem Вносим изменения в матрицу
update matrix 1
Rem Основной цикл
Do
Rem Сохраняем угол объекта
CameraAngleY# = Camera angle Y()

Rem Управление перемещением камеры
If Upkey()=1 then Move camera 10
If Leftkey()=1 then Yrotate Camera Wrapvalue(CameraAngleY#-5)
If Rightkey()=1 then Yrotate Camera Wrapvalue(CameraAngleY#+5)
If Spacekey()=1
Fill matrix 1,Rnd(50),Rnd(3)+1
randomize matrix 1,250
endif
X# = Camera position X()
Z# = Camera position Z()
Position Camera X#,250,Z#

Rem Обновляем экран
Sync
Loop
Начнем с подготовки текстуры для матрицы.
Prepare matrix texture 1,1,2,2
The "Команда "Prepare Matrix Texture" применяется для разбиения на ячейки текстуры, накладываемой на матрицу. Первый параметр после команды - это номер матрицы, для которой мы собираемся подготовить текстуру. Второй параметр - это номер изображения, используемого для текстурирования матрицы. Третий и четвертый параметры - это число создаваемых на каждой оси ячеек. Здесь мы использовали в качестве первого параметра значение 2. Это число делений по оси X. Значение 2 сообщает DarkBASIC, что текстуру надо разделить пополам на две части. В последнем параметре мы также использовали значение 2. Это, в свою очередь, число делений по оси Y. Таким образом, мы разделили изображение на четыре секции, или четыре отдельные текстуры. Изображение, используемое для наложения текстуры на матрицу, не может быть больше, чем 256х256 пикселов, однако вы можете разбить его максимум на 256х256 отдельных тайлов. В большинстве случаев значение двух последних параметров команды будут одинаковы. Если значения параметров будут разными, то текстуры будут непропорционально растянуты при наложении на квадратные ячейки матрицы. Тайлы нумеруются, начиная с левого верхнего угла, слева направо и сверху вниз. Нумерация начинается с 1.
For x = 0 to 19
For z = 0 to 19
t= rnd(3)+1
Set Matrix Tile 1,x,z,t
Next z
Next x
Эти вложенные циклы проходят по каждой ячейке матрицы, и случайным образом назначают для каждой из них ранее подготовленный тайл. Чтобы назначить отдельной ячейке матрицы определенный тайл, мы используем команду "Set Matrix Tile". Первый параметр после команды - номер матрицы, которую мы желаем изменить. Второй и третий параметры - это номера строки и колонки, в которых располагается ячейка матрицы, для которой мы хотим изменить тайл. Последний параметр - это номер тайла изображения, размещаемого в определенной ячейке матрицы. Для выбора случайного номера тайла в интервале от 0 до 3 мы применили команду "Rnd". Заметьте, что мы добавили 1 к этому числу, так как тайла с номером "0" не существует. Таким образом, после добавления 1, производится выбор случайного номера тайла в интервале от 1 до 4.
If Spacekey()=1
Fill matrix 1,Rnd(50),Rnd(3)+1
randomize matrix 1,250
endif
Эта часть кода изменяет высоту матрицы и случайным образом изменяет тайлы для каждой ячейки матрицы при каждом нажатии клавиши "пробел". Команда "Fill Matrix" устанавливает определенную высоту и определенный номер тайла изображения для всех тайлов матрицы. Эта команда наилучшим образом подходит для установки начальных значений для всех ячеек матрицы. Первый параметр после команды - номер матрицы, которую мы хотим изменить. Второй параметр - это высота, устанавливаемая нами для всех вершин матрицы. Это полезно при добавлении еще одной матрицы (например, матрицы "вода"), или создании слоев матриц, наложенных друг на друга. Для выбора случайного значения высоты в интервале от 0 до 50 мы использовали команду "Rnd". Эта величина соответствует координатам по оси Y в созданном вами 3D-пространстве. Наконец, последний параметр - это номер тайла подготовленной матричной текстуры, который мы хотим использовать. Для случайного выбора тайла мы применили команду "Rnd".
На этом мы завершаем главу об основах текстурирования матрицы.
Попробуйте изменить значения последних двух параметров в команде "Prepare Matrix Texture", чтобы посмотреть, как изменятся изображения в тайлах. Затем измените значения параметров каждой команды "Rnd" в соответствии с измененным числом тайлов, подготовленных вами для матрицы.
3. Перемещение по матрице
Цель урока: объяснить, как установить камеру в определенную позицию на матрице.
Sync On
Sync Rate 30

Rem Создаем матрицу
Make matrix 1,10000,10000,20,20
Rem Текстурируем матрицу
Load image "grass09.bmp",1
Prepare matrix texture 1,1,1,1
Fill matrix 1,0,1
rem Присваиваем координатам вершин матрицы случайные значения
randomize matrix 1,125

Rem Основной цикл
Do
set cursor 0,0
print X#
print Y#
print Z#
Rem Сохраняем угол объекта
CameraAngleY# = Camera angle Y()
Rem Управление перемещением камеры
If Upkey()=1
XTest# = Newxvalue(X#,CameraAngleY#,20)
ZTest# = Newzvalue(Z#,CameraAngleY#,20)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
Move camera 10
Endif
Endif
If Leftkey()=1 then Yrotate Camera Wrapvalue(CameraAngleY#-5)
If Rightkey()=1 then Yrotate Camera Wrapvalue(CameraAngleY#+5)
X# = Camera position X()
Z# = Camera position Z()
Y# = Get ground height(1,X#,Z#)
Position Camera X#,Y#+35,Z#
Rem Обновляем экран
Sync
Loop
Эта программа демонстрирует, как поместить камеру таким образом, чтобы она следовала рельефу местности на матрице.
set cursor 0,0
print X#
print Y#
print Z#
Мы начнем этот урок с объяснения двух полезных текстовых команд "Set Cursor" и "Print". Первая из них помещает курсор в точку на экране с координатами X и Y (параметры команды), с которой мы собираемся начать вывод текста, а вторая выводит текст на экран. Здесь мы используем переменные X#, Y# и Z#. На экран будут выведены значения каждой из них. Если вы хотите вывести на экран текстовую строку, вы должны заключить ее в кавычки.
If Upkey()=1
XTest# = Newxvalue(X#,CameraAngleY#,20)
ZTest# = Newzvalue(Z#,CameraAngleY#,20)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
Move camera 10
Endif
Endif
Эта часть кода ограничивает перемещение камеры для того, чтобы предотвратить выход игрока за пределы матрицы. Переменные Xtest# и Ytest# хранят координаты позиции, в которой мы собираемся установить камеру. Имейте в виду, что значение "20" на самом деле является расстоянием вдвое большим, чем то, на которое мы желаем переместить камеру. Такой прием не подпускает игрока к абсолютной границе матрицы. Выражение сравнения "If" проверяет, не вышли ли новые значения координат за границы матрицы. Матрица занимает площадь в координатах от 0 до 10000 в каждом направлении. Мы используем союз "and" для того, чтобы осуществить более одного сравнения в выражении "If". Если игрок не вышел за пределы указанных границ, то камера перемещается в новое место.
X# = Camera position X()
Z# = Camera position Z()
Y# = Get ground height(1,X#,Z#)
Position Camera X#,Y#+35,Z#
После того, как камера переместилась, мы сохраняем значения ее координат в переменных X# и Z#. Затем мы получаем координату высоты матрицы в том месте, где расположена камера, и сохраняем это значение в переменной Y#, используя команду "Get Ground Height". В скобках после команды первый параметр - это номер матрицы, для которой мы определяем значение высоты. Следующие два параметра - координаты X и Z, в этой точке мы желаем узнать высоту матрицы. После определения высоты мы устанавливаем камеру на 35 пунктов выше матрицы. Это позволяет перемещаться по матрице на 35 пунктов выше ее рельефа.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 305
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:23. Заголовок: Re:


4. Вид от третьего лица и перемещение на матрице
Цель урока: научиться перемещать объект на матрице, используя вид от третьего лица.
Sync On
Sync Rate 30
Rem Создаем матрицу
Make matrix 1,10000,10000,20,20
Rem Текстурируем матрицу
Load image "grass09.bmp",1
Prepare matrix texture 1,1,1,1
Fill matrix 1,0,1
Rem Создаем объект
Load image "barry.bmp",2
Make object sphere 10,25
Texture object 10,2
position object 10,100,0,100
rem Устанавливаем случайные значения для вершин матрицы
randomize matrix 1,125
Rem Основной цикл
Do
set cursor 0,0
print screen fps()
Rem Сохраняем угол объекта
AngleY# = object angle Y(10)
Rem Управление перемещением камеры
If Upkey()=1
XTest# = Newxvalue(X#,AngleY#,20)
ZTest# = Newzvalue(Z#,AngleY#,20)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
Move object 10,10
Endif
Endif
If Leftkey()=1 then Yrotate object 10,Wrapvalue(AngleY#-5)
If Rightkey()=1 then Yrotate object 10,Wrapvalue(AngleY#+5)
X# = Object position x(10)
Z# = Object position z(10)
Y# = Get Ground Height(1,X#,Z#)
Position object 10,X#,Y#+12.5,Z#
CameraZ# = Newzvalue(Z#,AngleY#-180,100)
CameraX# = Newxvalue(X#,AngleY#-180,100)
CameraY# = Get Ground Height(1,CameraX#,CameraZ#)
Position camera CameraX#,CameraY#+50,CameraZ#
Point camera X#,Y#+25,Z#
Rem Обновляем экран
Sync
Loop
Эта программа позволяет пользователю перемещать текстурированную сферу по матрице при помощи клавиатуры. Мы начнем этот урок с описания простой служебной команды.
print screen fps()
"Screen Fps()" является полезной командой, с помощью которой можно узнать, с какой скоростью происходит обновление экрана. Попробуйте выставить значение синхронизации 0 и запустите программу. Вы увидите число на экране, показывающее, сколько раз в секунду происходит обновление экрана. Если частота обновления на вашей видеокарте привязана к частоте обновления монитора, вы не сможете узнать максимальную скорость обновления, которую способна выдавать ваша видеокарта. Некоторые видеокарты позволяют отключать синхронизацию ("VSync"), при этом экран обновляется с максимально возможной скоростью.
X# = Object position x(10)
Z# = Object position z(10)
Y# = Get Ground Height(1,X#,Z#)
Position object 10,X#,Y#+12.5,Z#
CameraZ# = Newzvalue(Z#,AngleY#-180,100)
CameraX# = Newxvalue(X#,AngleY#-180,100)
CameraY# = Get Ground Height(1,CameraX#,CameraZ#)
Position camera CameraX#,CameraY#+50,CameraZ#
Point camera X#,Y#+25,Z#
Как и в предыдущем уроке, для нахождения высоты матрицы в определенном месте мы используем команду "Get Ground Height". Здесь мы используем эту команду дважды: один раз для того, чтобы определить высоту в месте, где располагается сфера, и второй раз для того, чтобы определить высоту в том месте, где располагается камера. Вы заметите, что оставшаяся часть кода такая же, как и в предыдущем уроке. Единственное, что мы здесь изменили - это добавили значение Y#.
Попробуйте использовать выражение "Rem", чтобы закомментировать следующую строку кода:
CameraY# = Get Ground Height(1,CameraX#,CameraZ#)
А в строке:
Position camera CameraX#,CameraY#+50,CameraZ#
замените переменную CameraY# на Y# и посмотрите, как это отражается на поведении камеры.
5. Туман и задник
Цель урока: объяснить применение основных команд для создания тумана и задника.
Команды тумана в основном применяются для создания тумана в 3D-сцене. Немного изменив параметры команды, можно создавать такие эффекты, как дым, подводное окружение, сумерки и т.д. Другое очень важное применение команды тумана состоит в том, чтобы использовать ее для создания эффекта "скрывающейся геометрии". В насыщенной 3D-среде с большим количеством полигонов можно использовать туман, чтобы скрыть геометрию сцены за пределами максимального расстояния видимости камеры. Этот метод может значительно увеличить скорость выполнения программ.
Sync On
Sync Rate 30
Backdrop on
Set camera range 1,5000
Fog on
Fog distance 4000
Fog color RGB(128,128,128)
Color Backdrop RGB(128,128,128)
Rem Создаем матрицу
Make matrix 1,10000,10000,20,20
Rem Текстурируем матрицу
Load image "grass09.bmp",1
Prepare matrix texture 1,1,1,1
Fill matrix 1,0,1
Rem Создаем простейший объект
Load image "barry.bmp",2
Make object sphere 10,25
Texture object 10,2
position object 10,100,0,100
rem Присваиваем случайные значения координатам вершин матрицы
randomize matrix 1,125
Rem Основной цикл
Do
Rem Сохраняем угол объекта
AngleY# = object angle Y(10)
Rem Управление перемещением камеры
If Upkey()=1
XTest# = Newxvalue(X#,AngleY#,20)
ZTest# = Newzvalue(Z#,AngleY#,20)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
Move object 10,10
Endif
Endif
If Leftkey()=1 then Yrotate object 10,Wrapvalue(AngleY#-5)
If Rightkey()=1 then Yrotate object 10,Wrapvalue(AngleY#+5)
X# = Object position x(10)
Z# = Object position z(10)
Y# = Get Ground Height(1,X#,Z#)
Position object 10,X#,Y#+12.5,Z#
CameraZ# = Newzvalue(Z#,AngleY#-180,100)
CameraX# = Newxvalue(X#,AngleY#-180,100)
Position camera CameraX#,Y#+50,CameraZ#
Point camera X#,Y#+25,Z#
Rem Обновляем экран
Sync
Loop
Начнем объяснение с нескольких установочных команд.
Backdrop on
Команда "Backdrop on" включает задник. Если он выключен, вы увидите эффект зеркального помещения, выражающийся в том, что можно перемещаться за пределами матрицы, но объект-игрок не сможет подбирать или удалять находившиеся там прежде предметы. Задник необходимо использовать в том случае, если вы знаете, что игроку будет виден задний план.
Set camera range 1,5000
Команда "Set Camera Range" устанавливает дальность видимого пространства для камеры. Первый параметр определяет, на каком расстоянии от камеры DarkBASIC должен начать рендеринг 3D-сцены. Второй параметр определяет расстояние от камеры, на котором прекращается рендеринг сцены. При выборе значения последнего параметра необходимо принять во внимание то, насколько далеко будет "видеть" игрок, и какое число полигонов будет одновременно отображаться. Попробуйте изменить значение первого параметра на 1000, а второго - на 100000 или 1000 и посмотреть, как это повлияет на рендеринг сцены.
Fog on
Команда "Fog On" указывает DarkBASIC, что на определенном расстоянии в сцене будет использоваться туман.
Fog distance 4000
Команда "Fog Distance" устанавливает расстояние, с которого должен начинаться наиболее плотный туман. Советуем установить этот параметр равным или чуть меньшим, чем последний параметр в команде "Set Camera Range", в противном случае вам придется наблюдать неприятный эффект обрезанных полигонов.
Fog color RGB(128,128,128)
Команда "Fog Color" устанавливает цвет тумана. Параметр после команды - цвет тумана. Здесь для установки цвета мы используем команду "RGB".
Color Backdrop RGB(128,128,128)
Команда "Color Backdrop" устанавливает цвет задника. Параметр после команды - цвет задника. Так же, как и в предыдущей команде, для установки цвета задника мы используем команду "RGB". Чтобы туман выглядел более реалистичным, советуем окрасить задник в тот же цвет, что и туман. В этом случае туман сольется с задником. Для создания других эффектов можно установить различные значения этих цветов. Попробуйте задать расстояние для тумана равным 500, установить значение цвета тумана равным "0,0,0", а цвета задника равным "0,0,32". Это создаст эффект вырисовывающегося ландшафта на фоне почти черного неба.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 306
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:24. Заголовок: Re:


III. ИГРА
1. Загрузка объектов
Цель урока: научиться загружать объекты в 3D-сцену и строить фундамент игровой программы.
Существует множество различных приложений, способных создавать и сохранять 3D-модели. В DarkBASIC можно использовать как формат "X" DirectX, так и формат "3DS" 3DStudio. В отличие от стандартных примитивов DarkBASIC, модели этих форматов помогут вам создавать более реалистичные и богатые графикой сцены.
Sync On
Sync Rate 30
Hide Mouse
autocam off

Backdrop on
Set camera range 1,5000
Fog on
Fog distance 4000
Fog color RGB(128,128,128)
Color Backdrop RGB(128,128,128)
Rem Создаем матрицу
Make matrix 1,10000,10000,20,20
Rem Текстурируем матрицу
Load image "grass09.bmp",1
Prepare matrix texture 1,1,1,1
Fill matrix 1,0,1
rem Присваиваем координатам вершин матрицы случайные значения
randomize matrix 1,125
rem Загружаем объект
Load object "idle.x",2
position object 2,5000,Get Ground Height(1,5000,5500),5500
Rem Основной цикл
Do
set cursor 0,0
print X#
print Y#
print Z#
Rem Сохраняем угол объекта
CameraAngleY# = Camera angle Y()
Rem Управление перемещением камеры
If Upkey()=1
XTest# = Newxvalue(X#,CameraAngleY#,20)
ZTest# = Newzvalue(Z#,CameraAngleY#,20)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
Move camera 10
Endif
Endif
If Leftkey()=1 then Yrotate Camera Wrapvalue(CameraAngleY#-5)
If Rightkey()=1 then Yrotate Camera Wrapvalue(CameraAngleY#+5)
X# = Camera position X()
Z# = Camera position Z()
Y# = Get ground height(1,X#,Z#)
Position Camera X#,Y#+35,Z#
Rem Обновляем экран
Sync
Loop
Прежде всего, введем несколько полезных команд.
Hide Mouse
Команда "Hide mouse" убирает с экрана курсор мыши. В большинстве случаев в 3D-сценах курсор мыши на экране вам не понадобится.
autocam off
Команда "Autocam Off" выключает режим автоматической камеры. Когда этот режим включен, то при создании каждого новый объект в DarkBASIC, камера перемещается для того, чтобы показать этот объект. Если загружается большое число объектов, камера будет показывать каждый из них по мере загрузки. Выключение этого режима также играет свою роль при загрузке матрицы. Когда режим автоматической камеры выключен, камера устанавливается в центр созданной вами матрицы. Если режим включен, то камера будет установлена в позицию с координатами (0,0,0) в 3D-сцене.
Load object "idle.x",2
"Load Object" - основная команда для загрузки объекта в DarkBASIC. Первый параметр этой команды - имя файла объекта, загружаемого в 3D-сцену. Чтобы команда распознала имя файла, оно должно быть заключено в кавычки. Второй параметр команды - это номер, назначаемый данному объекту. Эта команда очень похожа на команды "Make Object". Все команды для работы с объектами, описанные в предыдущих уроках, будут работать с загруженными объектами точно так же, как они работают с объектами, созданными в DarkBASIC.
Loop object 2
Команда "Loop Object" осуществляет циклическую анимацию загруженного в DarkBASIC объекта. Если загруженный объект не содержит данных об анимации, использование этой команды может вызвать ошибку. Создавая анимированный объект в специальной программе, обратите внимание на плавность анимации в цикле, в противном случае будет наблюдаться дергающееся движение при переходе модели от последнего к первому кадру анимации.
2. Управление при помощи мыши
Цель урока: объяснить, как использовать команды мыши для перемещения камеры.
Во многих играх используется такое свойство настройки, как "mouse look", позволяющая поворачивать камеру перемещением мыши. Это более эффективный метод управления камерой, чем управление с клавиатуры.
Sync On
Sync Rate 30
hide mouse
Backdrop on
Set camera range 1,5000
Fog on
Fog distance 4000
Fog color RGB(128,128,128)
Color Backdrop RGB(128,128,128)
Rem Создаем матрицу
Make matrix 1,10000,10000,20,20
Rem Текстурируем матрицу
Load image "grass09.bmp",1
Prepare matrix texture 1,1,1,1
Fill matrix 1,0,1
rem Присваиваем координатам вершин матрицы случайные значения
randomize matrix 1,125
X#=5000
Z#=5000
Rem Основной цикл
Do
OldCamAngleY# = CameraAngleY#
OldCamAngleX# = CameraAngleX#
CameraAngleY# = WrapValue(CameraAngleY#+MousemoveX()*0.2)
CameraAngleX# = WrapValue(CameraAngleX#+MousemoveY()*0.2)
Rem Управление перемещением камеры
If Upkey()=1
XTest# = Newxvalue(X#,CameraAngleY#,10)
ZTest# = Newzvalue(Z#,CameraAngleY#,10)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Downkey()=1
XTest# = Newxvalue(X#,Wrapvalue(CameraAngleY#-180),10)
ZTest# = Newzvalue(Z#,Wrapvalue(CameraAngleY#-180),10)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif

Yrotate camera CurveAngle(CameraAngleY#,OldCamAngleY#,24)
Xrotate camera CurveAngle(CameraAngleX#,OldCamAngleX#,24)

Y# = Get ground height(1,X#,Z#)
Position Camera X#,Y#+50,Z#
Rem Обновляем экран
Sync
Loop

Вы уже заметили, что мы используем тот же код, что и в предыдущем уроке. В последующих уроках мы продолжим "надстраивать" этот код, чтобы в итоге создать завершенную игру.
OldCamAngleY# = CameraAngleY#>
OldCamAngleX# = CameraAngleX#
CameraAngleY# = WrapValue(CameraAngleY#+MousemoveX()*0.2)
CameraAngleX# = WrapValue(CameraAngleX#+MousemoveY()*0.2)
Здесь в основном цикле мы сохраняем значения углов поворота камеры по осям Y и X в переменных "OldCamAngle" и после этого присваиваем новые значения переменным CameraAngle. Мы используем команду "WrapValue", чтобы значения углов находились в диапазоне от 0 до 360 градусов. Чтобы изменить значение переменных "CameraAngle", мы прибавляем к ним значения, возвращаемые командами "MouseMove", умноженные на поправочный коэффициент 0,2. Команды "MouseMoveX" и MouseMoveY()" возвращают относительное значение пространственных координат, на которое переместилась мышь с момента последнего считывания данных. Если быстро перемещать мышь вверх, вниз, вправо и влево, то возвращаемое значение будет намного больше, чем то, которое бы было при медленном перемещении мыши. Возвращаемое значение также зависит от размера экрана, используемого программой. Перемещение мыши со средней скоростью обычно возвращает значения от 8 до 16. Если эти значения прибавлять непосредственно к значениям углов поворота камеры, то скорость ее поворота будет слишком высокой. Нормализация этой величины путем умножения возвращаемого значения перемещения мыши на поправочный коэффициент 0,2 приводит к более приемлемым результатам.
Yrotate camera CurveAngle(CameraAngleY#,OldCamAngleY#,24)
Xrotate camera CurveAngle(CameraAngleX#,OldCamAngleX#,24)

Y# = Get ground height(1,X#,Z#)
Position Camera X#,Y#+50,Z#
После обработки всех значений, введенных с клавиатуры и мыши, мы поворачиваем камеру при помощи команд поворота камеры, используя команду "CurveAngle" для плавного перехода от старого угла положения камеры к новому. Первый параметр этой команды - новое значение угла, на который мы желаем повернуть камеру. Второй параметр - текущий угол поворота камеры. Третий параметр - скорость, с которой мы желаем перейти от старого к новому положению камеры. Команда "CurveAngle" изменяет это значение по кривой, в результате чего значение, используемое для вращения, находится в промежутке между старым и новым значением.
Заметьте интересный эффект поворота камеры, получаемый путем замены следующих двух строки кода
OldCamAngleY# = CameraAngleY#
OldCamAngleX# = CameraAngleX#
на
OldCamAngleY# = Camera Angle Y()
OldCamAngleX# = Camera Angle X()
с использованием команд "Camera Angle".
. Боковое движение (стрейфинг)
Цель урока: Показать способ реализации бокового движения (стрейфинга).
Боковое движение (стрейфинг) - это отличный способ ловко уходить от ракет или в движении просматривать боковые пространства. Мы продемонстрируем, как реализовать этот режим с использованием клавиш "стрелка вправо" и "стрелка влево". Здесь мы приводим только ту часть кода, которая претерпела изменения по сравнению с предыдущим уроком. По мере добавления новых возможностей в нашей игре, код становится слишком большим, чтобы приводить его целиком.


If Leftkey()=1
XTest# = Newxvalue(X#,Wrapvalue(CameraAngleY#-90),10)
ZTest# = Newzvalue(Z#,Wrapvalue(CameraAngleY#-90),10)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Rightkey()=1
XTest# = Newxvalue(X#,Wrapvalue(CameraAngleY#+90),10)
ZTest# = Newzvalue(Z#,Wrapvalue(CameraAngleY#+90),10)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
Боковое движение реализуется с помощью команд "NewXValue" и "NewYValue", предназначенных для определения значений X# и Z# следующей позиции. Для определения координат перемещения влево, мы сначала вычитаем 90 градусов из текущего значения угла поворота камеры "CameraAngleY#", чтобы обозначить направление движения. Чтобы значение угла не превышало 360 градусов, мы применяем команду "WrapValue". Используя значение этого угла в командах "NewValue", мы определяем координаты точки, находящейся в 10 единицах пространственных координат левее. Новые координаты сохраняются в переменных "XTest" и "ZTest". Затем производится проверка этих переменных, чтобы убедиться, что новые значения находятся в пределах матрицы. Если проверка оканчивается успешно, то новые значения сохраняются в переменных "X#" и "Y#" и используются для перемещения камеры. Как вы помните из урока I:2, ось Y проходит от верхней к нижней части экрана, поэтому любой поворот вокруг оси Y будет параллельным
4. Стрельба
Цель урока: показать, как реализовать стрельбу в режиме вида от первого лица.
В этом уроке объясняется, как создать оружие и стрелять из него в режиме вида от первого лица. Как и в предыдущем уроке, мы добавляем новые строки к существующему коду. Мы обсудим только изменения в коде, связанные с реализацией оружия и стрельбы.
rem Создаем пушку
Make object cylinder 1,2
XRotate Object 1,90
Fix object pivot 1
Scale object 1,100,100,500
position object 1,0,-7,15
Lock object on 1
Эта часть кода, помещенная перед основным циклом, создает цилиндрический объект и поворачивает его под прямым углом по отношению к установленному по умолчанию виду из камеры. Чтобы сделать такую ориентацию объекта ориентацией по умолчанию, мы используем команду "Fix Object Pivot". Это означает, что углы поворота повернутого объекта устанавливаются равными 0 без смены ориентации объекта. Эта команда часто используется для загрузки моделей с нефиксированной ориентацией. Если загружается модель персонажа, а он лежит лицом вниз, то с помощью этой команды можно повернуть модель так, что персонаж будет стоять. Точка вращения объекта фиксируется для того, чтобы сделать текущее положение объекта положением по умолчанию. После выравнивания объекта по отношению к камере, мы используем команду "Scale Object" для масштабирования объекта в направлении оси Z. Таким образом, создается объект - вытянутый ствол пушки. Первый параметр этой команды - номер объекта для масштабирования. Следующие три параметра команды - направления X, Y и Z, в которых мы хотим масштабировать объект. Мы устанавливаем значение масштабирования по осям X и Y равным 100, что не приводит к изменению масштаба объекта в этих направлениях, так как эта величина представляет собой процентное отношение (100%). Масштабирование по оси Z мы указываем равным 500. Это означает, что размер объекта по оси Z будет увеличен в пять раз. Затем мы позиционируем объект. По умолчанию камера установлена в позицию с координатами (0,0,0) и углами поворота (0,0,0). Мы размещаем цилиндр на 7 единиц пространственных координат ниже камеры и на 15 единиц впереди камеры. Таким образом, создается сходство со стволом пушки.
Rem Создаем снаряд
Make Object Sphere 2,2
Hide Object 2
Этот код создает небольшой сферический объект, применяемый в игре в качестве снаряда. Чтобы скрыть объект, мы используем команду "Hide Object". Причина, по которой мы это делаем, заключается в том, что снаряд не должен быть виден до тех пор, пока мы не выстрелим из пушки.
if Mouseclick()=1 and BulletLife=0
Position object 2,X#,Y#+43,Z#
Set object to camera orientation 2
BulletLife =25
show object 2
Endif
В этой части кода описывается ввод данных при нажатии кнопки мыши. Затем задаются координаты снаряда при выстреле из пушки. Чтобы определить, была ли нажата кнопка мыши, мы используем команду "MouseClick()". Эта команда возвращает номер нажатой кнопки мыши: 1 - для левой кнопки, 2 - для правой, и 0 - если ни одна из кнопок не была нажата. Сравнение "if" также проверяет, не был ли снаряд уже выпущен, сравнивая значение переменной "BulletLife" с 0. Если обе проверки проходят успешно, то объект "снаряд" помещается на семь единиц ниже камеры. После этого он позиционируется по отношению к камере при помощи команды "Set Object To Camera Orientation". Эта команда имеет только один параметр - номер позиционируемого объекта. Так как снаряд только что создан, мы устанавливаем значение переменной "BulletLife" равным 25. Чтобы программа произвела рендеринг объекта-снаряда, используем команду "Show Object".
If BulletLife > 0
Dec BulletLife
Move object 2,20
if BulletLife = 0 then Hide object 2
Endif
Эта часть кода отвечает за перемещение снаряда. Если значение переменной "BulletLife" больше нуля, то выполняется команда "Dec", уменьшающая это значение на единицу. Одновременно снаряд перемещается в направлении выстрела на 20 единиц. Затем снова проверяем значение переменной "BulletLife". Если оно равно 0, то "жизнь" снаряда закончилась и мы снова "прячем" этот объект.
Теперь вы можете добавить стрельбу в вашу игру.
5. Обычный звук и 3D-звук
Цель урока: показать, как загрузить и позиционировать источники 3D-звука.
В предыдущем уроке мы показали, как можно создать снаряд и стрелять. А сейчас добавим звуковые эффекты, чтобы выстрел в игре был более натуральным. Поскольку мы будем достаточно часто использовать переменные "CameraAngle", мы сократили их до аббревиатуры "cA" для удобства чтения кода.
Load sound "crickets.wav",1
Loop sound 1
Прежде чем мы рассмотрим 3D-звук, нам не помешает добавить в игру какой-нибудь звук окружающей среды. Команда "Load Sound" загружает звук в программу, но не воспроизводит его. Первый параметр этой команды - имя загружаемого звукового файла. Как и в любой другой команде, где требуется указывать имя файла, имя файла должно быть заключено в кавычки. Второй параметр команды - присвоенный этому звуку номер. DarkBASIC использует этот номер точно так же, как и при загрузке объектов или изображений. Номер является уникальным идентификатором для этого звука. Команда "Loop Sound" использует один параметр, номер воспроизводимого звука. Эта команда постоянно воспроизводит указанный звуковой файл. Понадобилось всего две команды, чтобы озвучить игру стрекотанием сверчков!
Load 3Dsound "fireball2.wav",2
Команда "Load 3DSound" загружает звук выстреливаемого снаряда. Первый параметр этой команды - имя загружаемого звукового файла, а второй параметр - присвоенный этому звуку номер. Загружая трехмерный звук, мы сообщаем DarkBASIC, что желаем поместить источник звука в определенной точке 3D-сцены.
Rem Поворачиваем камеру
if cAX#>270
if cAX#-270 > 90 then cAX#=270
else
if cAX# > 90 and cAX#-270<270 then cAX#=90
endif
YRotate camera CurveAngle(cAY#,oldcAY#,24)
XRotate camera CurveAngle(cAX#,oldcAX#,24)
Эта часть кода добавлена в игровую программу для того, чтобы игрок случайно не перевернул камеру. Углы камеры также должны содержать корректную информацию для правильного позиционирования слушателя 3D-звука.
Rem Позиционируем слушателя
Position Listener X#,Y#+50,Z#
Rotate Listener 0,cameraAngleY#,0
Команда "Position Listener" используется для позиционирования источника звука. Три параметра после команды обозначают координаты X, Y и Z, где вы хотите поместить слушателя. Мы будем использовать ту же позицию, в которой расположена камера. Команда "Rotate Listener" служит для поворота слушателя. Ее параметры - это углы X, Y и Z. Чтобы направление слушателя совпадало с направлением камеры, мы оставим значения углов X и Z равными 0, и будем учитывать только вращение вокруг оси Y. Для определения значения Y используем переменную "CameraAngleY#".
Rem Выстреливаем снаряд
if Mouseclick()=1 and BulletLife=0
Position object 2,X#,Y#+43,Z#
Set object to camera orientation 2
BulletLife =25
show object 2
Loop sound 2
Endif
В код, где мы проверяем, была ли нажата кнопка мыши, мы добавили команду "Loop sound", чтобы начал воспроизводиться звук выстреливаемого снаряда. Этот звук будет длиться до тех пор, пока не будет остановлен кодом, который проверяет время "жизни" снаряда.
If BulletLife > 0
Dec BulletLife
Move object 2,20
bX#=Object position X(2)
bY#=Object position Y(2)
bZ#=Object position Z(2)
Position sound 2,bX#,bY#,bZ#
if BulletLife = 0
Hide object 2
stop sound 2
endif
Endif
В код стрельбы мы добавили две команды для обработки позиции и окончания звука. Команда "Position Sound" используется для размещения звука летящего снаряда в указанных 3D-координатах. Первый параметр этой команды - номер позиционируемого звука. Следующие три параметра определяют позицию, в которую помещен источник звука. Мы получили значения координат X, Y и Z снаряда и сохранили их в переменных "'bX#", "bY#" и "bZ#". Это и есть значения, используемые нами для позиционирования источника звука снаряда. Как только программа определит, что величина "BulletLife" достигла значения 0, применяется команда "Stop Sound" для прекращения воспроизведения звука.
6. Математические столкновения
Цель урока: показать, как реализовать простые математические столкновения.
Сейчас мы объясним, как использовать математические столкновения для проверки столкновения снаряда и цели. Математическое столкновение вычисляется быстрее обычного столкновения, так как последнее должно проверить большее число объектов в программе. Применив простую функцию математического столкновения, мы можем узнать, насколько близко снаряд находится от цели. Если расстояние между ними достаточно мало, мы можем с достаточной уверенностью сказать о том, что они столкнулись.

If BulletLife > 0
Dec BulletLife
Move object 2,20
bX#=Object position X(2)
bY#=Object position Y(2)
bZ#=Object position Z(2)
Position sound 2,bX#,bY#,bZ#
set cursor 10,10
if Sqrt((mX# - bX#)^2 + (mY#+25 - bY#)^2 + (mZ# - bZ#)^2) <20
text 240,220 ,"Цель поражена"
BulletLife = 0
endif
if BulletLife = 0
Hide object 2
stop sound 2
endif
Endif
Следующие строки добавлены в ту часть кода, в которой проверяется время "жизни" снаряда.
if Sqrt((mX# - bX#)^2 + (mY#+25 - bY#)^2 + (mZ# - bZ#)^2) <20
text 240,220 ,"Цель поражена"
BulletLife = 0
endif
Это сравнение использует математическую функцию "Sqrt" для расчета расстояния между двумя объектами. Если расстояние меньше 20, то на экран выводится сообщение о том, что игрок поразил цель, и объект-снаряд прекращает свое существование путем установки времени "жизни" снаряда равным 0. Функция математического столкновения вычитает из значения координаты X цели, которое хранится в переменной mX#, значение координаты X снаряда. Затем это число умножается само на себя при помощи экспоненциальной операции " ^ ". Аналогичные вычисления осуществляются в отношении координат Y и Z. Заметьте, что мы добавили 25 к координате Y цели, так как это будет примерно соответствовать координате середины стоящей цели. Полученные значения складываются, и вычисляется квадратный корень полученной суммы. Окончательное значение можно рассматривать как расстояние между двумя объектами. Советуем запомнить эту строку кода на случай, если вам когда-либо потребуется определять расстояние между двумя точками в 3D-сцене.
Если вы не знакомы с квадратными корнями и экспонентами, вам придется обратиться к справочнику по математике, чтобы в деталях уяснить, как вычисляется расстояние. Знание того, чем являются переменные и значение, рассчитываемое по формуле, должно помочь вам в дальнейшем использовать эту часть кода в ваших собственных программах.
7. Эффект шлейфа (particle system)
Цель урока: создание простого эффекта шлейфа.
В этом уроке мы объясним, как сделать хвост из огня и дыма с использованием простого эффекта шлейфа. Шлейф определяется как совокупность объемных частиц, движущихся в соответствии с неким набором правил. Правила могут определять положение, скорость, направление движения, цвет, вращение, форму, размер, прозрачность и многие другие атрибуты, используемые для создания таких эффектов, как дым, огонь, водопад или рост листьев на дереве. Применение шлейфа помогает создавать многочисленные реалистичные эффекты. Для наших объемных частиц мы будем использовать плоский объект с текстурой огня и дыма. Настраиваемые свойства - это положение, размер, прозрачность и угол поворота.
rem Загружаем частицы (шлейф)
Load Image "fire.bmp",2
For x = 0 to 10
Make object plain x+10,5,5
Texture object x+10,2
Set object x+10,1,0,0
Ghost object on x+10
Next x
rem Включаем счетчик частиц
Pn=10
Эту часть кода следует поместить в начале программы, где мы загружаем все наши объекты и звуки. Прежде всего, загружаем текстуру для частиц и создаем десять плоских объектов. Команда "Set Object" используется для установки особых свойств объекта. Семь настраиваемых свойств объекта - это каркас, прозрачность, выбраковка, фильтр, источник света, туман и окружение. Нам потребуются только три из них: каркас, прозрачность и выбраковка. Первый параметр после команды - номер используемого объекта. Второй параметр - атрибут каркаса. Устанавливаем его равным 1, чтобы объект отображался заполненным полигонами, а не в виде каркаса. Это установки по умолчанию для большинства 3D-объектов. Третий параметр - атрибут прозрачности. Мы устанавливаем его равным 0. В данном контексте прозрачность означает, что черный цвет на растровых изображениях не будет показан при текстурировании объекта. Четвертый параметр - атрибут выбраковки. Этот параметр устанавливается равным 0, если в 3D-сцене требуется рендеринг обеих, видимой и обратной, сторон полигона. Обычно требуется рендеринг только одной стороны полигона. В большинстве случаев нет необходимости прорисовывать обе стороны, но поскольку мы используем плоский объект, не имеющий объема, то должны все-таки сделать это, чтобы наблюдатель мог видеть полигон отовсюду. Еще одна новая команда "Ghost Object" применяется для того, чтобы сделать объект прозрачным. При этом он появится подобно привидению. С помощью этой команды можно включать и выключать режим прозрачности. Команда использует один параметр - номер объекта, который надо сделать прозрачным. Мы также инициализируем переменную "Pn", и она становится равной номеру первой созданной нами частицы. Переменная "Pn" будет использоваться для хранения номера следующей обрабатываемой частицы.
If BulletLife > 0
Dec BulletLife
Move object 2,10
bX#=Object position X(2)
bY#=Object position Y(2)
bZ#=Object position Z(2)
Rem Шлейф частиц
inc Pn
if Pn=20 then Pn=10
Scale object Pn,100,100,100
Position object Pn,bX#,bY#,bZ#
point object Pn,X#,Y#,Z#
Zrotate object Pn,rnd(180)
for x = 1 to 10
scale object int((Wrapvalue((Pn-9+x)*36))/36)+10,100+x*25,100+x*25,100+x*25
set cursor 10,10
print int((Wrapvalue((Pn+x)*36))/36)+10
next x
Position sound 2,bX#,bY#,bZ#
set cursor 10,10
if Sqrt((mX# - bX#)^2 + (mY#+25 - bY#)^2 + (mZ# - bZ#)^2) <20
print "Цель поражена"
BulletLife = 0
endif
if BulletLife = 0
Hide object 2
stop sound 2
endif
Endif
Здесь мы добавили простой шлейф в часть игрового кода, вычисляющую время "жизни" снаряда.
inc Pn
if Pn=210 then Pn=10
Scale object Pn,100,100,100
Position object Pn,bX#,bY#,bZ#
point object Pn,X#,Y#,Z#
Zrotate object Pn,rnd(180)
for x = 1 to 10
scale object int((Wrapvalue((Pn-9+x)*36))/36)+10,100+x*25,100+x*25,100+x*25
next x
Когда снаряд начинает свою "жизнь", мы увеличиваем значение переменной "Pn", чтобы задействовать следующий объект системы частиц в множестве. Затем проверяем, не превысило ли значение переменной "Pn" числа созданных нами частиц, и если превысило, устанавливаем "Pn" равным 10. Возвращаем масштаб частицы в первоначальное значение и помещаем ее туда, где находится снаряд. Затем направляем частицу на камеру и поворачиваем ее на угол со случайным значением. Затем в цикле For … Next с помощью математической формулы масштабируем каждую частицу, чтобы казалось, что дым рассеивается. Попутно решаем задачу, какая частица находится в начале хвоста дыма, а какая - в его конце. Для этого воспользуемся уже знакомой командой "WrapValue". Обычно она применяется для того, чтобы значения углов не превышали 360 градусов. Так как мы используем 10 объектов, то вычитаем 9 из значения "Pn". Величина "Pn" всегда будет меняться от 10 до 19, что соответствует 10 объектам. Затем мы добавляем значение переменной "х" и умножаем все на 36. Если значение "Pn" равно 5, и мы находимся на шестой итерации цикла, тогда значение параметра "WrapValue" будет равно 11, помноженному на 36, или 396. Эта величина явно превышает 360, поэтому функция "WrapValue" делает значение переменной равным 36. Затем мы делим 36 на 36 и получаем значение 1. Оно является номером следующей после десятого объекта частицы, которая будет первой.
По существу, этот алгоритм последовательно, циклически перебирает все значения от 1 до 10, причем неважно, с какого значения мы начали. Поиск необычных решений трудных задач - неотъемлемая часть программирования. Можно по-разному решить задачу, и наиболее простой способ часто оказывается наилучшим. Этот пример также показывает вам, что вы не обязаны использовать команды DarkBASIC каким-то одним определенным способом. Нетрадиционное мышление приводит ко многим необычным решениям. Каждый объект масштабируется в соответствии с его позицией в хвосте дыма, представленной значением переменной цикла. Это дает эффект рассеивающегося дыма.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 307
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 09:24. Заголовок: Re:


III. ИГРА
8. Gosub
Цель урока: показать действие команды Gosub.
В этом уроке мы продемонстрируем действие команды "Gosub". Мы будем использовать "Gosub" для того, чтобы упорядочить и упростить программу, когда начнем добавлять к ней большое количество функций, а также чтобы сделать более понятным то, что происходит в ее основном цикле.
If BulletLife > 0 then Gosub ShootBullet
Мы заменили несколько строк кода для проверки времени "жизни" снаряда всего одной строкой. Команда "Gosub" применяется для того, чтобы выполнить код, расположенный в другом месте программы, а затем вернуться туда, откуда был произведен вызов команды "Gosub". Здесь мы вызываем подпрограмму "ShootBullet".
ShootBullet:
Dec BulletLife
Move object 2,10
bX#=Object position X(2)
bY#=Object position Y(2)
bZ#=Object position Z(2)
inc Pn
if Pn=21 then Pn=10
Scale object Pn,100,100,100
Position object Pn,bX#,bY#,bZ#
point object Pn,X#,Y#,Z#
Zrotate object Pn,rnd(180)
for x = 1 to 10
scale object int((Wrapvalue((Pn-9+x)*36))/36)+10,100+x*25,100+x*25,100+x*25
set cursor 10,10
next x
if bY# < Get Ground height(1,bX#,bZ#) then BulletLife=0
Position sound 2,bX#,bY#,bZ#
set cursor 10,10
if Sqrt((mX# - bX#)^2 + (mY#+25 - bY#)^2 + (mZ# - bZ#)^2) <20
print "Цель поражена"
BulletLife = 0
endif
if BulletLife = 0
Hide object 2
stop sound 2
for x=10 to 20
hide object x
next x
Explode = 20
endif
Return
Чтобы объявить подпрограмму, ей нужно задать уникальное имя и расположить его в начале подпрограммы. После имени подпрограммы нужно поставить двоеточие, иначе имя не будет распознано, что вызовет ошибку. В том месте, где заканчивается код подпрограммы, следует поместить команду "Return", чтобы исполнение кода было продолжено с того места, откуда была вызвана подпрограмма. Этот метод значительно уменьшает беспорядок в основном цикле, позволяя легче понять, что в нем происходит. Четко разработав структуру подпрограмм, вы избавите себя от многих часов головной боли по поводу упорядочивания структуры вашего
9. Эффект взрыва
Цель урока: создание простого эффекта взрыва.
В этом уроке мы покажем, как создать простой эффект взрыва, когда снаряд попадает в цель, в землю или просто заканчивается время его "жизни".
rem Создаем эффект взрыва
Make Object Sphere 30,20
texture object 30,2
ghost object on 30
Hide Object 30
Make Object Sphere 31,20
texture object 31,2
ghost object on 31
Hide Object 31
Load 3Dsound "Explode.wav",3
Эти строки кода надо поместить в начало программы, где мы загружаем объекты, звуки и изображения. Здесь мы создаем объекты, используемые для эффекта взрыва. Заметьте, что мы применяем ту же текстуру, что и для создания огня в шлейфе. Мы также загрузили звуковой файл, который будем использовать в качестве источника звука взрыва.
if Mouseclick()=1 and Explode =0
if BulletLife<50
Position object 2,X#,Y#-7,Z#
Set object to camera orientation 2
BulletLife =120
show object 2
Loop sound 2
Endif
Endif
Как видите, мы добавили в программу переменную "Explode". Проверяем, не произошел ли взрыв. Если взрыв происходит в данный момент, то не будем выстреливать еще один снаряд, потому что это может резко обрезать звук взрыва, уменьшая действие эффекта. Мы также установили интервал, через который снаряд может быть снова выпущен. Новый снаряд можно будет выстрелить, если при проверке окажется, что время "жизни" снаряда меньше 50. Это сделано для того, чтобы убедиться, что снаряд находится достаточно далеко, и отсутствие эффекта взрыва не будет замечено игроком.
if bY# < Get Ground height(1,bX#,bZ#) then BulletLife=0
Эта строка кода находится в подпрограмме "ShootBullet". Она проверяет, не попал ли снаряд в землю, и устанавливает значение переменную "BulletLife" равное 0 при положительном результате.
if BulletLife = 0
Hide object 2
stop sound 2
for x=10 to 20
hide object x
next x
Explode = 20
endif
Эта часть кода также находится в подпрограмме "ShootBullet". Код выполняется после того, как время "жизни" снаряда установлено равным 0, либо по причине столкновения с чем-либо, либо по причине окончания "жизни" снаряда. При этом убираются все объекты шлейфа, равно как и сам объект "снаряд". Переменной взрыва присвоено значение 20 для начала отсчета взрыва.
If Explode > 0 then Gosub ExplodeRocket
Эта строка кода располагается в нашем основном цикле. Если счетчик взрыва больше 0, то для выполнения кода взрыва вызывается подпрограмма "ExplodeRocket".
Rem Взрыв снаряда
ExplodeRocket:
Position object 30,bX#,bY#,bZ#
Show object 30
Position object 31,bX#,bY#,bZ#
Show object 31
EScale=20*(30-Explode)
Scale object 30,EScale,EScale,EScale
Yrotate object 30,WrapValue(Explode*37)
Scale object 31,EScale/1.5,EScale/1.5,EScale/1.5
Yrotate object 31,WrapValue(359-Explode*37)
Dec Explode
If Explode = 0 then hide object 30: Hide object 31
If Explode=18
position sound 3,bX#,bY#,bZ#
play sound 3
endif
If Explode < 15 then position sound 3,X#,Y#,Z#
Return
Подпрограмма "ExplodeRocket" производит взрыв. В место попадания снаряда мы помещаем две сферы, созданные для эффекта взрыва. Затем мы рассчитываем коэффициент масштабирования взрыва и сохраняем его в переменной "EScale". Затем масштабируем первую сферу и вращаем ее со скоростью, уменьшающейся по мере того, как сфера становится больше. То же самое мы делаем со второй сферой, только ее мы масштабируем с меньшей скоростью, чем первую сферу, а вращаем с большей скоростью, основанной на значении "Explode". После этого мы применяем команду "Dec" для уменьшения значения "Explode" на единицу. Потом проверяем, равно ли значение этой переменной 0. Если оно равно 0, обе сферы взрыва убираются. Заметьте, что мы использовали двоеточие, чтобы выполнить две команды "HideObject" в одной строке. Мы могли бы применить сравнение "If … EndIf", но двоеточие в качестве разделителя делает наш код короче и легче читаемым. Следующие строки кода создают звуковой эффект, когда вы сначала видите, как что-то происходит вдали, а затем слышите взрыв. Далее код задает ожидание, пока значение счетчика не достигнет 18, и только после этого начинает воспроизводить звук. Программа помещает источник звука в конечной точке полета снаряда. Когда счетчик достигает 15, источник звука перемещается в координаты камеры, что создает эффект отдаленного взрыва. За счет того, что используется команда "Play Sound", а не "Loop Sound", звук воспроизводится только один раз.
10. Монстр отстреливается
Цель урока: показать, как создать игровую ситуацию, когда монстр начинает отстреливаться.
В этом уроке мы создадим управляемую ракету монстра, а также определим метод, с помощью которого монстр сможет определить местонахождение игрока.
rem Создаем снаряд монстра
Make Object Sphere 102,2
texture object 102,2
Hide Object 102
Эта часть кода, создающая сферу для ракеты монстра, помещается в программе до основного цикла. Заметьте, что в качестве текстуры объекта мы используем текстуру под номером 2. Эта та же самая текстура, которую мы применяли для ракеты игрока и других эффектов. Повторное применение текстур сокращает объем памяти, используемой вашей программой.
rem Создаем эффект взрыва для монстра
Make Object Sphere 130,20
texture object 130,2
ghost object on 130
Hide Object 130
Make Object Sphere 131,20
texture object 131,2
ghost object on 131
Hide Object 131
Этот код также вставляется в программу до основного цикла. Он создает объекты взрыва для ракеты монстра.
rem Загружаем шлейф ракеты монстра
Load Image "fire.bmp",2
For x =100 to 110
Make object plain x+10,5,5
Texture object x+10,2
Set object x+10,1,0,0
Ghost object on x+10
Hide object x+10
Next x
MPn=110
Как вы заметили, эта часть кода взята из эффекта шлейфа снаряда игрока. Сам код остался прежним, изменились только номера объектов. Счетчик частиц шлейфа ракеты монстра "MPn" установлен в значение 110, что соответствует номеру первого объекта в совокупности частиц этого шлейфа.
Load 3Dsound "fireball2.wav",102
Load 3Dsound "Explode.wav",103
Этот код загружает звуковые эффекты для ракеты монстра. Заметьте, что мы не задействовали повторно звуковые эффекты, использованные ранее для снаряда игрока. Мы загрузили новые звуки, потому что звуковые эффекты для снарядов игрока и монстра могут воспроизводиться одновременно.
If MonsterBulletLife > 0 then Gosub MonsterShootBullet
If MonsterExplode > 0
Gosub MonsterExplodeRocket
else
Gosub MonsterAI
endif
Этот код помещается в нашем основном цикле. Здесь производится проверка времени "жизни" ракеты монстра, продолжительности ее взрыва и выполняются соответствующие подпрограммы, как и в отношении снаряда игрока. Добавилась лишь подпрограмма "MonsterAI". Мы ведь не хотим, чтобы монстр пытался стрелять в то время, когда взрывается предыдущий снаряд. Чтобы убедиться, что этого не происходит, мы используем сравнение "If Then Else".
Rem Простой AI для управляемой ракеты монстра
MonsterAI:
Point object 3,X#,Y#,Z#
PDist=Sqrt((mX# - X#)^2 + (mY#+25 - Y#)^2 + (mZ# - Z#)^2)
if PDist<1500
if MonsterBulletLife=0 or MonsterBulletLife < 500-PDist/10
Point object 3,X#,Y#-25,Z#
Position object 102,mX#,mY#+25,mZ#
Set object to object orientation 102,3
MonsterBulletLife =500
show object 102
Loop sound 102
Endif
endif
Return
Когда вызывается подпрограмма"MonsterAI", объект "монстр" направлен прямо на игрока. Рассчитывается расстояние между игроком и монстром. Если оно меньше 1500, то продолжается выполнение кода. Если игрок находится вне зоны видимости, ничего не происходит и подпрограмма далее не выполняется, а продолжает выполняться код из основного цикла. Если игрок находится в пределах досягаемости, программа проверяет, не закончилось ли время "жизни" ракеты и не попала ли она в игрока. Способ, с помощью которого мы проверяем, попала ли ракета в цель, заключается в вычислении значения "500-PDist/10". Ракета монстра пролетает 12 единиц координат в единицу своей "жизни". Время ее жизни составляет 500, таким образом, она может преодолеть расстояние в 6000 единиц. Если мы разделим расстояние, или величину переменной "PDist", на 12, то получим число единиц "жизни", которое ракета монстра затратила на подлет к игроку. Если расстояние между монстром и игроком составляет 1200 единиц, то необходимое на подлет к игроку число единиц "жизни" ракеты будет равно 100. Если мы вычтем эту величину из общего числа единиц "жизни" ракеты, то получим 400. Если это значение больше, чем значение переменной "MonsterBulletLife", тогда мы знаем, что ракета не попала в игрока. Мы делим расстояние на 12, а не на 10, что позволяет снаряду пролететь немного дальше, прежде чем можно будет выстрелить еще раз. Это делает игру более реалистичной, позволяя ракете пролететь мимо игрока. Если значение переменной "MonsterBulletLife" позволяет выстрелить еще раз, ракета монстра нацеливается прямо на координаты игрока. Ракете монстра задаются начальные и конечные координаты, устанавливается время ее "жизни" равное 500, объект "ракета" становится видимым и начинает воспроизводиться ее звук.
Rem Выстрел ракеты монстра
MonsterShootBullet:
Dec MonsterBulletLife
Move object 102,12
MbX#=Object position X(102)
MbY#=Object position Y(102)
MbZ#=Object position Z(102)
inc MPn
if MPn=121 then MPn=110
Scale object MPn,100,100,100
Position object MPn,MbX#,MbY#,MbZ#
Position sound 102,MbX#,MbY#,MbZ#
point object MPn,X#,Y#,Z#
Zrotate object MPn,rnd(180)
Show object MPn
for x = 1 to 10
scale object int((Wrapvalue((MPn-9+x)*36))/36)+110,100+x*25,100+x*25,100+x*25
next x
if MbY# < Get Ground height(1,MbX#,MbZ#) then MonsterBulletLife=0
Pdist=Sqrt((X# - MbX#)^2 + (Y#+25 - MbY#)^2 + (Z# - MbZ#)^2)
if Pdist<50
GoSub PlacePlayer
MonsterBulletLife = 0
endif
Rem Управляемая ракета
if Pdist <500 and Pdist>250 then Point object 102,X#,Y#,Z#
if Pdist < 100 then point object 102,X#,Y#,Z#
if MonsterBulletLife = 0
Hide object 102
stop sound 102
for x=110 to 120
hide object x
next x
MonsterExplode = 20
endif
Return
Подпрограмма "MonsterShootBullet" очень похожа на подпрограмму "ShootBullet", однако мы добавили несколько строк для того, чтобы сделать ракету монстра управляемой. Это создает игровое напряжение и бросает вызов игроку, пытающемуся уклониться от ракеты монстра.
Rem Управляемая ракета самонаведения
if Pdist <500 and Pdist>250 then Point object 102,X#,Y#,Z#
if Pdist < 100 then point object 102,X#,Y#,Z#
Это код для управляемой ракеты самонаведения. Если ракета находится на расстоянии от 500 до 250 единиц от игрока, она самонаводится по текущим координатам игрока. Находясь на расстоянии 100 единиц от игрока, ракета снова получает текущие координаты цели. Это дает игроку немного времени на попытку уклониться от ракеты.
Rem Взрыв ракеты монстра
MonsterExplodeRocket:
Position object 130,MbX#,MbY#,MbZ#
Show object 130
Position object 131,MbX#,MbY#,MbZ#
Show object 131
EScale=20*(30-MonsterExplode)
Scale object 130,EScale,EScale,EScale
Yrotate object 130,WrapValue(MonsterExplode*37)
Scale object 131,EScale/1.5,EScale/1.5,EScale/1.5
Yrotate object 131,WrapValue(359-MonsterExplode*37)
Dec MonsterExplode
If MonsterExplode = 0 then hide object 130: Hide object 131
If MonsterExplode=18
position sound 103,X#,Y#,Z#
play sound 103
endif
If MonsterExplode < 15 then position sound 103,X#,Y#,Z#
Return
Код подпрограммы "MonsterExplodeRocket" такой же, как и в подпрограмме "ExplodeRocket". Единственное, что отличает эти две подпрограммы - это переменные координат ракеты монстра и номера объектов и звуков.
11. Как вести счет
Цель урока: показать, как ведется счет игры.
В этом уроке мы покажем, как отслеживать счет игры для игрока и монстра, а также как перемещать игрока и монстра в новое положение, когда их поражает снаряд или ракета.
Gosub PlaceMonster
Gosub PlacePlayer
Мы поместили две команды "Gosub" до основного цикла. Соответствующие подпрограммы помещают игрока и монстра на случайные позиции матрицы.
PlaceMonster:
mX#=X#
mZ#=Z#
mY#=Y#
While Sqrt((X# - MX#)^2 + (Y#+25 - MY#)^2 + (Z# - MZ#)^2)<1600
mX#=rnd(10000)
mZ#=rnd(10000)
mY#= get ground height(1,mX#,mZ#)
EndWhile
Position object 3,mX#,mY#,mZ#
Return
Подпрограмма "PlaceMonster", предназначенная для установки случайных координат монстра на матрице, первоначально устанавливает для монстра те же координаты, что и координаты игрока и затем проверяет, чтобы монстр и игрок находились на достаточном расстоянии друг от друга. Первоначальная установка одинаковых координат является необходимым условием для генерации случайной позиции. В тексте этой подпрограммы мы используем цикл "While", чтобы обеспечить определенное условие: цикл повторяется до тех пор, пока расстояние между игроком и монстром не станет больше 1600. Для вычисления расстояния между игроком и монстром мы используем формулу вычисления расстояний из урока по математическому столкновению. Если расстояние меньше 1600, снова выполняется код поиска позиции. Новая случайная позиция рассчитывается и сохраняется в переменных положения монстра. Когда расстояние между игроком и монстром становится больше 1600, цикл завершается и монстр помещается в новом месте.
PlacePlayer:
While Sqrt((X# - mX#)^2 + (Y#+25 - mY#)^2 + (Z# - mZ#)^2)<1000
X#=rnd(10000)
Z#=rnd(10000)
Y#= get ground height(1,X#,Z#)
EndWhile
Position camera X#,Y#,Z#

Return
Подпрограмма "PlacePlayer" аналогична подпрограмме "PlaceMonster". Различие только в том, что мы помещаем на матрицу игрока, а не монстра. Мы также направляем камеру в сторону монстра, чтобы его было легче найти.
set cursor 550,20
print "MScore: ",MonsterScore
set cursor 550,40
print "PScore: ",PlayerScore
Этот код помещается внутри основного цикла. Используя команду "Set cursor", помещаем текст в правой части экрана. В позиции курсора выводим слова "MScore" и "PScore", чтобы показать игровой счет монстра и игрока. Затем выводим значения переменных "MonsterScore" и "PlayerScore".
if Sqrt((mX# - bX#)^2 + (mY#+25 - bY#)^2 + (mZ# - bZ#)^2) <20
Gosub PlaceMonster
inc PlayerScore
MonsterBulletLife = 1
BulletLife=0
endif
Эта часть кода из подпрограммы "ShootBullet", которая проверяет, был ли монстр поражен снарядом игрока. Мы добавили в сравнение "If" две строки кода. Если монстр был поражен, вызывается подпрограмма "PlaceMonster", чтобы поместить его в новом месте. Затем мы увеличиваем счет игры в пользу игрока, изменяя переменную "PlayerScore" при помощи команды "Inc".
Pdist=Sqrt((X# - MbX#)^2 + (Y#+25 - MbY#)^2 + (Z# - MbZ#)^2)
if Pdist<50
GoSub PlacePlayer
MonsterBulletLife = 0
inc MonsterScore
endif
Эта часть кода из подпрограммы "MonsterShootBullet", которая, как и предыдущая, проверяет, был ли поражен игрок ракетой монстра. В случае поражения, вызывается подпрограмма "PlacePlayer", помещающая игрока в новом месте. После этого мы увеличиваем счет игры в пользу монстра при помощи команды "Inc" и возвращаемся в подпрограмму "MonsterShootBullet".
12. HUD
Цель урока: создание "вида сверху" и простого экрана радара.
В этом уроке мы покажем, как создать "вид сверху", также известный как HUD (heads up display). Чтобы упростить задачу поиска монстра, мы создадим экран радара на нашем виде сверху и прозрачный задний план для отображения счета игры.
rem Создаем HUD
Make object Plain 200,1,1
position object 200,-2.7,1.9,4
Lock object on 200
ghost object on 200
Эта часть кода помещается до основного цикла. Мы создаем плоский объект и привязываем его к положению камеры. Эта плоскость будет использоваться в качестве экрана радара.
Make object Plain 201,1,1
position object 201,2.7,1.9,4
Lock object on 201
ghost object on 201
Эта часть кода также вводится до основного цикла. Плоский объект будет использоваться в качестве заднего плана для экрана отображения счета игры.
rem Загружаем и создаем растровые изображения hud
Load Bitmap "Radar.bmp",2
Create Bitmap 1,50,50
В этой части кода мы загружаем изображение радара и сохраняем его как изображение под номером 2. Растровое изображение отличается от текстуры. На нем можно рисовать и оно может быть изменено в самой программе. Особенно важным является растровое изображение под номером 0. Это изображение становится вашим экраном, на котором вы видите 3D-сцену. При вызове команды "Sync" именно это изображение перерисовывается и отображается. Мы загружаем изображение "Radar.bmp" в изображение под номером 2 и создаем новое пустое изображение, присваивая ему номер 1. Имейте в виду, что в DarkBASIC можно загрузить или создать не более 32 изображений. Команда "Load Bitmap" аналогична команде "Load Image". Первый параметр - имя загружаемого растрового изображения. Второй параметр - присвоенный ему номер - уникальный идентификатор изображения. Команда "Create Bitmap" создает в памяти пустое изображение указанного размера. Первый параметр - номер, присваиваемый изображению. Второй и третий параметры - это ширина и высота создаваемого растрового изображения. Параметры ширины и высоты представляют собой размеры изображения в пикселах.
Rem Создаем радар
Copy Bitmap 2,1
set current bitmap 1
ink rgb(0,0,255),rgb(0,0,0)
PRX#=X#/200
PRZ#=50-(Z#/200)
Circle PRX#,PRZ#,1
ink rgb(255,0,0),rgb(0,0,0)
MRX#=mX#/200
MRZ#=50-(mZ#/200)
Circle MRX#,MRZ#,1
Get image 200,0,0,50,50
set current bitmap 0
texture object 200,200
ink rgb(255,128,128),rgb(0,0,0)
Этот код помещается ближе к концу основного цикла. Так создается, прорисовывается и накладывается на плоскость экран радара.
Copy Bitmap 2,1
Команда "Copy Bitmap" копирует одно растровое изображение из памяти в другое, также находящееся в памяти. Первый параметр этой команды - номер копируемого изображения. Второй параметр - номер изображения, в которое вы хотите скопировать первое. Здесь мы копируем изображение, загруженное для заднего плана экрана радара в изображение, которое мы будем использовать в качестве экрана радара.
set current bitmap 1
С помощью команды "Set Current Bitmap", вы указываете программе, что определенное изображение будет изображением для рисования по умолчанию. Чтобы вновь увидеть 3D-сцену, вы должны установить номер текущего изображения снова равным 0. Текущим мы делаем изображение радара. Оно содержит скопированное изображение, которое мы загрузили для заднего плана радара.
ink rgb(0,0,255),rgb(0,0,0)
Команда "Ink" применяется для установки значения цвета переднего и заднего плана для любой команды рисования или текста. Первый параметр команды "Ink" - это цвет, используемый для рисования на переднем плане. Чтобы указать голубой цвет, мы применяем команду "RGB". Второй параметр - цвет заднего плана, или фона. При помощи команды "RGB" мы устанавливаем для него черный цвет.
PRX#=X#/200
PRZ#=50-(Z#/200)
Circle PRX#,PRZ#,1
С помощью этих трех строк кода рисуется голубая окружность на изображении радара, представляющая игрока. Переменные "PRX#" и "PRZ#" используются для хранения координат игрока. Так как наша матрица - квадрат со стороной 100000 единиц, а растровое изображение радара - квадрат со стороной 50 пикселов, то мы делим 100000 на 50 и получаем 200. 200 - это переменная масштабирования. Мы делим значение координаты X игрока на 200, чтобы получить примерное значение координаты X на экране радара, и сохраняем эту величину в переменной "PRX#". Те же вычисления повторяем и для координаты по оси Z. Так как отсчет координат растрового изображения начинается в левом верхнем углу, а координат матрицы - в левом нижнем, мы берем масштабированное значение Z и вычитаем его из 50 для того, чтобы получить обращенное значение для экрана радара. Если этого не сделать, то экран радара будет отображать обращенные координаты.
Circle PRX#,PRZ#,1
Мы используем координаты X и Z игрока на радаре, чтобы с помощью команды "Circle" нарисовать окружность по этим координатам на изображении радара. Первые два параметра этой команды - это координаты X и Y центра окружности на изображении. Третий параметр - радиус окружности. Мы установили этот параметр равным 1, чтобы нарисовать очень маленький кружок.
ink rgb(255,0,0),rgb(0,0,0)
MRX#=mX#/200
MRZ#=50-(mZ#/200)
Circle MRX#,MRZ#,1
Эти строки кода аналогичны приведенным выше, только мы устанавливаем цвет красным и используем переменные X и Y монстра для рисования окружности, которая символизирует монстра на радаре.
Get image 200,0,0,50,50
Команда "Get Image" копирует изображение или его часть для использования в качестве текстуры. Первый параметр этой команды - это номер создаваемого изображения. Второй и третий параметры - координаты X и Y левого верхнего угла прямоугольной области, которую мы желаем скопировать. Четвертый и пятый параметры - координаты правого нижнего угла этой прямоугольной области. Так как наше изображение имеет размеры 50х50 пикселов, мы копируем изображение целиком. Наше основное изображение - это по-прежнему изображение под номером 1, откуда и копируется изображение для текстуры.
set current bitmap 0
texture object 200,200
ink rgb(255,128,128),rgb(0,0,0)
Последняя часть кода радара снова устанавливает в качестве текущего изображение под номером 0, в котором и происходит прорисовка нашей 3D-сцены. Затем мы накладываем на плоский объект текстуру из только что созданного изображения. Оно содержит картинку радара с нарисованными на ней двумя кружками, соответствующими игроку и монстру. Меняем цвет из красного на матовый красный. Этот цвет будет использоваться до обновления изображения на экране радара. Отметим, что значения счета в игре выводятся тем же цветом.
13. Столкновения с окружающими предметами
Цель урока: показать, как оживить 3D-экран путем добавления окружающих предметов.
В этом уроке мы добавим несколько колонн к нашему ландшафту. Мы также применим способ математического столкновения для расчета столкновений с этими колоннами.
rem Создаем окружающие объекты
load image "cottag02.bmp",300
t=300
For x = 1 to 9
For z = 1 to 9
Make object cube t,100
Scale object t,100,600,100
y = get ground height(1,x*1000,z*1000)
position object t,x*1000,y+275,z*1000
texture object t,300
scale object texture t,1,-6
inc t
next z
next x
Эта часть кода вводится до основного цикла, но после того, как создана матрица. Загружаем изображение, чтобы наложить текстуру на колонны. Переменной t присваиваем значение 300. Это номер первого объекта-колонны. Чтобы создать и расположить каждый из этих объектов, мы используем вложенный цикл. Нежелательно, чтобы колонны помещались на краях матрицы, поэтому вместо того, чтобы выполнять цикл от 0 до 10, выполняем его от 1 до 9. Цикл по оси "x" используется для размещения объектов на матрице. Цикл по оси "z" -для размещения объектов сверху и снизу матрицы. Внутри цикла "z" мы создаем объект-куб с помощью переменной t. Задаем значение масштабирования куба 600 по оси Y, чтобы получить высокую колонну. Затем получаем значение высоты ячейки матрицы в новых координатах X и Z. Заметьте, что для получения координат X и Z мы умножаем переменные цикла на 1000, благодаря чему мы сможем поместить колонны на матрице через равные интервалы. Затем мы помещаем объект в 3D-сцене. К величине Y добавляем значение 275. Это почти половина высоты объекта. Эта операция приподнимает его по оси Y, так как видимое основание объекта находится в его центре. Мы не поднимаем объект на все 300 единиц только потому, что хотим, чтобы он "врастал" в землю. Затем накладываем декоративную текстуру на объект. Текстура также масштабируется, чтобы полностью покрыть объект. Для этого используем отрицательное значение 6, а не положительное. Это обращение необходимо, чтобы изображение накладываемой текстуры было обычным, а не перевернутым. С помощью этой уловки можно переворачивать текстуру. Затем мы увеличиваем значение переменной "t", чтобы начать создание следующего объекта.
Rem Проверка столкновения с декоративными объектами
Function DecoCollide(X#,Y#,Z#)
for u = 1 to 9
for v = 1 to 9
if X#>u*1000-60
if X#v*1000-60
if Z#u*1000-60
if X#v*1000-60
if Z#0
mA# = Object Angle Y(3)
Dec AvoidDeco
Yrotate object 3,WrapValue(mA#+AvoidDeco*60)
endif
Rem Перемещаем монстра в новое место
Position Object 3,mX#,mY#,mZ#
Rem Проверяем расстояние до игрока
PDist=Sqrt((mX# - X#)^2 + (mY#+25 - Y#)^2 + (mZ# - Z#)^2)
Rem Если игрок в зоне видимости, выпускаем ракету
if PDist<1500
if MonsterBulletLife=0 or MonsterBulletLife < 500-Pdist/10
Point object 3,X#,Y#-25,Z#
If BulletAvoidDeco > 0
CornerAim = Rnd(1)
mA# = object angle Y(3)
if CornerAim = 0 then Yrotate Object 3,WrapValue(mA#+BulletAvoidDeco*10)
if CornerAim = 1 then Yrotate Object 3,WrapValue(mA#+BulletAvoidDeco*-16)
Dec BulletAvoidDeco
Endif
If ShootUp > 0
mA# = object angle X(3)
XRotate Object 3,WrapValue(mA#+ShootUp*-8)
Dec ShootUp
Endif
Position object 102,mX#,mY#+25,mZ#
Set object to object orientation 102,3
MonsterBulletLife =500
show object 102
Loop sound 102
Rem Воспроизводим цикл анимации объекта
Loop Object 3,0,20
Endif
Endif
if PDist>1000
Rem Сохраняем старое положение
OldmX# = mX#
OldmZ# = mZ#
OldmY# = mY#
Rem Воспроизводим анимацию ходьбы
Loop Object 3,21,46
Rem Переместить монстра
Move Object 3,7
Rem Получаем новую позицию
mX# = Object Position X(3)
mZ# = Object Position Z(3)
mY# = Get Ground Height(1,mX#,mZ#)
Rem Проверка столкновения с колоннами
If DecoCollide(mX#,mY#,mZ#) = 1 and AvoidDeco = 0
mX# = OldmX#
mZ# = OldmZ#
mY# = OldmY#
AvoidDeco = 3
Endif
Endif
Return
В подпрограмме "MonsterAI" мы добавили код, необходимый для того, чтобы монстр обходил преграды, а также код, меняющий угол стрельбы монстра, в случае, если две переменные, описанные выше, имеют значение отличное от 0.
If AvoidDeco >0
mA# = Object Angle Y(3)
Dec AvoidDeco
Yrotate object 3,WrapValue(mA#+AvoidDeco*60)
endif
Если значение переменной "AvoidDeco" больше 0, ее значение уменьшается на 1, а также изменяются углы поворота монстра путем добавления величины "AvoidDeco", умноженной на 60, к текущим углам поворота монстра. Когда монстр натыкается на колонну, переменная "AvoidDeco" принимает значение 3. При каждом проходе цикла монстр перемещается сначала на 180, затем на 120, а потом на 60 градусов. Это заставляет монстра полукругом отойти назад от того места, где он "уткнулся" в преграду. Эта часть кода показывает, как монстр перемещается между преградами.
If BulletAvoidDeco > 0
CornerAim = Rnd(1)
mA# = object angle Y(3)
if CornerAim = 0 then Yrotate Object 3,WrapValue(mA#+BulletAvoidDeco*10)
if CornerAim = 1 then Yrotate Object 3,WrapValue(mA#+BulletAvoidDeco*-10)
Dec BulletAvoidDeco
Endif
Логика проверки переменной "BulletAvoidDeco" аналогична той, что описана выше, только величина изменения углов полета ракеты не такая большая. Когда ракета первый раз попадает в колонну, переменная "BulletAvoidDeco" принимает значение 2. Если ракета снова попадает в колонну, к этому значению прибавляется 2. Это делается до тех пор, пока ракета не сможет обогнуть преграду. Ракета выстреливается вправо или влево случайным образом, что увеличивает шансы того, что она пролетит мимо преграды.

if PDist>1000
Rem Сохраняем старое положение
OldmX# = mX#
OldmZ# = mZ#
OldmY# = mY#
Rem Воспроизводим анимацию движения
Loop Object 3,21,46
Rem Перемещаем монстра
Move Object 3,7
Rem Получаем новое положение
mX# = Object Position X(3)
mZ# = Object Position Z(3)
mY# = Get Ground Height(1,mX#,mZ#)
Rem Проверка столкновения с преградой
If DecoCollide(mX#,mY#,mZ#) = 1 and AvoidDeco = 0
mX# = OldmX#
mZ# = OldmZ#
mY# = OldmY#
AvoidDeco = 3
Endif
Endif
Эта часть кода управляет перемещением монстра. Сначала мы сохраняем предыдущие координаты монстра, прежде чем начать перемещать его. Затем воспроизводим цикл анимации ходьбы при помощи команды "Loop Object". В данном случае у этой команды на два параметра больше, чем в предыдущем. Два параметра после номера объекта - это диапазон воспроизводимых кадров. Это те кадры, которые мы добавили к объекту ранее. Анимация воспроизводится в цикле, пока мы перемещаем объект. Потом мы сохраняем новые координаты монстра и проверяем, не сталкивается ли он с препятствиями. Если столкновение происходит, мы не меняем значение координат монстра и устанавливаем значение "AvoidDeco" равным 3, заставляя монстра полукругом обойти объект.
If ShootUp > 0
mA# = object angle X(3)
XRotate Object 3,WrapValue(mA#+ShootUp*-8)
Dec ShootUp
Endif
Выражение сравнения для переменной "ShootUp" также добавлено к подпрограмме "MonsterAI". Если ракета монстра попадает в "землю", то переменная "ShootUp" принимает значение 3, а угол выстрела ракеты монстра увеличивается на 24 градуса. При каждом проходе цикла угол уменьшается на 8 градусов. Это дает возможность ракете монстра лететь по наилучшей траектории в направлении игрока.
Как видите, мы не проверяем, вышел ли монстр за пределы матрицы. В этом нет необходимости, так как монстр всегда движется навстречу игроку, а игрок не может выйти за пределы матрицы. Эти несколько строк кода должны сделать игру более интересной и наделить монстра определенным характером в процессе его охоты на игрока.

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 215
Зарегистрирован: 23.05.07
Рейтинг: 1

Награды: За активное участи в разделе "Мультимедиа" , а так же котигориях "Юмор" и "Истории"',
ссылка на сообщение  Отправлено: 18.06.07 10:14. Заголовок: Re:


Еле осилил...
Позновательно, но на любителя)

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Сообщение: 319
Зарегистрирован: 19.05.07
Откуда: Украина
Рейтинг: 0
ссылка на сообщение  Отправлено: 18.06.07 11:15. Заголовок: Re:


Vic пишет:

 цитата:

Еле осилил...
Позновательно, но на любителя)




При наличии программы, ты бы уже осилил даже вступительный курс программирования, если что, обращайся помогу

Спасибо: 0 
ПрофильЦитата Ответить





Сообщение: 234
Зарегистрирован: 23.05.07
Рейтинг: 1

Награды: За активное участи в разделе "Мультимедиа" , а так же котигориях "Юмор" и "Истории"',
ссылка на сообщение  Отправлено: 18.06.07 20:48. Заголовок: Re:


Заметана)

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 0
Права: смайлы да, картинки да, шрифты да, опрос нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет



WireNet (Phoenomix)

WireNet (Phoenomix)
Клуб профессиональной дрессировки собак Tools of Death - Энциклопедия орудий смерти! Сайт затрагивает тему смерти, и все что с ней связано. Рассматривается все то, что нас убивает. Создай свою игру или скачай готовую Создание сайтов, анимаций, потретов. Уникальные рисованные сайты Мужской форум SmehOff Фан-форум Уилла Смита Обмен кнопочками находится здесь! Заходите и станьте нашим другом!
Первый электротехнический поиск TOPlist минск, поиск информации