Давайте сделаем вот такую штуку:
Запустим её несколько раз и увидим, что результат запуска каждый раз будет отличаться - будет меняться размер, цвет и расположение круга. math.random - это генератор случайных чисел. Он получает два параметра и генерирует число в диапазоне от первого до второго включительно. Теперь сделаем незначительное изменение. Перетащим инициализацию переменных непосредственно в функцию TIC.
Как видим, поведение программы полностью изменилось. Впервые с начала курса на экране что-то движется :) . С огромной скоростью мелькают круги разного цвета и размера. Сделаем ещё одно изменение. Вытащим вызов cls за пределы TIC.
Поведение снова поменялось. Теперь круги не мелькают, а наслаиваются один на другой.
В этот момент я подумал, что иллюстрации к каждому куску кода это наверное плохо. Программы надо запускать и смотреть что они делают :) . Дальше без иллюстраций, если не попросят их вернуть.
Попытаюсь объяснить, что именно происходит при запуске программы.
Сначала происходит последовательное выполнение инструкций программы, где определение функций - это фактически просто присваивание, мы говорим - вот такой последовательности действий мы присваиваем вот это имя, сами действия внутри функций при этом не выполняются.
После однократного выполнения всех инструкций, программа вызывает специальную функцию TIC и продолжает её вызывать с частотой около 60 раз в секунду.
Т.о в первой программе мы сначала однократно определили переменные x,y,c и r и функцию TIC, а затем стали вызывать функцию TIC, которая чистит экран и рисует круг пользуясь этими переменными. Так как значение переменных не меняется, круг получается каждый раз абсолютно одинаковый и изменений на экране мы не видим. Во второй программе мы присваиваем переменным случайные значения уже ВНУТРИ функции TIC, т.о. мы 60 раз в секунду чистим экран, присваиваем переменным новые значения и рисуем круг. Получаем мелькающие круги. В третьей программе мы чистим экран до того, как начинаем запускать TIC, соответственно, предыдущие нарисованные круги не стираются.
Для чего нужна эта особая функция, которая так часто вызывается? Как я уже говорил, TIC-80 - это игровая консоль и предназначена она, прежде всего, для запуска игр. Игровые программы, в большинстве своём, устроены довольно похоже. Есть игровой мир, состояние которого описывается большим количеством переменных (обычно упакованных в какие-то объекты и структуры), есть игрок, который, пользуясь каким-то устройством ввода(джойстиком, геймпадом, клавиатурой, мышкой и т.д. и т.п.), может повлиять на значения этих переменных (кроме игрока, есть и другие факторы, которые могут повлиять на значения - например время, случайность, сложные взаимоотношения игровых объектов) и есть игровая программа, которая по значениям этих переменных, отображает игровой мир. Функция TIC - это основная часть такой программы, её цель - проверить состояние игрового мира и сообщить игроку обо всех произошедших в нём изменениях - попросту показать на экране, что в игре происходит.
В предыдущих программах анимация получалась за счёт того, что значения переменных создавались генератором случайных чисел. Попробуем создать что-нибудь немного более предсказуемое.
создаём глобальную переменную t, в функции TIC очищаем экран, печатаем значение t посередине экрана и увеличиваем её значение на единицу. Наблюдаем посередине экрана очень быстро увеличивающееся число. Заодно ввели функцию print, понятно как она работает? Здесь мы связали значение переменной со сменой кадров, это можно использовать для создания самой разнообразной анимации.
Как-то мало контроля :) . В одном случае круг уполз за пределы экрана, в другом вырос так, что перерос экран. Для того чтобы остановить безобразие (и конечно не только для этого) существует инструкция if. выглядит она так
if условие then
какие-то действия
end
или более полный вариант:
if условие then
какие-то действия
elseif другое условие then
ещё какие-то действия (блоков elseif может быть сколько угодно, в том числе их может вообще не быть)
else
какие-то действия
end
elseif можно перевести как "если нет, но при этом". а else - "иначе". Ну, к примеру, чтобы круг не вырос больше экрана, нужно, чтобы его радиус не стал больше 67.
Теперь попробуем решить задачку чуть посложнее. Хотелось бы, чтобы тот круг, который ползает, не просто останавливался, дойдя до края экрана, а менял направление движения. В предыдущей программе, для того, чтобы определить, что делать, достаточно было знать положение круга на экране. если не дошёл до определённой точки - двигайся вправо, если дошёл - остановился. Теперь нам в каждый данный момент нужно знать, куда именно двигать круг. Решить задачу можно (как минимум) двумя способами. Первый - ввести дополнительную переменную, которая будет хранить одно из двух значений, например "left" и "right", каждый шаг проверять текущее значение и в зависимости от него либо добавлять к координате X (столбик) единицу (движемся вправо), либо отнимать (движемся влево), при достижении края экрана будем менять "left" на "right", а "right" на "left".
Обратите ещё раз внимание на отличие равенства (==) от присваивания (=). Так же мы тут ненавязчиво использовали строки. Если хотим присвоить переменной какое-то текст, его нужно просто взять в кавычки. Что ещё можно делать с текстом, покажу позже.
Вторая программа делает ровно то же самое, что и первая. Она более короткая, но, наверное, немного менее понятная. Обычно программирование балансирует между лаконичностью и понятностью :) . Попробуйте просто представить себе выполнение программы пошагово. Вот мы прибавляем 1, круг ползёт вправо. Вот мы в очередной раз прибавили 1 и t стало равно 210, тут мы умножили d на -1, теперь мы будем прибавлять не 1, а -1 (или вычитать 1, что одно и то же), следовательно круг поползёт влево. Вот d стало равно 0, снова умножили d на -1, снова d равна 1, снова ползём вправо итд. Хммм... Что бы такое дать... На прошлом уроке мы написали функцию, которая рисует сову (точнее голову совы). Пусть сова летает по экрану, случайно выбирая направления и не вылетает за его пределы. Вроде бы всего, что я написал выше должно для этого хватить.