Сегодня рассмотрим такую интересную возможность, который представляет языки программирования, как создание собственных функций.
Мы уже использовали функции, встроенные в язык, такие, как print(), box(), fbox(), frame(), теперь рассмотрим, как можно создавать свои.
Простая функция
Функция создаётся очень просто. Пишем ключевое слово fn, дальше придумываем имя для функции и ставим круглые скобки. Скобки идут всегда после функции, даже если у неё нет параметров. И в конце в фигурных скобках пишем код функции.
Например, создадим функцию, которая выводит по центру экрана жёлтый прямоугольник размером 20х20 с белой рамкой.
fn yellowCube()
{
fbox(-10,-10,20,20,YELLOW)
box (-10,-10,20,20,WHITE)
}
Это особенно удобно когда какой-то фрагмент постоянно повторяется в коде. Можно дать ему осмысленные имя и тогда код становится более компактным и читабельным. Но даже когда некоторая последовательность повторяется только один раз, если дать ей осмысленное имя то код становится более читабельным.
Функции обычно записываются в конце кода программы или выносятся в отдельный файл. Теперь вместо большого объема текста можно просто записать yellowCube() и на экране будет желтый квадрат с белой рамкой.
Функция с параметрами
Куда более интересные возможности предоставляет возможность использование параметров. Создадим функцию, которая рисует желтый квадрат 20х20 в указанном месте экрана. В качестве параметров будем передавать центр квадрата
fn yellowCube( $x, $y )
{
fbox( $x-10, $y-10, 20, 20, YELLOW )
box( $x-10, $y-10, 20, 20, WHITE )
}
Символ доллара $ делают переменную локальной, то есть она видна только внутри функции и не видно снаружи. Это позволяет избежать конфликта имён. Если внутри функции нужно использовать глобальную переменную, то значок $ ставить не нужно.
Значения, возвращаемые функцией
Есть ещё одно прекрасное свойство функций. Она может не только делать какие-то действия но и выдавать на выход результат.
Поэтому функцию можно использовать для присвоения переменной какого то значения или вставлять функцию в качестве параметров в другую функцию.
foo = function1( )
function3( function1( ), function2( ) )
Здесь, в первой строчке мы переменной foo присвоили значение, которое выдала функция function1( ). Во второй строчке мы в функцию function3 в качестве параметров передали значения, которые вернули функции function1( ) и function2( ). Естественно, нужно следить, что бы тип возвращаемых значений соответствовал тому, какое тип имеет переменная или параметр.
Во втором случае сначала будут выполнены функции function1( ) и function2( ), а затем будет выполнена function1( ) с полученными параметрами.
Для того, что бы это осуществить, в код функции нужно вставить ключевое слово ret( )(от англ. return-вернуть) и в скобочках указать, что требуется вернуть.
Пример 1
Нам нужна функция, которая возвращает расстояние в пикселях между двумя точками на экране.
В качестве параметров будем передавать ей координаты этих точек.
Тут стоит вспомнить школьную математику, что квадрат гипотенузы равен сумме квадратов катетов.
Мы легко можем вычислить расстояние между двумя точками по оси X и по оси Y просто вычтя координату по заданной оси одной точки из другой (отрезки c и b). Возведём их в квадрат сложим и из полученной суммы извлечём квадратный корень.
fn dist( $x1, $y1, $x2, $y2 )
{
$xx = $x1 - $x2
$xx=$xx * $xx
$yy=$y1 - $y2
$yy=$yy * $yy
ret( sqrt( $xx + $yy ) )
}
Здесь используется встроенная функция sqrt( ), которая возвращает квадратный корень из числа, которое ей передали в качестве параметра.
Теперь функцию dist( ) можно использовать для присвоения значения переменной, в качестве параметра для другой функции и в качестве проверяемого условия
// в переменной foo теперь хранится расстояние
// между точками (100,-50) и (200, 10)
foo = dist(100, -50, 200, 10)
// используем результат работы функции dist( )
// в качестве параметров для другой функции
function1( dist( 100, -50, 200, 10 ) )
// код в фигурных скобках будет выполняться, пока
// расстояние между точками dot1 и dot2 больше 10
while dist( dot1X, dot1Y, dot2X, dot2Y) > 10
{
some code
}
// код в фигурных скобках выполнится, только если
// расстояние между точками dot1 и dot2 больше 10
if dist( dot1X, dot1Y, dot2X, dot2Y) > 10
{
some code
}
Пример 2
Рассмотрим для примера функцию который я использую практически во всех своих проектах. Эта функция нужна для выведения значения числовой переменной на экран.
Подобной функции нет среди встроенных в язык. Но есть такая функция.
Вывести текст на экран.
Параметры ( text, x, y, color, align, max_xsize )
text - ID контейнера с текстом;
x, y - координаты точки, относительно которой происходит выравнивание;
color - цвет;
align - выравнивание; опциональный;
max_xsize - максимальный размер (кол-во пикселей) текста по горизонтали; опциональный.
В качестве параметра здесь нужно передавать текст, а это другой тип данных.
Число 10 в памяти компьютера хранится в одном байте в виде - 00001010,
Текст "10" в памяти компьютера хранится в двух байтах в виде символов "1" и "0", выглядит он так 00110001 00110000
Для преобразования числа в текст есть такая функция.
num_to_str
Конвертировать число из переменной в текстовую строку .
Параметры ( str, num )
str - контейнер для строки;
num - число.
Что бы вывести значение переменной num на экран, нужно написать такой код
str = "" // создаём контейнер для строки с именем str
num_to_str( str, num) // теперь в str хранится num в виде текста
print( str, 0, 0 ) // выводим на экран
Я создал функцию, которая в качестве параметра принимает число, а на выходе возвращает строку. Назвал функцию n2s ( number to string).
Теперь, что бы вывести значение числовой переменной num на экран, нужно записать.
print( n2s(num), 0, 0 )
Само объявление функции выглядит так
fn n2s( $n )
{
$s=""
num2str( $s, $n )
ret( $s)
}
include
Eсть прекрасная возможность под названием include (включить) благодаря ей можно вынести часть кода в другой файл
Для этого часть кода переносят в другой файл, полученный файл сохраняется рядом с исходным, а в исходном файле делают запись include и в кавычках имя файла который должен быть включён.
В отдельный файл можно перенести все константы, переменные, начальную инициализацию, чтобы не загромождать основной файл и с ним было проще работать. Но, в основном, эта возможность используется для создания библиотек функций.
Если собрать универсальные функции, которые вы постоянно используете, то можно переносить их с одного проекта в другой тем самым уменьшается объем кода, который необходимо написать.
Примечания
Функции уже встроенный язык часто имеют необязательные параметры, поэтому желательно смотреть в источнике чтобы узнать какие параметры бывают у них ещё. Например рассмотрим функцию
Вывести текст на экран.
Параметры ( text, x, y, color, align, max_xsize )
text - ID контейнера с текстом;
x, y - координаты точки, относительно которой происходит выравнивание;
color - цвет;
align - выравнивание; опциональный;
max_xsize - максимальный размер (кол-во пикселей) текста по горизонтали; опциональный.
примеры:
print( "Hello Pixi!", 0, 0 ) //цвет - белый; выравнивание - по центру;
print( "line1\nline2", 50, 50, RED ) //выравнивание - по центру;
print( "line1\nline2", -50, 50, RED, TOP | LEFT ) //выравнивание - по верхнему левому краю;
У этой функции можно не записывать последние 3 параметра. В этом случае используется белый цвет и выравнивание по центру.
Там же можно найти константы, используемые при выравнивании.
В пользовательских функциях в Pixilang все параметры обязательны.
Пример 3
Напишем код, где жёлтый квадрат летает по экрану, отскакивая от синей стены, а по центру экрана выводится расстояние в пикселях от центра экрана до квадрата. Большая часть кода оформлена в виде функций и выведена в отдельный файл, благодаря чему в коде легко разобраться.
В строке 2 подключаем файл с функциями
В строке 10 применяем эффекты. Все используемые эффекты собрал в одну функцию.
В строке 11 обновляем координаты, проверяем, не вышел ли квадрат за границу и в случае необходимости меняем его скорость по одной из координат.
В строке 16 выводим расстояние от центра до квадрата. Так как функция dist возвращает вещественное число, я делю его на 1 с отбрасыванием дробной части.
На этом всё. В следующем уроке рассмотрим обработку событий, таких как клики и движения мышки/пальца по экрану.