СПО в российских школах

Команда ALT Linux рассказывает о внедрении свободного программного обеспечения в школах России
Январь 21, 2011

BASIC-256. Глава 12

Методические материалы
Автор: Владимир Черный

Продолжаем публиковать перевод книги Джеймса Рено. Эту главу перевел Владимир Черный.
Оглавление:

Где взять BASIC-256

Глава 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 – останавливает воспроизведение текущего файла.
wavwait – останавливает исполнение дальнейших операторов программы, пока не закончится воспроизведение текущего звукового файла.

Перемещение картинок — спрайты

Спрайты — специальные графические объекты, которые можно перемещать по экрану без необходимости перерисовки экрана. Кроме этого можно определить когда два спрайта перекрываются (сталкиваются). Спрайты дают возможность более легкого программирования сложных игр и анимаций.

 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(номер_спрайта)

Эти функции возвращают различную информацию о загруженном спрайте
spriteh — возвращает высоту спрайта в пикселях
spritew — возвращает ширину спрайта в пикселях
spritex — возвращает координату х центра спрайта
spritey — возвращает координату y центра спрайта

Во втором примере (Программа 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

Windows версия
http://basic256.org (http://www.sourceforge.net/projects/kidbasic)

Как установить BASIC-256 в Linux

Для Альт Линукс: настроить репозиторий и обновить/установить пакет через synaptic или apt
Для rpm-based дистрибутивов: rpm -Uvh <имя_пакета>.rpm

Комментарии (9) к “BASIC-256. Глава 12”

  1. В качестве учебных материалов по BASIC256 предлагаю простые
    программы-картинки на основе математических формул, тетрис
    на BASIC256, тренажер по умножению и др. Программы составлены мной, снабжены комментариями, позволяющими легче
    понять алгоритм работы программы. Скачать можно с сайта
    compicture.ucoz.ru -буду рад, если программы помогут кому-
    нибудь в изучении языка.

  2. Владимир Черный говорит:
    Январь 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!

  3. Володя, вряд ли автор пойдет на ликвидацию goto :) ведь это же классика. Нужно ли запрещать вилки лишь потому, что некоторые личности могут тыкать ими не только в еду, но и в живых людей?

    Дружище Vovavobov, очень рад, что Вас заинтересовал BASIC-256 настолько, что Вы написали для него такие занимательные программы! Однако, присоединяюсь к комментариям Володи Черного — стиль прежде всего! Поэтому предлагаю проанализировать тексты своих программ, чтобы сделать их структурированными. К тому же, по мне, это не менее занимательно, чем программировать что-либо с нуля 😉

  4. Владимир Черный говорит:
    Январь 25, 2011, 1:38 пп

    Сергей, я конечно не экстремист… и понимаю, что goto иногда, очень очень очень редко (например, выйти экстренно из трех вложенных циклов) нужен, но программы уважаемого vovavobov — это программистский экстремизм, «fortran головного мозга». По ним надо учить, как НЕ НАДО программировать. Я так расстроился… не дай бог наших детей научат ТАК программировать :(
    Хотел написать комментарий автору на сайт напрямую, но у него там такая капча… Интересно, с какого раза он сам угадывает, что там за число написано?!! Мне с 10 попыток не удалось, хотя я и не дальтоник ни разу.

  5. Спасибо за критику! Я признаюсь, что еще не все операторы
    освоил, для меня BASIC256 стал своеобразным средством для
    отдыха- весьма интересно создавать небольшие программы,сразу наблюдая результат. Конечно, любую программу
    можно улучшить, но если мне удалось показать, что на этом
    языке можно не только домики и рожицы рисовать, то уже неплохо. В плане программирования и оформления сайта я не профессионал, был бы рад, если бы Вы объяснили про «..угадывание числа..» и «..10 попыток..», был бы весьма
    признателен, т.к. я не понял, о чем идет речь. Сайт вроде бы
    простой получился, не перегруженный лишней информацией.

  6. Владимир Черный говорит:
    Январь 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 — если комментарий убрать — увидим, как рисуется шар.

  7. oleg говорит:
    Январь 26, 2011, 4:46 пп

    В Паскале тоже есть GOTO :)
    Из вложенных циклов (двойных) выходить можно по ‘brake’, в Бейсике должен быть.
    Простота интерпретатора BASIC-256 позволит применять для среднего звена (5-9 классы), проведения факультативных занятий, организации внутришкольных Олимпиад по программированию. Да даже при изучении численных методов, Бейсик справится и с профильным мат. уровнем (10-11 классы)? Например, красиво бы вышло решение определенных интегралов (нахождение площадей трапеций методом прямоугольников), включая графически? Кто-нибудь может так решить? Я пас :)

  8. Владимир Черный говорит:
    Январь 26, 2011, 5:17 пп

    Олег! Я же написал про тройной цикл, если вы заметили… Ну, а что касается вашей задачки — не думаю, что она сложная. Вы начните ее решать.
    Посмотрите пример (мой) из предыдущего коммента убрав комментарий перед первым refresh (и поставив перед вторым). Аналогичным способом можно рисовать прямоугольники вписанные в конкретный график.
    Задача построения графика, конечно тоже сама по себе серьезная, но много раз решенная.
    Впрочем, Если кто найдет время задачку Олега решить на BASIC-256 — присылайте!

  9. oleg говорит:
    Январь 28, 2011, 2:01 пп

    Понятно, посмотрел как создается трехмерный эффект. Задачку по «прямоугольникам» пока не могу решить, сейчас разбираюсь с особенностями работы в OpenOffice Base (СУБД). Интересено, в 3 версии уже появилась возможность вставки изображений в таблицу, создавать связи между таблицами, подстановка данных списком.. Следующим по плану идет разбор полетов в ЛОГО :) у нас педколледж, начальная школа..

Оставьте комментарий