BASIC-256. Глава 12
Методические материалыАвтор: Владимир Черный
Продолжаем публиковать перевод книги Джеймса Рено. Эту главу перевел Владимир Черный.
Оглавление:
- Глава 1: Знакомство с BASIC-256 – cкажи «Привет»
- Глава 2: Рисуем основные фигуры
- Глава 3: Звуки и музыка
- Глава 4: Мыслить как программист
- Глава 5: Программа задает вам вопросы
- Глава 6: Сравнения, сравнения, сравнения
- Глава 7: Циклы и счетчики — повторяем снова и снова
- Глава 8: Графика на заказ — создание фигур своими руками
- Глава 9: Подпрограммы — повторное использование кода
- Глава 10: Управляем мышкой, перемещаем объекты
- Глава 11: Использование клавиатуры для управления программой
Глава 12 Картинки, музыка и спрайты
В этой главе мы начинаем изучать управление мультмедийным и графическим содержанием программ. Научимся загружать графические образы (картинки) из файлов, проигрывать асинхронно звуковые файлы типа WAV, а также создавать анимацию (мультфильмы) с использованием спрайтов.
Образы из файла
Ранее мы видели как создавать графические формы используя встроенные инструменты рисования. Функция imgload позволит вам загружать картинки прямо из файла и отображать их в ваших программах на BASIC-256.
1 # imgload_ball.kbs — Демонстрация функции Imgload
2 clg
3 for i = 1 to 50
4 imgload rand * graphwidth, rand * graphheight, "greenball.png"
5 next i
Программа 60 Загрузка графического файла.
Пример вывода программы 60 Загрузка графического файла
Программа 60 показывает действие imgload. Последний аргумент этой функции — имя графического файла на вашем компьютере. Необходимо, чтобы это файл был в одном и том же каталоге с программой, иначе надо указать полный путь к файлу. Обратите внимание, что координаты (x,y) — это центр загруженной картинки, а не верхний левый угол.
В большинстве случаев удобно сохранять файлы с картинками и звуками в том же каталоге, что и программа до того, как вы ее запустите. Это задает текущий рабочий каталог программы так, что BASIC-256 сможет эти файлы найти и загрузить. |
imgload x, y, имя_файла imgload x, y, коэфф_искажения, имя_файла imgload x, y, коэфф_искажения, угол, имя_файла Функция читает картинку из файла и показывает ее в области графического вывода. Значения x и y соответствуют центру образа. Образы могут быть различных форматов: BMP, PNG, GIF, JPG, иJPEG Дополнительно можно изменить размер картинки задав десятичное число коэфф_искажения. Коэффициент равный 1 означает полный размер. Если вы хотите предварительно повернуть картинку, задайте угол поворота по часовой стрелке в радианах (от 0 до 2π) |
Функция impload также позволяет масштабировать картинку и поворачивать ее, как это делает stamp. В качестве примера посмотрите программу 61
1 # imgload_picasso.kbs — Загрузка картинки с вращением и масштабированием
2 graphsize 500,500
3 clg
4 for i = 1 to 50
5 imgload graphwidth/2, graphheight/2, i/50, 2*pi*i/50, "picasso_selfport1907.jpg"
6 next i
7 say "Здравствуй, Пикассо."
Программа 61 Загрузка картинки с масштабированием и вращением.
Примерный вывод программы 61 Загрузка картинки с масштабированием и вращением.
Воспроизведение звуков из файлов типа WAV
До сих пор для извлечения звуков мы использовали команду sound и команду say преобразования текста в звук. BASIC-256 также умеет воспроизводить звуки, записанные в WAV-файл. Воспроизведение звука из WAV-файла происходит в фоновом режиме. Программа продолжает выполнять команды идущие после команды запуска звука, при этом звук также продолжает воспроизводиться.
1 # spinner.kbs
2 fastgraphics
3 wavplay "roll.wav"
4
5 # задаем параметры вращающегося луча
6 angle = rand * 2 * pi
7 speed = rand * 2
8 color darkred
9 rect 0,0,300,300
10
11 for t = 1 to 100
12 # рисуем вращающийся луч
13 color white
14 circle 150,150,150
15 color black
16 line 150,300,150,0
17 line 300,150,0,150
18 text 100,100,"A"
19 text 200,100,"B"
20 text 200,200,"C"
21 text 100,200,"D"
22 color darkgreen
23 line 150,150,150 + cos(angle)*150, 150 + sin(angle)*150
24 refresh
25 # update angle for next redraw
26 angle = angle + speed
27 speed = speed * .9
28 pause .05
29 next t
30
31 # ждем, пока перестанет звучать воспроизводимый звуковой файл.
32 wavwait
Программа 62 Вращающийся луч (радар) со звуковым сопровождением.
Примерный вывод программы 62
wavplay имя_файла wavwait wavstop Функция wavplay загружает файл типа .wav из текущего каталога и воспроизводит его. Следующая инструкция программы выполняется сразу же как начинается воспроизведение звука. wavstop – останавливает воспроизведение текущего файла. |
Перемещение картинок — спрайты
Спрайты — специальные графические объекты, которые можно перемещать по экрану без необходимости перерисовки экрана. Кроме этого можно определить когда два спрайта перекрываются (сталкиваются). Спрайты дают возможность более легкого программирования сложных игр и анимаций.
1 # sprite_1ball.kbs
2
3 color white
4 rect 0, 0, graphwidth, graphheight
5
6 spritedim 1
7
8 spriteload 0, "blueball.png"
9 spriteplace 0, 100,100
10 spriteshow 0
11
12 dx = rand * 10
13 dy = rand * 10
14
15 while true
16 if spritex(0) <=0 or spritex(0) >= graphwidth -1 then
17 dx = dx * -1
18 wavplay "4359__NoiseCollector__PongBlipF4.wav"
19 end if
20 if spritey(0) <= 0 or spritey(0) >= graphheight -1 then
21 dy = dy * -1
22 wavplay "4361__NoiseCollector__pongblipA_3.wav"
23 endif
24 spritemove 0, dx, dy
25 pause .05
26 end while
Программа 63 Прыгающий мяч с использованием спрайтов и звуковых эффектов.1
Пример экрана программы 63
По коду программы 63 видно, что достижение анимационного эффекта прыгающего мяча со звуком проще, чем это можно было бы реализовать ранее. Для использования спрайтов, необходимо сообщить программе на BASIC-256 сколько их будет (функция spritedim), определить спрайт (командой spriteload или spriteplace), затем сделать его видимым (командой spriteshow), и затем только перемещать (командой spritemove). Кроме этого, есть еще функции, позволяющие определить положение спрайта на экране (команды spritex и spritey), его размеры (команды spritew и spritey) и его видимость (команда spritev).
spritedim количество_спрайтов
Функция spritedim резервирует в памяти место для указанного количества спрайтов. Вы можете создать столько спрайтов, сколько нужно, однако, если вы создадите слишком много спрайтов, программа будет работать очень медленно. |
spriteload номер_спрайта, имя_файла
Эта команда загружает графический файл (форматов GIF, BMP, PNG, JPG, или JPEG) с учетом пути (если указан) к файлу, и создает спрайт. По умолчанию спрайт помещается на экран так, что его центр находится в точке (0,0) и спрайт скрыт. Необходимо его переместить в нужную позицию экрана (используя spritemove или spriteplace) и затем показать его (используя spriteshow) |
spritehide номер_спрайта spriteshow номер_спрайта Команда spriteshow показывает на экране графического вывода предварительно загруженный, созданный или спрятанный спрайт. Команда spritehide делает указанный (по номеру) спрайт невидимым на экране. Этот спрайт по прежнему существует и его можно будет показать позже. |
spriteplace номер_спрайта, x, y
Эта команда помещает центр спрайта в указанную координатами x и y точку экрана. |
spritemove номер_спрайта, dx, dy
Эта команда перемещает спрайт на dx пикселей вправо и на dy пикселей вниз. Отрицательные значения также можно использовать для обозначения перемещения спрайта влево и вверх. Центр спрайта не может выйти за границы окна графического вывода т.е. всегда в пределах от (0,0) до (graphwidth-1, graphheight-1). Можно перемещать скрытый спрайт, но его не будет видно, пока вы не покажете его используя команду showsprite. |
spritev(номер_спрайта)
Эта функция возвращает true (истина), если спрайт виден в графической области экрана и false (ложь), когда спрайт не виден. |
spriteh(номер_спрайта) spritew(номер_спрайта) spritex(номер_спрайта) spritey(номер_спрайта) Эти функции возвращают различную информацию о загруженном спрайте |
Во втором примере (Программа 64) у нас будет два спрайта. Первый спрайт (номер нуль) – неподвижный, а второй (номер один) будет прыгать, отражаясь от стенок и неподвижного спрайта.
1 # sprite_bumper.kbs
2
3 color white
4 rect 0, 0, graphwidth, graphheight
5
6 spritedim 2
7
8 # спрайт-отбойник
9 spriteload 0, "paddle.png"
10 spriteplace 0,graphwidth/2,graphheight/2
11 spriteshow 0
12
13 # подвижный мяч
14 spriteload 1, "blueball.png"
15 spriteplace 1, 50, 50
16 spriteshow 1
17 dx = rand * 5 + 5
18 dy = rand * 5 + 5
19
20 while true
21 if spritex(1) <=0 or spritex(1) >= graphwidth -1 then
22 dx = dx * -1
23 end if
24 if spritey(1) <= 0 or spritey(1) >= graphheight -1 then
25 dy = dy * -1
26 end if
27 if spritecollide(0,1) then
28 dy = dy * -1
29 print "Ба-бах!"
30 end if
31 spritemove 1, dx, dy
32 pause .05
33 end while
Программа 64 Столкновение спрайтов.2
Примерный экран программы 64 Столкновение спрайтов
spritecollide(номер_первого, номер_второго)
Эта функция возвращает true (истину), если два спрайта столкнулись или один перекрывает другой.3 |
Большая программа данной главы использует спрайты и звуки для создания игры типа пинг-понг. |
1 # sprite_paddleball.kbs
2
3 color white
4 rect 0, 0, graphwidth, graphheight
5
6 spritedim 2
7
8 spriteload 1, "greenball.png"
9 spriteplace 1, 100,100
10 spriteshow 1
11 spriteload 0, "paddle.png"
12 spriteplace 0, 100,270
13 spriteshow 0
14
15 dx = rand * .5 + .25
16 dy = rand * .5 + .25
17
18 bounces = 0
19
20 while spritey(1) < graphheight -1
21 k = key
22 if chr(k) = "K" then
23 spritemove 0, 20, 0
24 end if
25 if chr(k) = "J" then
26 spritemove 0, -20, 0
27 end if
28 if spritecollide(0,1) then
29 # отскок назад с увеличением скорости
30 dy = dy * -1
31 dx = dx * 1.1
32 bounces = bounces + 1
33 wavstop
34 wavplay "96633__CGEffex__Ricochet_metal5.wav"
35 # отражение спрайта мяча от ракетки
36 while spritecollide(0,1)
37 spritemove 1, dx, dy
38 end while
39 end if
40 if spritex(1) <=0 or spritex(1) >= graphwidth -1 then
41 dx = dx * -1
42 wavstop
43 wavplay "4359__NoiseCollector__PongBlipF4.wav"
44 end if
45 if spritey(1) <= 0 then
46 dy = dy * -1
47 wavstop
48 wavplay "4361__NoiseCollector__pongblipA_3.wav"
49 end if
50 spritemove 1, dx, dy
51 end while
52
53 print "Вы отбили мяч " + bounces + " раз(а)."
Программа 65. Пинг-понг
Примерный вывод программы 65 Пинг-понг
—————————————————
1Автор не учитывает размер мяча, что приводит к кажущемуся запаздыванию звука. Столкновение мяча со стенкой стоит определять не по центру шара (спрайта) а по его краю, а именно в строках 16 и 20 соответственно вычитать или прибавлять радиус шара (spritew(0)/2) (прим. переводчика).
2Автор опять, видимо в целях упрощения программы, не учитывает соударение неподвижного спрайта с подвижным, когда удар приходится в левую или правую стенку прямоугольника, изображающего неподвижный спрайт. В этот момент, подвижный спрайт начинает скакать вдоль неподвижного. В качестве упражнения, предлагаем поправить код (прим. переводчика).
3Функция слишком примитивна. На самом дела она вычисляет столкнулись ли два прямоугольника, описанных около спрайта. Если в примере 64 неподвижный спрайт будет в виде тонкой палочки, идущей по диагонали, вы наглядно убедитесь в бесполезности этой функции.(прим. переводчика).
Где скачать BASIC-256:
Для дистрибутивов ALT Linux
- ветка 4.0 basic256-0.9.6-alt5.M40.1.i586.rpm
- ветка 4.1 basic256-0.9.6-alt5.M41.1.i586.rpm
- ветка p5 basic256-0.9.6-alt5.M50P.1.i586.rpm
- ветка 5.1 basic256-0.9.6-alt5.M51.1.i586.rpm
Windows версия
http://basic256.org (http://www.sourceforge.net/projects/kidbasic)
Как установить BASIC-256 в Linux
Для Альт Линукс: настроить репозиторий и обновить/установить пакет через synaptic или apt
Для rpm-based дистрибутивов: rpm -Uvh <имя_пакета>.rpm
Январь 24, 2011, 11:37 дп
В качестве учебных материалов по BASIC256 предлагаю простые
программы-картинки на основе математических формул, тетрис
на BASIC256, тренажер по умножению и др. Программы составлены мной, снабжены комментариями, позволяющими легче
понять алгоритм работы программы. Скачать можно с сайта
compicture.ucoz.ru -буду рад, если программы помогут кому-
нибудь в изучении языка.
Январь 25, 2011, 11:57 дп
Уважаемый vovavobov! Примеры визуально красивые и в этом их прелесть — прельщать учеников самим процессом 😉 Но, я категорически не советую учить по ним программированию! Даже сам автор говорит — используйте goto как можно меньше, а в ваших программах это везде, где надо и не надо!
Например zz.kbs
фрагмент:
6 f:
7 k=255-p
8 color k/2,k,k
9 circle 300,300,p
10 p=p-1
11 if k<255 then goto f
легко заменяется на:
7 for k=0 to 255
8 color k/2,k,k
9 circle 300,300,p
10 p=p-1
11 next k
Так что если хотите учить других — научитесь сначала правильному стилю программирования сами (прочтите, наконец, главу 7 !), а то я уже начинаю жалеть, что вытащил этот бейсик на всеобщее рассмотрение Надо попросить автора ликвидировать этот оператор goto!
Январь 25, 2011, 12:58 пп
Володя, вряд ли автор пойдет на ликвидацию goto ведь это же классика. Нужно ли запрещать вилки лишь потому, что некоторые личности могут тыкать ими не только в еду, но и в живых людей?
Дружище Vovavobov, очень рад, что Вас заинтересовал BASIC-256 настолько, что Вы написали для него такие занимательные программы! Однако, присоединяюсь к комментариям Володи Черного — стиль прежде всего! Поэтому предлагаю проанализировать тексты своих программ, чтобы сделать их структурированными. К тому же, по мне, это не менее занимательно, чем программировать что-либо с нуля 😉
Январь 25, 2011, 1:38 пп
Сергей, я конечно не экстремист… и понимаю, что goto иногда, очень очень очень редко (например, выйти экстренно из трех вложенных циклов) нужен, но программы уважаемого vovavobov — это программистский экстремизм, «fortran головного мозга». По ним надо учить, как НЕ НАДО программировать. Я так расстроился… не дай бог наших детей научат ТАК программировать
Хотел написать комментарий автору на сайт напрямую, но у него там такая капча… Интересно, с какого раза он сам угадывает, что там за число написано?!! Мне с 10 попыток не удалось, хотя я и не дальтоник ни разу.
Январь 26, 2011, 1:18 пп
Спасибо за критику! Я признаюсь, что еще не все операторы
освоил, для меня BASIC256 стал своеобразным средством для
отдыха- весьма интересно создавать небольшие программы,сразу наблюдая результат. Конечно, любую программу
можно улучшить, но если мне удалось показать, что на этом
языке можно не только домики и рожицы рисовать, то уже неплохо. В плане программирования и оформления сайта я не профессионал, был бы рад, если бы Вы объяснили про «..угадывание числа..» и «..10 попыток..», был бы весьма
признателен, т.к. я не понял, о чем идет речь. Сайт вроде бы
простой получился, не перегруженный лишней информацией.
Январь 26, 2011, 2:55 пп
Уважаемый vovavobov, начну с конца. У вас есть формочка для комментариев, она заканчивается «капчей» — нарисованное число, которое надо ввести — так вот там практически нет человеко-читаемых картинок. Так что комментариев у вас практически не будет.
Теперь о программах. Я не говорю об оптимизации программы, я говорю о стиле програмирования. Там где можно обойтись без goto — надо обходиться без него.
Например, ваша заставка из шариков (6_shar)
graphsize (600,600)
clg
a:
pause 1.5
b:
p=255*rand
n=600*rand
t=600*rand
z=600*rand
if p255 then goto a
color n/3,255-p,z/3
circle n-0.2*p,t+0.5*p,p
p=p-1
if k>0 then goto f
goto a
Вот мой вариант:
dim c(3)
dim m(2)
graphsize (600,600)
clg
fastgraphics
while true
pause .5
c={int(255*rand),int(175*rand)+80,int(255*rand)}
m={int(600*rand),int(600*rand)}
for p=c[1] to 0 step -1
color c[0],255-p,c[2]
circle m[0]-0.2*p,m[1]+0.5*p,p
# refresh
next p
refresh
end while
Он использует циклы и быструю графику, ну, и массивы (можно обойтись). Но, главное зачем вам столько goto там понадобилось? Я уж не говорю о том, чтобы получить случайное число от 80 до 255 совсем не нужен цикл!!!
Маленькое замечание — первый закомментареный refresh — если комментарий убрать — увидим, как рисуется шар.
Январь 26, 2011, 4:46 пп
В Паскале тоже есть GOTO
Из вложенных циклов (двойных) выходить можно по ‘brake’, в Бейсике должен быть.
Простота интерпретатора BASIC-256 позволит применять для среднего звена (5-9 классы), проведения факультативных занятий, организации внутришкольных Олимпиад по программированию. Да даже при изучении численных методов, Бейсик справится и с профильным мат. уровнем (10-11 классы)? Например, красиво бы вышло решение определенных интегралов (нахождение площадей трапеций методом прямоугольников), включая графически? Кто-нибудь может так решить? Я пас
Январь 26, 2011, 5:17 пп
Олег! Я же написал про тройной цикл, если вы заметили… Ну, а что касается вашей задачки — не думаю, что она сложная. Вы начните ее решать.
Посмотрите пример (мой) из предыдущего коммента убрав комментарий перед первым refresh (и поставив перед вторым). Аналогичным способом можно рисовать прямоугольники вписанные в конкретный график.
Задача построения графика, конечно тоже сама по себе серьезная, но много раз решенная.
Впрочем, Если кто найдет время задачку Олега решить на BASIC-256 — присылайте!
Январь 28, 2011, 2:01 пп
Понятно, посмотрел как создается трехмерный эффект. Задачку по «прямоугольникам» пока не могу решить, сейчас разбираюсь с особенностями работы в OpenOffice Base (СУБД). Интересено, в 3 версии уже появилась возможность вставки изображений в таблицу, создавать связи между таблицами, подстановка данных списком.. Следующим по плану идет разбор полетов в ЛОГО у нас педколледж, начальная школа..