Программирование с нуля - это совсем просто! 106) Программирование спрайтовых игр: Функции
Школа программирования
106) Программирование спрайтовых игр: Функции
Продолжение темы про разработку игр и мультимедийных приложений на Blitzbasic. Последний выпуск - N 103.
Допустим, мы сформировали некоторый набор команд, который в дальнейшем хотим использовать в разных местах программы. Каждый раз копировать его вручную неудобно, так как если потом эту последовательность операторов понадобится немного изменить, то изменения придется вносить и дублировать во множество строк.
Обычная практика программирования подразумевает выделение таких часто используемых групп команд в блоки или модули. Они называются функции.
Функция начинается с ключевого слова
Function
за которым следует ее название, выбранное программистом, и круглые скобки, а заканчивается парой слов
End Function
Между ними записываются команды, которые в дальнейшем будут многократно повторяться при указании только одного имени функции.
Глобальные переменные
К используемым в программе переменным можно обращаться из наборов команд внутри функций. Однако чтобы значения этих переменных корректно сохранялись до обращения к функции, внутри ее содержимого и после нее, надо такие переменные (они называются глобальные) предварительно описать в начале программы с помощью команды Global.
Рассмотрим такой пример. Допустим, мы написали программу, показывающую текущее число кадров в секунду (FPS):
Graphics 800,600,16
SetBuffer BackBuffer()
FirstTime = Millisecs()
FPS = 0
N = 0
while not KeyHit(1)
Cls
if MilliSecs() > FirstTime + 1000 then
FirstTime = Millisecs()
FPS = N
N = 0
else
N = N + 1
end if
Text 400,100,FPS
Flip
Wend
Часть кода, рассчитывающая показатель FPS, удобно выделить в виде функции, чтобы потом свободно к нему обращаться из разных мест. Вот как это можно сделать:
Graphics 800,600,16
SetBuffer BackBuffer()
FirstTime = Millisecs()
FPS = 0
N = 0
while not KeyHit(1)
Cls
GetFPS()
Text 400,100,FPS
Flip
Wend
; функция GetFPS() function GetFPS()
if MilliSecs() > FirstTime + 1000 then
FirstTime = Millisecs()
FPS = N
N = 0
Else
N = N + 1
end if
end function
Название нашей функции мы придумали сами - GetFPS. Значение числа кадров хранится в переменной FPS.
Код, находящийся внутри определения функции, выполняется, только когда в основной программе встречается вызов GetFPS(). При записи вызова функции надо указывать круглые скобки следом за ее названием.
Однако этот пример будет работать не так, как нужно - на экране все время будет показываться значение 0. Почему? Потому что внутри функции GetFPS() при ее вызове перед командой Text значения переменных N, FPS и FirstTime не трактуются как глобальные, и их новые вычисленные значения на каждом шаге формирования экрана не сохраняются.
Вот как надо изменить начало программы:
...
Global FirstTime = Millisecs()
Global FPS = 0
Global N = 0
...
Когда каждая из этих переменных встречается в тексте в первый раз, перед ней необходимо указать ключевое слово Global. Можно данный код переписать для большей наглядности и так:
...
Global FirstTime
Global FPS
Global N
FirstTime = Millisecs()
FPS = 0
N = 0
...
Так как переменным присваиваются значения уже после того, как они впервые были определены с помощью Global, смысл данного кода остается прежним.
Значение, возвращаемое функцией
Единственный недостаток нашего подхода - необходимость обращения к переменной FPS для получения значения числа кадров, хотя расчет ее величины происходит в функции GetFPS(). Сейчас мы переделаем ее так, чтобы получить число кадров можно было одним указанием названия GetFPS(). Такой подход хорош тем, что мы избавляемся от необходимости помнить как название функции, так и переменную, которые нужны для расчета одного параметра программы.
Для этого внутри функции надо указать, что она не просто выполняет некоторую группу команд, но и формирует некоторое значение, которое можно получить, обратившись к названию функции как к имени обычной переменной. Это достигается использованием команды Return, после которой ставится возвращаемое функцией значение.
Например:
Return 0
Важно! При выполнении этой команды работа функции сразу прекращается, и все следующие за ней операторы пропускаются.
Вот как GetFPS() может быть переписана:
function GetFPS()
if MilliSecs() > FirstTime + 1000 then
FirstTime = Millisecs()
FPS = N
N = 0
Else
N = N + 1
end if
return FPS
end function
Возвращаемое функцией значение равняется, как видно, содержимому переменной FPS. Тогда основную часть программы можно записать так:
while not KeyHit(1)
Cls
Text 400,100, GetFPS()
Flip
Wend
Функция GetFPS() здесь используется так же, как имя переменной. Хотя она не хранит значение, а рассчитывает его на лету, суть программы от этого не меняется.
Использование показателя FPS может быть самым разным. В одних программах удобнее привязывать анимационные события к числу кадров в секунду (когда выполняется объемная графическая работа, значение FPS может сильно изменяться), в других, где величина FPS достаточно стабильна и невелика, смену анимации проще выполнять через фиксированные промежутки времени (хотя принципиальной разницы между этими подходами нету, фиксированные промежутки все же менее гибки, нежели отношение номера текущего кадра в секунду к FPS).
Неплохо также основываться на показаниях FPS при определении детальности и качества изображения.