Вы находитесь на странице: 1из 1

Главная 3D 2D Engines Web Stereo Sound

Официальный сайт Основы AngleScript


Обзор Введение в основы AngleScript
Документация AngleScript - это скриптовый интерпретатор 3D RAD, описываемый некоторыми как подобный С, и во
ЧАВО многом это так, но он имеет некоторые отличия. AngleScript - это язык программирования, который
может быть использован для доступа к многим функциям 3D RAD. Описание этих функций можно
Обзор редактора найти в справке объекта скрипта, загруженной выше. AngleScript имеет большинство возможностей,
находящихся в языках программирования высокого уровня, и с добавлением функций 3D RAD это
Начало делает его очень всесторонним языком для трехмерного программирования.
Добавление камеры Основные описания и переменные
Визуальные аспекты В этом разделе я опишу, что напоминают операторы и формат функции Main(). Также мы обсудим
взгляд на то, что такое переменные и как они работают на Вас.
Группировка

Импорт Сначала я должен объяснить, что 3D RAD обрабатывает скрипт приблизительно 75 раз в секунду.
Поэтому для того, чтобы не замедлять Вашу частоту кадров, Ваш код должен быть хорошо
Аддоны спроектирован, и Вы должны стараться не использовать избыточно операторы зацикливания, но
больше об этом позже. Когда 3D RAD проходит через объект скрипта в первый раз, он инициализирует
Реклама переменные и обработает Ваш код, затем он вернется спустя 1/75 секунды для того, чтобы пройти его
еще раз. 3D RAD имеет функцию Main(), это главная точка, где запускается обработчик. Функция
Шейдеры подобна контейнеру кода, и здесь могут быть другие ветви, ведущие из этого контейнера к другим
контейнерам, но все они должны вернуться в функцию Main() для продолжения со следующей строкой
Функции редактора
кода. Эти другие контейнеры (функции) могут быть встроенными функциями 3D RAD или Вашими
CamChase собственными функциями, построенными пользователем; больше о функциях позже. Почему я
сравниваю функции 3D RAD с контейнером - это потому, что переменная может быть эксклюзивной для
SketchUp пользовательской встроенной функции (контейнера), или она может быть глобальной, таким образом,
она может быть использована во всех функциях. Если Вы объявляете переменную перед функцией
3DS Max Main(), это говорит о том, что она будет глобальной переменной. Глобальная переменная сохраняет
свое значение между проходами обработчика, таким образом, скрипт обрабатывается 75 раз в секунду,
Lightwave и между каждым проходом через, значение переменной сохраняется, даже если код изменяет его. Я
Мультиплеер обсужу больше о переменных и функциях в этом разделе.

События Затем я должен объяснить причину для двух прямых слешей, сопровождаемых описанием. Это
операторы уведомления, когда Вы пишете Ваш код, он помогает время от времени помещать
Устойчивость операторы уведомления так, чтобы когда Вы смотрели на них в будущем, они помогли бы вам
вспомнить, как это работает. Я включил больше операторов напоминаний (коротко rem) в следующий
Основы AngelScript пример кода. Эти операторы напоминания описывают операции в каждом разделе этого кода примера.
Справка программы // проект TutScript3
int count = 0; // определяет целую переменную, называемую count и устанавливает ее в ноль
void Main() // начинает главный цикл. 3D Rad циклически проходит здесь 75 раз в секунду.
{
if (count < 200) OUT_0 = iFloatRand(0,1); // если count меньше 200, то OUT_0 = случайному числу
if (count == 300) // если count = 300, то скрыть OBJ_0 и запустить OBJ_3
{
iObjectHide(OBJ_0);
iObjectStart(OBJ_3);
}
count++; // увеличивает переменную count на 1
}

Первая строка кода - это оператор напоминания, сообщающая Вам, для чего этот код. Во второй
строке мы инициализируем переменную count (int count = 0;). Это определяет целую переменную,
называемую "count" и устанавливает ее значение в ноль. При объявлении после функции Main() это
происходит только один раз, и любая переменная, которую Вы планируете использовать на протяжении
Вашего кода, должна быть определена здесь. Это называется глобальным объявлением, что значит,
что переменная может быть прочитана любой созданной Вами функцией. Опционально, Вам не нужно
устанавливать ее значение (например, int count;), или она может быть установлена в любон значение,
подобно (например, int count = 5;).

Это подводит нас к тому, что такое переменная; переменная - это место в памяти, которое хранит
значение, и для нас, людей, оно должно быть идентифицируемо, так что мы даем ему имя. Есть 5
типов переменных, 1 - это целое число, 2 - это число с плавающей точкой, 3 - это строка, 4 - это вектор,
и 5 - это квартернион, но здесь я не буду углубляться в последние два.

Целое число может иметь значение от -2,147,483,648 до 2,147,483,647, число с плавающей точкой -
/+3.402823466E38. Имена переменных могут быть фактически любым именем, состоящим из букв или
цифр, в большинстве случаев Вы можете не использовать любые символьные значения, подобные
следующим {}[]<>,./?\|)(&^%$#@!?~`=+:-; или пробелу. Anglescript имеет несколько зарезервированных
слов, которые Вы не можете использовать, было бы лучше проверить их веб-сайт для подробностей.
Лучший метод именования переменных заключается в использовании имени, которое представляет то,
для чего должно использоваться значение, обратитесь к переменной "count", использованной в коде
примера.

Обратный слэш "\" используется для того, чтобы сообщить компилятору о том, что это специальный
символ, и не отображать его подобно "r" в приведенном выше примере. Так как это не отображаемы
символ, он должен быть возвратом каретки. Затем, если Вы сохраняете или загружаете файл, Вам
нужно объявить строку с именем файла, подобную этой:

String filename="c:\\program files\\3drad\\3drad_res\\temp";

Так как Windows использует обратный слэш для разделителя папок, он также должен иметь обратный
слэш для того, чтобы сообщить компилятору о его отображении.

Часть кода (void Main( ){ code }) является главной функцией и содержит главное тело Вашего кода
между фигурными скобками. Фигурные скобки являются важными и определяют начало и конец Вашего
кода. 3D Rad циклически проходит здесь 75 раз в секунду. Void Main( ) имя "Main" зарезервировано для
Anglescript как главное размещение Вашего скрипта, и не может быть изменено или использовано где
угодно в Вашем коде. Функции могут возвращать переменную, содержащую значение, но в этом случае
нет точки потому, что с ней нечего делать, что подводит нас к объявлению "void" перед "Main". Слово
"void" объявляет, что тип данных, возвращаемых функцией, в этом случае означает ничего. Вы также
можете определить свои собственные функции, которые возвращают значения, но я не хочу
углубляться в это сейчас. В действительности Void не является типом данных, и он используется для
того, чтобы сообщить компилятору о том, что функция не возвращает никаких данных.

Затем в скрипте на предыдущей странице Вы видите 2 оператора if(), которые являются операторами
принятия решений. Вы можете видеть из этих 2 примеров операторов if(), что есть разница в способе,
которым они лежат, второй имеет фигурные скобки, охватывающие операторы. Фигурные скобки не
являются безусловно необходимыми, но они помогают Вам понимать, где начинаются и заканчиваются
Ваши операторы. По традиции программирования новичков, лучше использовать фигурные скобки для
всех операторов (например, код if()). Формально оператор if() не нуждается в фигурных скобках в
некоторых обстоятельствах. Формат должен быть - все на одной строке, подобно этому примеру, Вы
даже можете иметь более одного оператора в строке.

if (count < 200) OUT_0 = iFloatRand(0,1);

Вы можете вкладывать одни операторы if() внутрь других, но больше об этом позже. Каждый элемент
кода должен быть с точкой с запятой (;), это сообщает компилятору, что это конец кода так, чтобы он
переместился к следующему элементу. В скрипте, который Вы видите, есть два знака равенства,
идущих дважды и друг за другом. Два знака равенства используются для сравнения переменных, и
один используется для назначения значения переменной. Два знака равенства называются блоками
сравнения. Использование этих блоков сравнения внутри оператора if() может проверить, чему равно
значение переменной. Есть много типов блоков сравнения, больше о блоках сравнения и создании
принятия решений есть дальше в следующем разделе.

Последняя строка кода (count++) увеличивает значение переменной "count" на 1. Это также может быть
записано как (count=count+1), но это немного сложнее и в действительности не нужно. Если Вы хотите
(увеличить) count больше, чем на 1, то используйте этот метод примера (count+=5) или (count=count+5).

Объявление переменных:

Вот, как Вы определяете переменные;

int aa; // это определяет целую переменную, называемую aa, которая не имеет значения
int aa=10; // это определяет целую переменную, называемую aa с значением 10
int aa,bb,cc; // это определяет 3 целых переменных, называемых aa, bb, и cc, которые не имеют значения
int aa-1,bb=2,cc=3 // это определяет 3 целых переменных, называемых aa, bb, и cc, которым назначены значения.

Тот же самый формат может быть использован для переменных с плавающей точкой и строковых
переменных. Объявление значения строковой переменной должно иметь значки кавычек, подобно
следующему:

string aa="Hello World";

Объявление массивов раскрывается в разделе массивов. Есть еще 2 переменных для рассмотрения -
это Vector3 и Quaternion. Эти переменные используются математическими функциями 3D Rad. Их
объявление выполняется так же, как и для других переменных.

Vector3 directionzyx;
Quaternion rotationzyx;

Последнее для непосвященных - Вы не должны объявлять переменные, которые Вы не будете


использовать. Иногда при разработке скрипта Вы можете добавить переменные, которые
заканчиваются чрезмерностью Ваших требований и даже для целей отладки. Поэтому, когда Вы
заканчиваете разработку скрипта, пройдитесь по нему и удалите избыточные переменные, отладочные
переменные, и не забудьте добавить операторы напоминания так, чтобы когда Вы будете смотреть на
Ваш код в будущем, Вы будете знать, как он работает.

Строковые переменные - это переменные, чье значение является символом или несколькими
символами. Подобно другим переменным, Вы должны объявить переменную прежде, чем Вы
назначите ей что-нибудь. Например;

string text="a";
string text="abcdefghijklmnopqrstuvwxyz";

Это также представляет все символы на клавиатуре.

Теперь 3D Rad имеет много функций, помогающих манипулировать строками, но есть несколько
базовых вещей, которые Вы можете использовать в AngleScript.

Первая - это добавление строк вместе.

ext="John "; name="Thomas";


text+=name;

Этот результат является "John Thomas", обратите внимание на то, что я добавил пробел в конце John
так, что результирующая строка будет иметь пробел между ними.

Затем Вы можете добавить к концу строки числовую переменную.

int score=10;
text="Score "+score;

Результат - "Score 10".

Вещи, которые Вы не можете делать с другими математическими функциями - это умножение, деление
и вычитание строк.

Есть несколько специальных символов, которые Вы можете использовать для форматирования


отображения строки.

"\r" - это возврат каретки или новая строка. Этот символ не отображается, но перемещает текст после
себя на новую строку.

Text="This is a test to \rsee how it works!";

Это будет отображено:

"This is a test to
see how it works!"

Из моих экспериментов с объектом вывода текста 3D Rad следующее не работает. Text=score;, где
score -это целая переменная или переменная с плавающей точкой.

Вы должны делать следующее:

text=""+score;

Разработка эффективного кода

Выше я упоминал, что Вы должны разрабатывать Ваш код более эффективно, и не использовать
избыточно операторы зацикливания. Если Вы являетесь новичком в кодировании, я напомню
некоторые операторы и процессы, с которыми Вы можете быть незнакомы, но они объясняются в
последующих разделах.

Главное правило программирования - это правило K.I.S.S. - Сохраняй это простым, тупица. В
большинстве случаев есть более, чем один способ сделать одну и ту же работу. Поэтому, после того,
как Вы разработали часть кода, не нужно расслабляться и говорить: Хорошо, оно работает, лучше я не
буду путаться с этим. Часто что-то может быть сделано лучше, проще, и не забудьте включить
операторы напоминания. Операторы зацикливания для проверки, сравнения всех видов информации if,
но они остановят частоту кадров, если обработка окажется большой. Как я упоминал выше, всегда есть
другой способ сделать ту же самую работу без слишком сильного замедления вещей. Внизу есть 2
простых метода для проверки одного и того же списка данных. Допустим, мы хотим проверить список
счета игроков в массиве. Следующий оператор зацикливания for() сделает это хорошо, но этот код
замедлит частоту кадров по сравнению со следующим примером.

Этот пример кода цикла for() не очень сильно замедлит обработку сам по себе, но если где-то
сдублирован для каждого игрока, или должен просчитать большой массив, он замедлит частоту
кадров.

int []player = {0,0,0,0,0,0} // массив счета игроков


void Main()
{
for ( int l = 0; l < 5; l++ ){ // начало цикла
if ( player[l] > 0 ){ // проверка того, инициализирован ли игрок
player[l]++; // если так, то увеличить счет
}
}
}

Этот код обрабатывается 75 раз в секунду, и увеличивает счетчик на каждом проходе. Он проверяет
один элемент массива за каждый проход, затем значение счетчика увеличивается для проверки
следующего элемента массива для следующего прохода. Это намного более эффективный способ
проверки периодически повторяющихся данных.

int []player = {0,0,0,0,0,0} // массив счета игроков как глобальный массив


int l=0; // инициализация в качестве глобальной переменной
void Main()
{
if ( player[l] > 0 ){ // проверка того, инициализирован ли игрок
player[l]++; // если так, то увеличить счет
if (l==5){
l=0;
}else{
l++;
}
}

Другой эффективный метод прохода заключается в операторе switch(). Он может быть


инкрементирован, подобно последнему примеру, но иметь несколько операторов if() для проверки,
подобной следующему примеру. Каждый оператор проверяется по очереди один раз каждую 1/75
секунды. Каждая обработка следует оператору ключа, может иметь более одного оператора, и не
нуждается в идентичной обработке, подобно приведенной в нашем примере. Больше об операторе
switch() в следующем разделе.

int player1=0;
int player2=0;
int l=0; // инициализация в качестве глобальной переменной
void Main()
{
switch(l){ // switch инкрементируется на каждом проходе
case 1:
if ( player1 > 0 ){ // проверка того, инициализирован ли игрок
player1++; // если да, то увеличить счет
}
break;
case 2:
if ( player2 > 0 ){ // проверка того, инициализирован ли игрок
player2++; // если да, то увеличить счет
}
}
if (l==2){
l=0;
}else{
l++;
}

Есть процессы, которые никогда не должны выполняться на протяжении процесса игры, подобные
загрузке или сохранению данных, эти процессы должны выполняться в начале или в конце игры. Если
Вам нужно позиционировать игроков, Вы загружаете данные, затем на старте игры Вы
инициализируете их, не делая это в процессе игры. Если затем нужно загрузить данные в массив
потому, что они основаны на памяти, они работают намного быстрее, чем операторы загрузки и
сохранения.

Отладка Вашего кода

Прежде всего - редактор скриптов 3D Rad имеет отличную кнопку отладки, используйте ее регулярно.

Затем - если вещи не идут так, как планировалось в течении игры, то выводите переменные,
находящиеся под вопросом, на экран так, чтобы Вы могли видеть, что происходит. Для того, чтобы
сделать это, добавьте iObjectTextSet(OBJ_x,string); к Вашему коду. Поместите ее внизу кода за
пределами любых циклов и операторов if(). Затем объявите глобальную строковую переменную,
называемую debug.

debug="";

Добавьте переменную debug к коду возле других переменных, которые Вы хотите проверить, подобно
этому.

If(damage>0){
score++;
}
debug="score "+score+" Damage "+damage;

Это отобразит переменные score и damage на экране в течение процесса игры, и Вы сможете видеть,
что происходит. Вы можете использовать этот метод для векторов, целых чисел и т.д. Разметка Вашего
кода

Вы можете извещать экземпляры кода так далеко, как некоторые строки обозначены от других. Это
помогает идентифицировать блоки кода, подобные операторам if(), циклам и даже функциям. Это не
обязательно, это просто помогает Вам визуально идентифицировать блоки кода и то, что они могут
содержать. Блок кода может содержать другие блоки кода. Вообразите или даже попробуйте
выравнивать весь Ваш код влево, и Вы увидите, что намного труднее найти блоки кода. Мое
предпочтение заключается в том, чтобы иметь функции, выровненные левее, чем первое объявление
или блок кода как первый выступ. Весь код внутри блока как следующий выступ. Когда блок
заканчивается, то следующий блок на том же самом выравнивании. Проверьте пример кола на
странице 1.

Принятие решений

Это обсуждение о принятии решений, и рассматриваются операторы if() и блоки сравнения немного
более подробно. Сначала давайте начнем с оператора if().

Оператор if() имеет много форм, ниже некоторые.

В первом примере, если сравнение является истиной, то код между фигурными скобками
обрабатывается. Если сравнение является ложью, то обрабатывается следующая строка кода после
последней фигурной скобки. Вы наиболее часто будете видеть или использовать этот формат.

If(сравнение){
// что-то сделать здесь
}

В следующей комбинации if(){}else{}, если сравнение истинно, то обрабатывается код между первым
набором фигурных скобок. Если ложь, то обрабатывается код между вторым набором фигурных
скобок. Вы можете назвать это триггерной системой, где выполняется одна или другая обработка.

If(сравнение){
// что-то сделать здесь
}else{
// иначе сделать что-то здесь
}

Теперь этот оператор if() немного усложнится. Если первое сравнение является истиной в этом
следующем операторе if(), то обрабатывается код между первым набором фигурных скобок. Затем
пропускается следующее сравнение во втором аргументе и обрабатывается строка кода после
последней фигурной скобки. Если первое сравнение ложно, то проверяется следующее сравнение на
истину или ложь. Если это сравнение истинно, то обрабатывается код между вторым набором
фигурных скобок. Если оно ложно, то происходит переход к следующей строке кода, следующей за
последней фигурной скобкой. Это подобно операции 2 наборов операторов if(), одному за другим,
подобно первому примеру, за исключением того, что если первое сравнения является истиной, оно
пропускает второе сравнение.

If(сравнение){
// что-то сделать здесь
}else if(сравнение){
// иначе сделать что-то здесь
}

Следующий набор операторов называется вложенными операторами. Первый if() выполняет


сравнение, и если оно истинно, обрабатывается второй оператор if(). Если сравнение ложно, то
пропускается внутренний if(), и продолжается код после последней фигурной скобки. Это полезно,
только если есть что-то еще, что Вы хотите обработать, а также проверить внутренний оператор if().
Если у Вас есть два условия для сравнения, то это может быть сделано с логическими блоками
сравнения в одном операторе, показанном в следующем примере.

if(сравнение){
// сделать что-то
if(сравнение){
// сделать что-то
}
}

Это называется логическим сравнением И. Если у Вас есть 2 набора условий для сравнения прежде,
чем Вы обработаете что-то, то это то, как Вы должны это сделать. Если первое сравнение истинно, и
следующее истинно, то обрабатывается код между фигурными скобками.

if(сравнение && сравнение){


// сделать что-то
}

Во всех приведенных выше примерах кода я использовал слово "сравнение" вместо алгоритма блока
сравнения (например, значение 1 <= значение 2). Щелкните на приведенной выше ссылке и
просмотрите различные блоки сравнения, и не бойтесь экспериментировать. Большинство является
просто тем, на что они похожи.

== равно

<= меньше или равно

>= больше или равно

> меньше

< больше

!= не равно

&& логическое И

|| логическое ИЛИ

Эти являются наиболее популярными, которые Вы будете использовать. Приоритет сравнения всегда
выполняется, где левое сравнивается с правым. Поэтому, если левое значение 1 меньше или равно
правому значению 2, то результат будет истиной (например, значение 1 <= значение 2).

Следующий скрипт использует вложенный if() и метод триггера для включения или выключения звука,
или он должен быть случайной вспышкой света, подобной грому или молнии. Добавьте к новому
проекту объект звукового эффекта и объект скрипта. Вставьте приведенный ниже код в редакторе
текста скрипта и редактируйте OBJ_X, каким бы ни было значение звукового объекта. Выйдите из
скрипта и нажмите пробел для запуска этого кода. Вы должны услышать случайный звук различной
длины. Для изменения длины звука увеличьте или уменьшите число 3 в функции iFloatRand().

int sw = 1; // определяем переменную sw и устанавливаем 1


int randEvent; // определяем переменную randEvent
void Main(){
randEvent = iFloatRand(1,3); // случайное число между 1 и 3
if(randEvent == 1){ // здесь ждем случайное число 1
if(sw == 1){ // здесь проверяем, включен ли звук
sw = 0; // здесь устанавливаем переменную sw в ноль
// отключаем звук
iObjectStop(OBJ_X);
}else{ // в противном случае включаем звук
sw = 1; // это устанавливает переменную sw в единицу
// включаем звук
iObjectStart(OBJ_X);
}
}
}

Функции

В мире скриптинга это может быть очень запутано и для неопытных очень сбивающим с толку. Для
уменьшения запутанности помогает разбивать Ваш код на сегменты. если у Вас есть любой код,
который повторяется еще и еще, это также создает чрезмерно большие скрипты. Здесь входят
функции, функции хранят код, который может быть доступен много раз на протяжении Вашего скрипта.
Представьте, например, что Вы хотите отслеживать положение игрока из двух или трех различных
областей Вашего скрипта, то вместо многократного написания кода, Вы просто вызываете функцию из
этих мест. Эта функция будет содержать код, который выполняет сравнение и возвращает результат
обратно в главный скрипт. это не только упрощает Ваше главное тело кода, это помогает Вам
отлаживать любые проблемы путем изоляции разделов кода. Другое преимущество заключается в том,
что Вы можете повторно использовать функции в других скриптах без необходимости их повторного
написания и отладки.

Функции не нужно возвращать значение, но в большинстве случаев Вам понадобится рассчитать что-то
или найти значение, поэтому Вы захотите вернуть значение. Для того, чтобы сделать это, Вы должны
объявить природу значения, которое вернет Ваша функция, например, целое число, число с
плавающей точкой и т.д.

Для вызова функции, которая возвращает значение Вы просто назначьте ее переменной, подобно,
например, "play=myGameOver(damage);". В этом примере функция получает значение в переменной,
называемой "damage", затем делает что-то с ней в функции myGameOver(), и возвращает результат в
переменной "play". Если функция не возвращает значение, то Вы вызываете е подобно этому
"myGameOver()", если Вы хотите, Вы можете передать ей значение подобно предыдущему примеру.
Функции могут получать более одной переменной, но Вы должны разделить их запятой ",", подобно
примеру "play=myGameOver(damage, life,shield)".

Приведенный ниже пример показывает, как Вы объявляете функцию, которая вернет целое значение.
Это очень простая функция, Вы передаете ей значение, которое получается как переменная целого
числа в аа, и в следующей строке аа увеличивается на 1 и возвращается вызывающему аргументу.

int myFunction(int aa){


return aa++;
}
Эта функция получает несколько значений.
int myFunction(int aa , int bb){
return aa + bb;
}

Для функций, принимающих переменную, она должна быть объявлена в объявлении заголовка
функции подобно приведенному выше примеру. Если Вам нужна другая переменная внутри функции,
Вы объявляете ее так, как в приведенном ниже примере. Эта переменная теперь доступна только для
чтения изнутри этой функции, и даже может иметь то же самое имя, что и другие переменные в Вашем
коде, за исключением глобальных переменных. Когда обработчик выходит из этой функции, значение
переменной теряется, так что все переменные в следующем примере являются доступными только для
чтения изнутри функции. В прошлом у меня были ситуации, где Вы хотите сохранить значение в
функции, но Вы не можете, так что Вы просто находите другой способ сделать это. Функция может
только вернуть одно значение, это должно быть то же самое значение (целое - с плавающей точкой -
строка), что и в объявлении заголовка функции.

int myFunction(int aa , int bb){


int cc=10;
return aa + bb+cc;
}

Имя функции может быть почти любым, но есть несколько зарезервированных слов, самое очевидное -
это слово Main(), используемое AngleScript для главной функции. Для подробностей проверьте веб-
сайт AngleScript. 3D Rad также имеет имена функций, которые Вы не можете использовать. Лучший
метод для имен заключается в использовании имени, которое соотносится с целью функции, например,
если функция отслеживает жизнь игрока, используйте имя, отражающее это. Вы можете использовать
любые буквы или цифры, но не любые символы, подобные "{ }[ ]< >,./?\|)(&^%$#@!"~`=+:-;" или пробела.
AngleScript является чувствительным к регистру, и Вы должны использовать для вызова функций тот же
самый регистр, что и тот, с которым Вы объявили их. Это значит, что myGameOver() не то же самое что
и myGameover(), это происходит для всех функций, включая встроенные функции 3D Rad.

Ниже приведен пример того, как Вы можете сделать раскладку функции в редакторе 3D Rad. Этот
скрипт вызывает мою определенную пользователем функцию, называемую myDamageCounter() из двух
различных положений. Они отправляют в функцию различные значения в зависимости от повреждения,
которое Вы можете захотеть нанести игроку, и где он может удариться, больше для попадания в голову,
меньше для попадания в тело. Эта функция вернет целое значение, основанное на результатах кода
внутри функции. Я определил три внутренних целых числа, эти целые числа могут быть доступны и
изменены только изнутри функции. Если Вы прочитаете через описания напоминаний кода, Вы
увидите, как это работает. Если удалить функцию и включить строки кода в главный скрипт, дважды, Вы
увидите, насколько сложнее он станет.

int count=0; // объявляем переменную count


int headBlow=0; // объявляем headBlow как глобальную переменную
int bodyBlow=0; // объявляем bodyBlow как глобальную переменную
void Main(){ // главная функция AngleScript
headBlow=IN_44; // получаем значение триггера и объекта Value
bodyBlow=IN_45; // получаем значение триггера из объекта Value
if(headBlow > 0){ // если headBlow больше нуля
count= myDamageCounter (count, 10); // увеличиваем на 10 (больше повреждения, чем попадание в голову)
OUT_44=0; // нулевой триггер в объекте Value
}
if(bodyBlow > 0){ // если bodyBlow больше нуля
count= myDamageCounter (count, 5); // увеличиваем на 5 (меньшее, чем попадание в тело)
OUT_45=0; // нулевой триггер в объекте Value
}
if(count== -1){ // если count равно минус один, то закончить игру
iObjectStart(OBJ_X) // закончить игру с объектом растворения выхода
}
}
int myDamageCounter(int aa ,int bb){ // функция, определенная пользователем
int cc=aa+=bb; // объявление внутренней переменной и назначение нового значения
if(cc >= 100){ // проверка того, не больше ли 100
return -1; // возврат минус 1 to для завершения игры
}else{
return cc; // возвращение увеличенного счетчика повреждений в cc
}
}

Эта функция примера увеличивает значение счетчика на пять или на десять в зависимости от того,
откуда была вызвана, или минус один, если счетчик равен или больше сотни, таким образом, завершая
игру.

Я не уверен, что этот пример является всем, что полезно, но он демонстрирует то, как работают
функции, как Вы можете уменьшить код и в общем упростить его, делая его легче для отладки. 3D Rad
имеет свои собственные встроенные функции, которые могут быть использованы из объекта скрипта.
Ваши определенные пользователем функции в основном следуют тем же самым соглашениям, что и
функции, определенные 3D Rad. Поэтому, то, что Вы изучили до сих пор, вызывает эти функции 3D Rad
так же.

Зацикливание

AngleScript имеет 3 оператора зацикливания, которые могут быть использованы по различным


причинам. Ниже следует правильный синтаксис для этих аргументов. Вам не нужно использовать
фигурные скобки, но если Вы делаете это, Вы должны иметь оператор зацикливания и только один
последующий оператор на одной и той же линии. Для учащихся лучше использовать фигурные скобки
потому, что они помогают идентифицировать, где начинаются и где заканчиваются аргументы. Все эти
операторы цикла обрабатывают код между фигурными скобками до тех пор, пока условие BOOL_EXP
является истинным.

while( BOOL_EXP ){
STATEMENT
}
do{
STATEMENT
}while( BOOL_EXP );
f
or( INIT ; BOOL_EXP ; NEXT ) {
STATEMENT
}

Следующая функция содержит цикл "while". Этот цикл сохраняет обработку кода внутри этого цикла до
тех пор, пока переменная "сс" больше нуля. Булево выражение вычисляется перед обработкой кода
между фигурными скобками и, если оно истинно, то продолжается обработка следующей строки кода, в
этом случае оператора "return". Основное различие между циклами "while" и "do while" заключается в
том, что цикл "while" вычисляет выражение перед исполнением кода, а цикл "do while" обрабатывает
код прежде, чем он вычисляет выражение.

float _pow(float num, float exp){ // num to the power of exp


int cc=exp;
float ret=1;
while(cc>0){
ret*=num;
cc--;
}
return ret;
}

Так, в следующем примере я использовал цикл "do while" для того, чтобы показать разницу. Теперь, с
булевым выражением, следующим за кодом, переменная сс будет описывать на один больше к -1, и
переменная ret умножается дополнительный раз прежде, чем вычисляется выражение. Это должно
отправить неправильное значение в оператор return, и функция вернет неправильное количество. Для
исправления этого должно быть изменено выражение для чтения (cc>1). Это демонстрирует разницу
между двумя операторами.

float _pow(float num, float exp){ // num to the power of exp


int cc=exp;
float ret=1;
do{
ret*=num;
cc--;
} while(cc>0);
return ret;
}

Цикл "for" является посчитывающим циклом. В следующем примере у меня есть замещенный цикл "for"
и сделаны некоторые другие изменения. В первой части выражения "for" мы настраиваем переменную.
Вы можете назначить значение из другой переменной, как в приведенном ниже примере, или подобно
этому (cc=10;). Если переменная не была инициализирована раньше, то Вы должны сделать это (int
cc=10). Булево выражение может использовать любые блоки сравнения, которые Вы можете
использовать в циклах "while", или даже оператор "if". Есть много типов блоков сравнения, для
большего об операторах сравнения обратитесь к веб-сайту AngleScript. В следующей части оператора
"for" Вы можете увеличить или уменьшить подсчитывающее значение. Для большего об этих
операторах обратитесь к веб-сайту AngleScript. Если нужно подсчитывать больше, чем на один, Вы
можете просто подсчитывать, делая это (cc+=5), это увеличит счетчик на 5. Вы можете просто
использовать его в качестве подсчитывающего цикла, подобно примеру, или Вы можете использовать
подсчитывающую переменную для увеличения некоторой другой переменной с циклом.

float _pow(float num, float exp){ // num to the power of exp


float ret=1;
for (int cc=exp; cc>0; cc--){
ret*=num;
}
10
return ret;
}

Вы можете также вкладывать циклы, то есть помещать один во внутрь другого. Вы можете захотеть
вычислить координату x/y, где внешний цикл для х, и внутренний цикл для вычисления координаты y.
Если Вы хотите преждевременно закончить цикл, Вы должны использовать оператор break. Это только
закончит содержащий его цикл, это не закончит внешний цикл, если он содержится внутри внутреннего
цикла.

Массивы и обработка массивов

Массив - это упорядоченное расположение элементов, которое может содержать различные значения,
обычно использующие общее имя. Массивы часто используются для обработки списков, если данные
подобны файловой информации. Будьте снисходительны ко мне для этого следующего описания как
для тех, кто никогда не сталкивался с массивами. Массив подобен ряду коробок (элементы массива),
выровненных так, что Вы можете одновременно заглядывать в одну из них для того, чтобы увидеть то,
что она может хранить, или Вы можете захотеть положить в нее что-то. Теперь, если Вы обрабатываете
числовые значения, каждая коробка (элемент массива) может содержать только одно значение. Вы
можете использовать отдельную коробку (элемент массива) в математических формулах, но больше об
этом позже. Для того, чтобы посмотреть через ряд коробок (элементов массива), Вы используете
оператор зацикливания, так я раскрываю последний раздел, я также демонстрирую, как Вы
используете его затем с массивами. Я упоминал выше, что массив является общим именем для всех
этих элементов. Именование массива следует тому, что я описывал выше об именовании переменных
в первых разделах о переменных. Массив может быть числовым или строковыми массивами. Подобно
обычным переменным, Вы должны объявить массив. AngleScript использует три типа значений - число
с плавающей точкой, целое и строку. для объявления массива Вы должны сделать это.

int[ ] a ;

Это объявляет целочисленный массив, называемы "а".

float [ ] b;

Это объявляет массив чисел с плавающей точкой, называемый "b". Сейчас этот массив имеет только
один элемент с пустым содержимым. Если Вам нужен массив с большим количеством элементов, Вы
объявляете его подобно этому.

int[ ] a (10) ;

Это инициализирует массив, называемый "а", содержащий 10 элементов с пустым содержимым. Вы


также можете инициализировать элемент значением так, как показано ниже.

int[ ] a = { 1,10,4};

Это инициализирует массив, называемый "а" с тремя элементами, значение первого элемента равно
одному, второго - десяти, и третьего - четырем.

Это основы того, как Вы объявляете массив, дальше мы покажем некоторые использования массива,
но сначала слово о том, как индексируется массив.

Соглашение о нумерации элемента массива начинается с первого элемента, и это ноль, следующий
элемент - это 1, следующий - две и так далее. Так как первый элемент - это элемент номер ноль, а не
элемент номер один. Сначала запутывает, но для обработки массивов Вы должны получить понимание
этой концепции. Например, Вы можете иметь систему вычисления очков, которая имеет игроков 1, 2, 3
и так далее. Для представления этого в массиве это должно быть

score[0] = 1;
score[1] = 2;
score[2] = 3;

Если Вам нужно проверить наибольший счет для 3 игроков, следующий цикл for дет Вам пример того,
что может понадобиться сделать. Этот цикл подсчитывает от 1 до 3, оператор if() еще раз сравнивает
"newscore" со счетом в массиве. Если "newscore" больше, чем старое значение, сохраненное в массиве
счета, оно будет назначено переменной "HiScore". Если (оно) не выше, то затем будет продолжено
сравнение со следующим элементом массива. Другая важная вещь заключается в том, что мы
используем минус 1 в аргументе массива потому, что элементы начинаются с нуля.

for(count=1; count<=3; count++){


if(newscore> score[count-1]){
HiScore=newscore;
}
}

Массивы AngleScript могут быть только одномерными, в отличие от Си, где могут быть многомерные
массивы. Для информационных целей, многомерный массив имеет следующий синтаксис.

float [ ]cords (10,10); // это двухмерный массив чисел с плавающей точкой с 11 элементами в каждом измерении

Вы только получите ошибку, когда Вы объявите массив, подобный этому, в AngleScript невозможно
иметь многомерные массивы. Если Вы преобразуете код из Си или других языков, то Вам нужно найти
другой способ сделать это.

Для нашего примера мы разработаем функцию чтения файла. Функция чтения файла будет требовать
имя файла и загрузит массив, называемый "score", содержащий данные файла.

Вы не можете передать массив в функцию и вернуть массив из функции, поэтому Вы должны объявить
его как глобальный массив, что сделает его доступным везде в Вашем скрипте.

// инициализируйте массив "score" как глобальный массив


// помните о том, что глобальный массив или переменная могут
// быть просчитаны из всех частей Вашего скрипта.
int[] score (5);
void Main()
{
//Здесь происходит Ваш скрипт...
}
void SaveMyScore(string filename){ // функция записи в файл
int filehandle= iFileWriteOpen(filename); // инициализируйте переменную дескриптора файла
int =0; // инициализируйте переменную count
int arrayLen=score.length( ); // получите длину массива из метода длины массива
while(count< arrayLen){ // цикл while подсчитывает от 0 до длины массива
iFileValueWrite(filehandle, score[count], true); // сохраняйте каждое значение из массива счета в файл
count++; // увеличьте count
}
iFileClose(filehandle); // приведите в порядок закрытием файла
} // выход из функции

Эта функция принимает "filename" как "string" из вызывающего аргумента, затем она вызывает функцию
3D Rad для получения дескриптора файла. Затем она инициализирует переменную "count", затем она
получает длину массива из метода длины массива. Эта переменная получит это значение из метода
"length()", который является методом массива. Массив имеет 2 метода: "length()" и "resize()", Вы можете
использовать метод "length()", когда Вам нужно найти число содержащихся в нем элементов. Метод
"length()" возвращает число элементов, так что массив, который содержит 10 элементов, которые будут
иметь номера от 0 до 9. Метод "resize()" используется для увеличения или сокращения элементов в
массиве, но больше об этом позже. Теперь вернемся обратно к нашей функции, я использовал цикл
"while" для извлечения всех данных из функции 3D Rad FileValueRead(). Эта функция 3D Rad извлекает
только одно значение за раз, поэтому это значение назначается массиву "score[]". Переменная "count"
индексирует массив, готовый к следующему значению из функции FileValueRead(). Когда переменная
"count" больше, чем "arrayLen", то больше нет значений из файла, так что сравнение в аргументе
"while" будет истиной, завершая цикл. Затем мы приведем в порядок, закрыв файл и вернувшись к
главному скрипту.

С этой функцией мы можем писать в файл, и мы получим это, передав ей имя файла.

void GetMyScore(string filename){ // чтение счета из файла


int filehandle = iFileReadOpen(filename); // получение дескриптора файла
int count=0; // инициализация переменной count
int arrayLen=score.length( ); // получение длины массива из метода массива
while(count< arrayLen){ // цикл while от count до длины массива
score[count]=iFileValueRead(filehandle); // загрузить массив счета из файла
count++; // увеличить count
}
iFileClose(filehandle); // привести в порядок, закрыв файл
} // выход из функции

Сначала функция принимает "filename" из вызывающего скрипта. Сначала она получат переменную
"filehandle", затем инициализирует переменную "count". Затем инициализирует переменную "arrayLen"
получает ее значение из метода "length()". Для получения данных из каждого элемента в массиве мы
используем цикл "while", он продолжает цикл до тех пор, пока переменная "count" больше "arrayLen".
Функция 3D Rad FileValueWrite() записывает значение из каждого элемента по очереди до тех пор, пока
сравнение цикла не станет истиной. Наконец, мы закроем файл, и функция завершиться.

Подсчитывание несуществующих элементов может привести к ошибке. Если у Вас есть массив,
который содержит 10 элементов, и цикл, который обращается к 10, это может привести к ошибке
потому, что индексатор имеет переполнение числа элементов, поэтому мы используем метод length()
для того, чтобы найти число элементов, из которого Вам может понадобиться вычесть один прежде,
чем Вы начнете подсчитывать, это зависит от оператора цикла, который Вы используете, или от
способа, которым Вы его используете. Вы можете назначить значение любому элементу в массиве так,
как указано ниже.

a[0] = 1;
a[5] = 10;
a[8] = playerone;

Это назначает значение 1 нулевому элементу, 10 элементу 5, или значение из переменной "playerone"
элементу 8. Вы можете использовать элемент массива в формуле подобно следующему примеру.

c = a[5] - a[8];

Это назначает "с" значение разности между элементом 5 и элементом 8.

Вы можете увеличить размер массива, назначив новый элемент с методом "resize()". Если у Вас есть
массив, который имеет 10 элементов, Вы можете увеличить его до 15 элементов вот так.

score.resize(15);

Теперь массив содержит 15 элементов, пронумерованных от 0 до 14. Еще одна вещь - Вы должны
изменить размер массива прежде, чем Вы получите число его элементов с методом "length()", или это
приведет к ошибке.

Вы можете думать, что я охватил все, что нужно знать о массивах, но это только подсказка. Массивы
имеют намного больше использований и намного больше трюков, но все, приведенное выше, является
экстремально полезным. Эта часть должна дать Вам достаточно информации для начала с
использованием массивов в сочетании с файловыми функциями 3D Rad.

Switch / Case

Следующий пример скрипта является правильным синтаксисом для switch/case. INT_EXP - это
целочисленное значение, которое Вы хотите вычислить. INT_CONST - это значение, которое
инициализируется истинным условием. Каждый блок case должен заканчиваться оператором break,
если только Вы не хотите продолжить вычисление значения в следующем операторе case или
обработать оператор default.

switch( INT_EXP )
{
case INT_CONST:
STATEMENT
case INT_CONST:
STATEMENT
default:
STATEMENT
}

Оператор default является опциональным. Следующий код вычисляет число randEvent, которое может
быть 1 или 2. Если 1, то первый оператор case будет истиной, и код после case будет обработан.

switch( randEvent )
{
case 1:
// сделать что-то
break;
case 2:
// сделать что-то
break;
}

Каждый аргумент case может иметь несколько аргументов, подобных if(), циклам и т.д. Вы можете
иметь много аргументов case и правильно использовать этот очень эффективный метод управления
потоком кода.

Олег Широколава, e-mail: shyrokolava@mail.ru