Blitz3d - массивы, взаимодействие объектов

Массивы

Далее массивы понадобятся для хранения адресов, координат, приращений.
Одномерный массив можно представить, как полоску клетчатой бумаги, в каждой клетке которой записано какое-л значение. Пример:
1 | 5 | 7 | 19 | 29 | 111 | 3 |
Массивы задаются командой:
DIM имя_массива (количество_элементов)

Примеры:

DIM A(7), DIM Name$(5), DIM K#(256)

Числовой массив изначально заполнен нулями, строковой – пустыми строками.
Массивы также бывают двумерными, трехмерными и т. д.:
Фото
Для доступа к элементу массива необходимо указать имя и в скобках номер, например A(2), A(5), Name$(4). Для двумерного массива нужно указать два номера, для трехмерного – три и т. д.
Пример:

DIM K(3, 3)
K(1, 2) = 5
K(3, 1) = 4
PRINT K(1, 1)
PRINT K(1, 2)

Программа, заполняющая массив – таблицу умножения

DIM A(10, 10)
FOR X = 1 TO 10
 FOR Y = 1 TO 10
  A(X, Y) = X * Y
 NEXT
NEXT

Задание: вывести элементы массива, соответствующие умножению 5 на 7 и 3 на 9

PRINT  “5 * 7 =  “ + A(5, 7)
PRINT  “3 * 9 =  “ + A(3, 9)

Обработка массива объектов

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

GRAPHICS3D 640,480
cam = CREATECAMERA()
POSITIONENTITY cam, 0, 0, -20
star = LOADSPRITE("C:\MEDIA\STAR.JPG")

Теперь необходимо разобраться с физической моделью программы. Изначально, 100 звезд размещаются в пространстве случайным образом. Каждая звезда имеет приращения по каждой из координатных осей, которые сначала равняются нулю, но изменяются, в зависимости от положения звезды относительно начала координат. То есть, если какая-либо координата положительна, то приращение уменьшается, если отрицательна – увеличивается. Это приводит к тому, что звезда будет кружиться вокруг начала координат по изогнутой траектории, которую называют кривой Лиссажу.
Создадим три массива. Первый будет содержать адреса спрайтов, второй – их координаты, третий – приращения. Так как координат всего три, а звезд – 100, то второй и третий массивы будут иметь размерность 100 x 3. Звезда n будет иметь адрес addr(n), располагаться в точке с координатами x = c#(n, 1), y = c#(n, 2), z = c#(n, 3) и иметь приращения dx = dc#(n, 1), dy = dc#(n, 2), dz = dc#(n, 3)

DIM addr(100)
DIM c#(100, 3)
DIM dc#(100, 3)

В следующем цикле создается 100 звезд

FOR n = 1 TO 100
 addr(n) = COPYENTITY(star)
 FOR nn = 1 TO 3
 
Каждая  из трех координат приравнивается  к случайному значению  от –8 до 8.
  C#(n, nn) = RND(-8, 8)
 NEXT
NEXT

Далее следует бесконечный цикл,  в котором  для каждой  из 100 звезд изменяются координаты  и приращения,  а также происходит визуализация трехмерной сцены:
REPEAT

В двух вложенных циклах к каждой координате каждой звезды прибавляется ее приращение. Затем в зависимости от знака координаты, приращение изменяется (если с#(n, nn) < 0, то SGN(с#(n, nn)) = -1 и приращение увеличивается на 0.005 и наоборот). Затем спрайт звезды помещается в точку, заданную координатами.

 FOR n = 1 TO 100
  FOR nn = 1 TO 3
   c#(n, nn) = c#(n, nn) + dc#(n, nn)
   dc#(n, nn) = dc#(n, nn) - 0.005 * SGN(c#(n, nn))
  NEXT
  POSITIONENTITY addr(n), c#(n,1), c#(n,2), c#(n,3)
 NEXT
 IF KEYDOWN(1) THEN EXIT
 RENDERWORLD
 FLIP
FOREVER

Фото

Взаимодействие объектов
В большинстве случаев, когда программа оперирует массивом объектов, встает вопрос об их взаимодействии. Наиболее часто встречаемый вариант – столкновение объектов. Когда два или более материальных объекта пытаются занять одно и то же пространство, нужен способ изменить их траекторию (другие варианты – уничтожить один из них, остановить оба объекта и т. д.). Этот случай называется столкновением или коллизией. Blitz3D может автоматически реагировать на столкновения, используя один из нескольких стандартных методов.
Чтобы активизировать механизм реагирования на столкновения нужно вначале задать тип сталкиваемых объектов с помощью команды:
ENTITYTYPE объект, тип

Это нужно для того, чтобы затем определить, какие объекты с какими и как должны сталкиваться. Тип – это число. Задавая один и тот же тип для разных объектов, вы определяете их, как группу участников столкновений. Теперь нужно задать механизм столкновения командой:
COLLISIONS тип движущегося объекта, тип неподвижного объекта, метод определения столкновения, реакция

Данная команда определяет столкновение, если объект первого типа движется и пытается занять пространство второго, неподвижного. Если двигаются оба объекта, то сначала первый из них надвигается на второй, затем второй на первый.
Методы столкновения: 1 - сфера со сферой, 2 – сфера с многогранником, 3 – сфера с параллелепипедом. То есть, движущийся объект всегда виртуально представлен сферой, то есть вне зависимости от его формы он будет реагировать на столкновения, как сфера. Можно задавать радиус этой сферы:
ENTITYRADIUS объект, радиус сферы

Реакция на столкновение может быть двух типов: 1 – остановка объекта, 2 – скольжение объекта вдоль неподвижного.
И в заключение, необходимо дать команду UPDATEWORLD, чтобы проверить столкновения и соответственно отреагировать.
Для следующей программы понадобятся функции определения текущих координат объекта
ENTITYX(объект) – координата X
ENTITYY(объект) – координата Y
ENTITYZ(объект) – координата Z

Программа, создающая нагромождение шаров

Создадим заголовок:
GRAPHICS3D 640,480

cam = CREATECAMERA()
l = CREATELIGHT()
ROTATEENTITY l, 45, 45, 0

Создадим  и оттектурируем плоскость:
grass = LOADTEXTURE("C:\MEDIA\GRASS.JPG")
SCALETEXTURE grass, 16, 16
p = CREATEPLANE()
POSITIONENTITY p, 0, -5, 0
ENTITYTEXTURE p, grass 

Зададим тип плоскости, равным 1, тип шаров будет равным 2:
ENTITYTYPE p, 1

Шары (2) могут сталкиваться  с плоскостью (1), которая определяется,  как многогранник(2),  при этом они будут останавливаться (1):
COLLISIONS 2, 1, 2, 2

Шары (2) могут сталкиваться  с другими шарами (2), которые определяются,  как сферы(1),  при этом они будут скользить(2):
COLLISIONS 2, 2, 1, 2

Когда переменная s равна 0, это означает, что нужно создать новый шар:
s = 0

Бесконечный цикл:
REPEAT

 IF s = 0 THEN

Создаем шар, если s = 0, задаем его тип (2)  и радиус сферы столкновения (1):
  s = CREATESPHERE()  
  ENTITYTYPE s, 2
  ENTITYRADIUS s, 1

Задаем случайное местоположение шара  на высоте 12:
  POSITIONENTITY s, RND(-5,5), 12, RND(10,20)
 END IF

Заносим текущие координаты шара  в три переменные:
 sx# = ENTITYX(s)
 sy# = ENTITYY(s)
 sz# = ENTITYZ(s)

Шар перемещается вниз  под воздействием гравитации:
 MOVEENTITY s, 0, -0.3, 0

Проверяем столкновения:
 UPDATEWORLD 
 
Если координаты шара  не изменились,  то он прочно застрял  и нужно бросать новый шар:
 IF sx# = ENTITYX(s) AND sy#=ENTITYY(s) AND SZ# = ENTITYZ(s) THEN s = 0

Завершаем цикл, визуализируем сцену:
 IF KEYDOWN(1) THEN EXIT
 RENDERWORLD
 FLIP
FOREVER

Фото

Заключение
Основная цель данного спецкурса - заинтересовать людей этим перспективным направлением в программировании и показать его возможности. Базовые навыки, данные здесь, конечно, не могут полностью охватить все аспекты (особенно математические) создания комплексной программы трехмерного моделирования, для научного эксперимента и других целей. Но, проведенные занятия дадут импульс заинтересованным людям для дальнейшего изучения языка Blitz3D (возможно, трехмерных технологий других, более близких им языков), что позволит им в будущем стать специалистами в этой области, использовать знания в применении к другим научным дисциплинам.