В Sanny Builder'e используются следующие виды циклов:
1. FOR..END
2. WHILE..END
3. REPEAT..UNTIL
Циклы могут быть вложенными (т.е. один цикл внутри другого).
Внимание: в циклах не используется задержка. Вы должны сами
устанавливать ее внутри тела цикла, если она необходима.
Оператор FOR..END
Этот оператор задает цикл со строго определенным числом итераций
(повторений)
Для него используется следующий синтаксис:
FOR <counter> = <initial value> TO /DOWNTO <final value> [step <int>]
...
END
Основные параметры:
<counter> - переменная, которая используется в качестве счетчика
итераций (повторений) цикла.
<initial value> - стартовое значение счетчика
TO/DOWNTO - при TO счетчик будет наращивать свое значение, при DOWNTO
уменьшать.
<final value> - конечное значение цикла, при котором он завершит работу
Помните, что при DOWNTO конечное значение должно быть меньше стартового
<step> - значение приращения или уменьшения счетчика при итерациях.
По умолчанию его значение равно 1.
Пример цикла:
...
var
$value: int = 0
$final: int = 100
end
FOR $MyCounter = 1 to $final step 2
$value += $mycounter
end
...
Оператор WHILE..END
Синтаксис:
WHILE <condition>
...
END
Цикл WHILE работает до тех пор, пока выполняется условие. Условие
проверяется перед итерациями, поэтому если оно будет сразу ложным,
то цикл не выполнится никогда.
$var = 10
while $var > 11
inc($var)
end
так как условие в цикле ложно, скрипт никогда не придет на команду
Inc($var)
Оператор While может принимать в качестве условий логические
константы True и False:
While True .. End - цикл будет выполняться бесконечно, пока вы не
прервете его командой Break.
While False .. End - цикл будет игнорироваться компилятором.
В текущей версии для цикла WHILE доступно только одно условие.
Вы можете проверять большее кол-во условий внутри тела цикла и
использовать команды Break и Continue.
Оператор REPEAT..UNTIL
Синтаксис:
REPEAT
...
UNTIL <condition>
Цикл Repeat работает до тех пор пока не выполнится условие после
команды Until. Условие проверяется после итераций, поэтому
цикл всегда будет иметь минимум одну итерацию.
Оператор Repeat может принимать в качестве условий логические
константы True и False:
Repeat .. Until True - цикл будет иметь только одну итерацию
Repeat .. Until False - цикл будет выполняться бесконечно,
пока вы не прервете его командой Break.
В текущей версии для цикла REPEAT доступно только одно условие.
Вы можете проверять большее кол-во условий внутри тела цикла и
использовать команды Break и Continue.
Continue и Break
Иногда вам может потребоваться пропустить текущую итерацию и перейти
к следующей, например после проверки условия. Для этого существует
ключевое слово Continue. Оно может использоваться в качестве параметра.
Тогда оно обозначает метку, после которой происходит приращение
счетчика и переход к следующей итерации.
Например:
if
$currentactor.dead
jf continue
В качестве отдельной команды оно обозначает опкод 0002 (jump), с
переходом на следующую итерацию.
if
not $currentactor.dead
jf @next
Continue // jump continue
:next
Кроме этого существует команда Break, которая прерывает цикл. Она может
использоваться как отдельная команда так и как параметр (jf break)
Примеры :
1) Пример использование цикла REPEAT...UNTIL:
Пример написал я , т.е Alexander
Смысл следующий: мы создаём машину и актёра в ней , затем заставляем машину понтоваться,т.е.
поднимать и удерживать колёса разными способами,прям как на соревновании лоурайдеров.
create_thread @Anims // создаём поток с именем Anims
:Anims // начинаем поток
wait 0 // ждём 0 мс,если не напишем,то может вылететь
#REMINGTN.Load // объявляем нужную модель машины - Ремингтон
#FAM2.Load // объявляем нужную модель актёра - Член Грув Стрит банды
038B: load_requested_models // загружаем ранее объявленые модели
:Anims_2 // создаём второй label
wait 0 // ждём 0 мс,если не напишем,то может вылететь
if and // условие с выполнением всех подусловий(проверок)
#REMINGTN.Available // проверка (загрузилась ли модель #REMINGTN)
#FAM2.Available // проверка (загрузилась ли модель #FAM2)
player.Defined($PLAYER_CHAR) // проверка (существует ли игрок)
jf @Anims_2 // если хоть одна из проверок возвратила значение False,т.е. не выполнилась,
// то переходим к началу label'a
wait 5000 // ждём 5 мс,просто для удобства
car.Create(4@,#REMINGTN,2492.6,-1669.5,13.4) // создаём тачку напротив дома Карла
0129: 5@ = create_actor 4 #FAM2 in_car 4@ driverseat // создаём актёра в этой машине
wait 3000 // ждём 3 мс,просто для удобства
Car.ToggleHydraulics(4@) = True // устанавливаем на машину гидравлику,если не поставим,то
// финтов машина делать не будет
$Timer = 25 // Создаём переменную,и приравниваем её к 25,это будет наш таймер
:Anims_3 // создаём следующий label
wait 0 // ждём 0 мс,если не напишем,то может вылететь
REPEAT // начинаем цикл
wait 10 // ждём 10 мс
07F5: car 4@ control_hydraulics 1000.0 0.0 0.0 0.0 // машина поднимает к-л колесо,вот номера
// колёс 1000.0 - переднее левое,0.0 - заднее левое,следующий 0.0 - переднее правое и послед-
// ний 0.0 - заднее правое.
$Timer -= 1 // отнимаем от нашей переменной 1
UNTIL $Timer <= 1 // пока таймер не будет меньше либо равен 1,наш цикл будет выполнятся,
// так всё запутано из-за того,что чтобы поднять колесо надо выоплнить эту команду большое
// количество раз и за маленькое время,и чтобы колесо держалось навису эту команду тоже
// надо поддерживать
// принцип действия заключается в том,что мы задаём переменной $Timer значение 25,и с каждым
// разом когда мы выполняем команду поднятия колеса,от этой переменной отнимается еденица,
// команда выполняется каждые 10 мс(wait 10),и когда $Timer становится равной или меньше еди-
// ницы,мы переходим к следующему действию,поднятие уже другого колеса,но предварительно опять
// задаём переменной $Timer значение 25,а то если она равна нулю,то выполнение перекинется на
// поднятие другого колеса,и так пока не будет найдено хоть одно нормальное значение $Timer
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 1000.0 0.0 0.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 0.0 1000.0 0.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 0.0 0.0 1000.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 1000.0 0.0 1000.0 0.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 1000.0 0.0 1000.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 1000.0 1000.0 0.0 0.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 0.0 1000.0 1000.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 120
REPEAT
wait 10
07F5: car 4@ control_hydraulics 1000.0 0.0 0.0 1000.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 120
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 1000.0 1000.0 0.0
$Timer -= 1
UNTIL $Timer <= 1
$Timer = 25
jump @Anims_3 // тут прыгаем на начало label'a , чтобы все действия поднятия колёс у машины
// пошли заново
Если вытащить из машины актёра,то машина перестанет поднимать колёса.
2) Пример использование цикла FOR...END:
Взято из примеров SB
Давайте создадим последовательно 10 актёров на одинаковом расстоянии друг от друга,используя
данный тип цикла и массив:
create_thread @Actors // создаём поток с именем Actors
:Actors // начинаем поток
wait 5000 // делаем задержку в 5 секунд,чтобы увидить действие цикла в игре самому
var // объявляем переменные
$num: Integer = 10 // это количесво актёров
$actor: array 10 of Actor // это массив из 10 актёров
$X: Float // координата по оси X
$Y: Float // координата по оси Y
end // заканчивание объявления переменных
#WMOPJ.Load // объявляем нужную модель
038B: load_requested_models // загружаем модель
while not #WMOPJ.Available //цикл-пока модель не загрузится,действие скрипта дальше не пойдёт
wait 0 // задержка,даже нулевая,неотемлемая часть любого цикла
end // конец цикла
wait 0 // ждём 0 мс, желательно писать после любого цикла,на всякий случай
Actor.StorePos($PLAYER_ACTOR, $x, $y, $z) // записываем коорд-ы игрока в переменные $x,$y и $z
inc($y,2) // прибавляем к Y координате число 2
dec($x,3) // отнимаем от X координаты число 3
FOR $CurrentIndex = 1 TO $num // начинаем цикл создания актёра
inc($x) // прибавляем к координате X число 1 , 1 - число,которое задаётся автоматически
$actor[$CurrentIndex].Create(4, #WMOPJ, $x, $y, $z) //тут создаём актёра,теперь поподробнее:
// $actor - имя массива актёров,$CurrentIndex - номер элемента массива,мы номера элементов
// перебираем этим циклом,сами посмотрите
wait 250 //задержка-неотемлемая часть любого цикла,если не писать,то толку от цикла не будет
end // конец цикла
#WMOPJ.Destroy // удаление модели из памяти
end_thread // конец потока
Мне понравилось не делать прибавление координат,а только координату Z менять на 30 или больше
при создании актёра,и изменять кол-во актёров и кол-во элементов массива на очень большое,
такое зрелище... Правда потом вылетает...