TO UP S C I - G A M E S - C L U B    ( Читальный Зал ) HOME

Занимательный компьютер "В МИРЕ НАУКИ" 1988/#02

Воспроизведение "живых" сцен на экране дисплея: задачи для начинающих программистов

А. К. ДЬЮДНИ

Эффективные кинофокусы не всегда требуют сложного технического оборудования или финансовой поддержки крупных киностудий. Любители фантастических сюжетов теперь сами могут воспроизводить удивительные явления, хотя и ограниченного репертуара, на экранах своих домашних компьютеров с помощью того, что можно было бы назвать программами видеоэффектов. Представим на минуту, что по экрану компьютера внезапно поползли червяки. Программа видеоэффектов способна создать такую "живую" сцену. Или, например, экран может превратиться в водяную поверхность с расходящимися кругами от падающих дождевых капель. Создать этот эффект тоже в общем-то довольно просто. И наконец, вообразим, что наш экран -- это иллюминатор, через который видна Вселенная с взрывающимися или стремительно пробегающими мимо звездами, как будто мы находимся на борту космического корабля, с колоссальной скоростью пролетающего по звездному коридору. Подобная иллюзия достигается при помощи третьей, довольно экономной программы.
     Экономия средств, на мой взгляд, одно из главных свойств программ подобного рода. Если достигается какой-то поразительный эффект, то лучше, если порождающая его программа оказывается чрезвычайно короткой. Как же лучше всего ввести читателей в таинственный мир удивительных явлений, видимых на экране дисплея и скрывающихся за ними. Судя по сравнительно небольшой, но всегда присутствующей части получаемой мной писем, многие начинающие любители компьютерных игр с грустью смотрят на страницы статей нашей рубрики, чувствуя свою неспособность превратить представленные в них алгоритмы в работающие программы. Они остаются лишь пассивными зрителями, когда мимо них в ярком парадном шествии проходят множества Мандельброта, лестницы слов, сотворенные компьютерами карикатуры, сосуды с первобытным бульоном и звездные скопления. Они могут лишь мечтать о той радости, которую испытывают авторы программ, видя, как алгоритмы обретают плоть и кровь и оживают на экране дисплея.
     ...
     Кто бы смог удержаться от соблазна написать программу, порождающую на экране симпатичных копошащихся червячков? Энтузиазм читателей, наверное, не очень пострадает, когда они узнают, что каждый червяк на экране представляет собой не что иное, как цепочку окружностей. Впрочем, чтобы составить программу для какого-нибудь видеоэффекта (и вообще любую программу), нужно на время абстрагироваться от эмоций и сосредоточиться на анализе. Каким же образом заставить червяка двигаться? Добавляя новую окружность у головы и удаляя старую у хвоста: в результате появляется ощущение движения, как будто бы червяк ползет, -- конечно, это иллюзия, но фокус тем не менее удается.
     Идея программы WORMS (червяки) зародилась у меня, когда я впервые увидел подобный эффект на экране моего новенького компьютера SUN. Кто-то занес эффектную графическую программу в каталог системных и прикладных программ, обычно поставляемых в комплекте с машиной. Этот кто-то, по-видимому, подумал, что зрелище копошащихся на большом экране дисплея SUN червей убедит покупателей, что высокая цена на машину вполне оправдана.
     Действительно, решение написать эту программу пришло, когда я задумался над тем, каким образом достигается впечатление, что червяк ползет. Пристально вглядываясь в экран, я вскоре понял, что эффект движения достигается каждый раз за счет добавления новой окружности к голове червяка и стирания старой в хвосте. "Ага, -- сказал я себе, -- это просто". Я сразу представил себе коротенькую программку, но затем подумал о том, что программа, стирающая старую окружность, должна помнить, где находится этя окружность. А поскольку каждое звено червяка рано или поздно нужно будет стереть, положение каждой окружности нужно запоминать.
     Простейшая структура данных, позволяющая запоминать большое число однородных элементов данных, это массив. Следовательно, теперь нужно было подумать о том, как можно запоминать окружности в массиве. На каком бы языке мы ни писали программу, графическая команда "нарисовать окружность" (или стереть ее, проведя по ее контуру черной линией) обычно требует указания двух координатных значений, а именно центра окружности и радиуса. Радиус всех окружностей, из которых строятся звенья червяков, будет постоянной величиной, а вот координаты центра должны меняться от одной окружности к другой. Поэтому необходимо хранить лишь координаты центров. Так как, вообще говоря, абсцисса центра отличается от ординаты, то координатные значения центров удобнее хранить не в одном, а в двух массивах. Назовем их xcirc и ycirc. Таким образом, элемент xcirc(i) будет хранить координату i-й окружности по оси x, а ycirc(i) -- по оси y.
     Теперь мы подошли к главной трудности в программе WORMS: нужно, чтобы она каким-то образом добавляла к массиву новые окружности и удаляла из него старые. Подобно червяку, сами массивы будут состоять из цепочек окружностей. Однако массивы не движутся по экрану. Мы заведем специальную переменную, называемую указателем, в которой будет храниться та позиция массива, где в данный момент содержится координата последней, хвостовой окружности червяка.
     ...
     Посредством какого механизма программа может решить, где следует нарисовать новую головную окружность? Очевидно, она должна быть в непосредственной близости от предыдущей и где-то "впереди" от нее. Более того, чтобы извивания и повороты червяка выглядели естественно, новое направление не должно слишком резко отличаться от предшествующего. Здесь решение проблемы заключается просто в том, чтоьы ввести одну-единственную новую переменную dir (от слова direction - направление). Она должна содержать текущее направление движения червяка, выраженное в градусах. При каждом повторении главного цикла программа будет произвольно либо увеличивать, либо уменьшать значение dir на 10 градусов.
     Прошло время решить, насколько близко друг от друга должны быть окружности и какого они должны быть размера. В качестве пробного значения радиуса можно принять, например, 4. Чтобы червяк выглядел как единое целое, нужно, чтобы окружности частично перекрывали друг друга.
     ...
     Одна проблема все же осталась: а что, если червяк уползет за пределы экрана? Чтобы решить ее, я наделил программу еще одним свойством. Если координатные значения x или y выходят за диапазон, соответствующий размерам экрана, то они автоматически преобразуются в координаты точки, расположенной на его противоположном крае. ...
     Ну вот и все, что касается программы WORMS. Или может быть правильнее было бы назвать ее WORM (червяк)? Ведь алгоритм порождает лишь одного червяка. Чтобы к названию программы по праву добавить окончание S, читатели могут завести по одному набору массивов и переменных для каждого червяка, который должен появиться на экране.
     ...
     Программы для других уже упомянутых видеоэффектов теперь, наверное, могут быть написаны даже новичками, если они к тому же воспользуются некоторыми подсказками. Программа, которую я назвал RAINDROPS (дождевые капли), случайным образом выбирает точку на экране дисплея и описывает вокруг нее последовательность концентрических окружностей возрастающего радиуса. Затем программа выбирает другую точку и повторяет процедуру построения окружностей. RAINDROPS продолжает работать до тех пор, пока "хозяин погоды" не нажмет клавишу. Таким образом, программа строится из двух циклов: внешнего цикла, в котором выбирается точка, и внутреннего цикла, в котором рисуются окружности вокруг выбранной точки. Программа преобразует два случайных числа в диапазоне между 0 и 1 в координаты точки на экране путем умножения этих чисел на соответствующие размеры экрана. Получаемая в результате точка (x, y) становится центром последовательности окружностей, рисуемых во внутреннем цикле. Пусть индекс k пробегает значения от 1 до 25 по мере того, как на экране строятся белые (или какого-нибудь другого цвета) окружности. Центры всех этих окружностей находятся в точке с координатами (x, y), а радиусы принимают значения, равные 4k. Проще, конечно, оставлять нарисованные таким образом окружности неподвижными. Однако эффект был бы более реалистичным, если бы несколько окружностей, или даже одна, распространялись, подобно волне. Для этого программа RAINDROPS должна стирать (перерисовывать черным цветом) окружность радиуса 4(k-1) всякий раз после того, как нарисована окружность радиуса 4k.
     Программа STARBURST (звездный взрыв) демонстрирует эффект космического взрыва. По существу тот же эффект можно интерпретировать как полет вдоль огромного звездного корридора, наблюдаемого из иллюминатора космического корабля, который движется с околосветовой скоростью. Звезды каждый раз перемещаются на небольшое расстояние вдоль линий перспективы по направлению к наблюдателю. Величина сдвига возрастает по мере того, как звезды приближаются к наблюдателю. Создается впечатление, что объекты, находящиеся ближе, движутся с большей скоростью по сравнению с удаленными объектами. Программа STARBURST несколько сложнее, чем RAINDROPS. Она должна постоянно следить за всеми звездами, находящимися в пределах экрана. Для этого читатели могут воспользоваться массивом, назвав его, скажем, stars (звезды) -- а правильнее будет сказать двумя массивами, как в программе WORMS, -- чтобы хранить координаты х и у каждой звезды. Координата z оказывается скрытой в кажущемся движении звезд.
     Когда звезда впервые появляется в исходной точке (100, 100), ее перемещения вначале очень малы, но затем они растут по мере того, как звезда приближается к наблюдателю (или наоборот -- наблюдатель приближается к звезде). Величина приращения обратно пропорциональна z -- кажущемуся расстоянию от наблюдателя. При составлении программы можно запланировать, например, по 25 сдвигов на каждую звезду, прежде чем она выйдет за пределы экрана. Таким образом, расстояние z до любой данной звезды можно принять равным 25-k, где k - количество итераций в расчете кажущихся расстояний до этой звезды.
     В большом цикле программы на каждом шаге создается одна новая звезда, а для всех остальных звезд координаты, хранящиеся в массивах, получают приращения.



http://www.chat.ru/~lifesoft Life Software  ( Last modified: Mon Aug 14 20:22:12 YEKST 2000 ) (C)