Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

13. Мультипликация (движение картинки)

   Управление картинкой на “пустом” экране ничем не отличается от управления окружностью - нарисовал - стер - нарисовал на новом месте. Но если на экране уже есть какое-то изображение, на фоне которого должна двигаться картинка, то возникает проблема - как стереть “старое” изображение, чтобы не испортить фон.

   Здесь нам поможет “связка” операторов GET и PUT.

   Вспомним, что при выводе оператором PUT картинки на экран, по умолчанию над цветом точки экрана и цветом точки картинки выполняется логическая операция “исключающее или”. При этом на месте точек, совпадающих по цвету, появляются черные “дыры” (точнее, прозрачные “дыры”, через которые виден цвет фона). Значит, если наложить картинку саму на себя, то она исчезнет с экрана. Если фон экрана уже содержит изображение, то при первом выводе картинки ее цвета изменятся (к сожалению!), но зато при втором выводе восстановится фоновое изображение. В ряде случаев изменение цветов картинки нежелательно, тогда приходится использовать другой алгоритм, который мы разберем позже.

   Итак, за основу возьмем алгоритм управления окружностью и программу CIRCLES.BAS. Дополним алгоритм “нулевым” пунктом:

      0. Рисуем и запоминаем картинку

и немного модифицируем остальные пункты:

  1. Задаем константы.
  2. Задаем исходное положение картинки и выводим ее на экран.
  3. Ждем нажатия клавиши.
  4. Вычисляем новое положение картинки.
  5. Стираем картинку на старом и выводим ее на новом месте.
  6. Обновляем переменные, отвечающие за положение картинки, и переходим к пункту 3.

   Положение картинки на экране задается следующим образом: фиксируется некоторая точка картинки и задаются ее координаты на экране. За эту точку картинка “привязывается” к экрану, поэтому ее иногда называют точкой привязки. В качестве точки привязки возьмем левый верхний угол (вершину) прямоугольной области, в которой размещена картинка.

x = 0 1 2 3 4 5 6 7 8
y = 0     7 7 7 7 7    
1   8           8  
2 8     8   8     8
3 8   3 3   3 3   8
4 8               8
5 8     12 12 12     8
6   8           8  
7     8 8 8 8 8    

   Для рисования картинки можно использовать любые графические операторы, но если картинка маленькая, удобнее задавать ее по точкам. Посмотрим на увеличенный рисунок рожицы.

 

   В таблице справа записаны цвета отдельных точек картинки. (Подразумевается, что пустые клетки таблицы заполнены нулями.)

   В программе на Quick Basic таблицу чисел удобно задать с помощью оператора DATA.


‘Задаем картинку

DATA 0, 0, 7, 7, 7, 7, 7, 0, 0
DATA 0, 8, 0, 0, 0, 0, 0, 8, 0
DATA 8, 0, 0, 8, 0, 8, 0, 0, 8
DATA 8, 0, 3, 3, 0, 3, 3, 0, 8
DATA 8, 0, 0, 0, 0, 0, 0, 0, 8
DATA 8, 0, 0, 12, 12, 12, 0, 0, 8
DATA 0, 8, 0, 0, 0, 0, 0, 8, 0
DATA 0, 0, 8, 8, 8, 8, 8, 0, 0

‘Выводим ее на экран

SCREEN 7
DIM a%(40)
FOR y = 0 TO 7
   FOR x = 0 TO 8
      READ c: PSET (x, y), c
   NEXT x
NEXT y

‘Запоминаем картинку в массиве и очищаем экран

GET (0, 0)-(8, 7), a%
CLS

‘Задаем константы

lf$ = CHR$(0) + CHR$(75)
rt$ = CHR$(0) + CHR$(77)
up$ = CHR$(0) + CHR$(72)
dn$ = CHR$(0) + CHR$(80)

‘Задаем исходное положение картинки и выводим ее на экран

x0 = 165: y0 = 45: x = x0: y = y0
PUT (x0, y0), a%

‘Ждем нажатия клавиши

10 w$ = INKEY$: IF w$ = "" THEN GOTO 10

‘Вычисляем новое положение картинки

SELECT CASE w$
   CASE  lf$: x = x0 - 5
   CASE  rt$: x = x0 + 5
   CASE  up$: y = y0 - 5
   CASE  dn$:  y = y0 + 5
   CASE CHR$(27): STOP
   CASE ELSE: GOTO 10
END SELECT

‘Стираем картинку на старом и выводим на новом месте

PUT (x0, y0), a%
PUT (x, y), a%

‘Обновляем переменные

x0 = x: y0 = y
GOTO 10

   Запишем программу в файл ROZICA.BAS и попробуем ее выполнить. Пока “рожица” бегает по экрану - все хорошо. Но при попытке увести ее за экран появляется сообщение об ошибке “Illegal function call” и высвечивается строка с оператором PUT(x, y), a%. Что ж, будем контролировать значения переменных x и y, а при необходимости, восстанавливать прежние значения. Это просто для случаев движения влево или вверх, так как (x, y) - координаты левого верхнего угла картинки:

CASE lf$: x = x0 - 5: IF x < 0 THEN x = x0

CASE up$: y = y0 - 5: IF y < 0 THEN y = y0

   

Если же мы движемся вправо или вниз, то необходимо чтобы правый нижний угол картинки еще помещался на экране. Чтобы не менять во всей программе параметры экрана при их изменениях, введем переменные xmax - номер самой правой точки экрана и ymax - номер самой нижней точки экрана (для SCREEN 7 xmax = 319, ymax = 199). То же самое относится и к изменению размеров картинки - пусть она при выводе в левый верхний угол экрана занимает место от 0 до dx по горизонтали и от 0 до dy по вертикали. Тогда проверочные условия примут вид:

CASE rt$: x = x0 + 5: IF x + dx > xmax THEN x = x0

CASE dn$: y = y0 + 5: IF y + dy > ymax THEN y = y0

   Естественно значения dx и dy задавать после операторов DATA, а переменные xmax и ymax инициализировать после оператора SCREEN. В результате доработок получим следующую программу:


‘ ---------- Программа “Рожица” ----------
‘Задаем картинку DATA 0, 0, 7, 7, 7, 7, 7, 0, 0 DATA 0, 8, 0, 0, 0, 0, 0, 8, 0 DATA 8, 0, 0, 8, 0, 8, 0, 0, 8 DATA 8, 0, 3, 3, 0, 3, 3, 0, 8 DATA 8, 0, 0, 0, 0, 0, 0, 0, 8 DATA 8, 0, 0, 12, 12, 12, 0, 0, 8 DATA 0, 8, 0, 0, 0, 0, 0, 8, 0 DATA 0, 0, 8, 8, 8, 8, 8, 0, 0 dx = 8: dy = 7 ‘Выводим ее на экран SCREEN 7: xmax = 319: ymax = 199 DIM a%(40) FOR y = 0 TO dy FOR x = 0 TO dx READ c: PSET (x, y), c NEXT x NEXT y ‘Запоминаем картинку в массиве и очищаем экран GET (0, 0)-(dx, dy), a% CLS ‘Задаем исходное положение картинки и выводим ее на экран x0 = 165: y0 = 45: x = x0: y = y0 PUT (x0, y0), a% ‘Ждем нажатия клавиши 10 w$ = INKEY$: IF w$ = "" THEN GOTO 10 ‘Вычисляем новое положение картинки SELECT CASE w$ CASE lf$: x = x0 - 5: IF x < 0 THEN x = x0 CASE up$: y = y0 - 5: IF y < 0 THEN y = y0 CASE rt$: x = x0 + 5: IF x + dx > xmax THEN x = x0 CASE dn$: y = y0 + 5: IF y + dy > ymax THEN y = y0 CASE CHR$(27): STOP CASE ELSE: GOTO 10 END SELECT ‘Стираем картинку на старом и выводим на новом месте PUT (x0, y0), a% PUT (x, y), a% ‘Обновляем переменные x0 = x: y0 = y GOTO 10

   Задание. Запишите программу под тем же именем. Нарисуйте фон, по которому будет двигаться рожица. Убедитесь, что при движении рожицы фон не портится. Задайте вместо рожицы другую картинку (человечка, кошку, крестик и т.д.). Сохраните результат под другим именем.

 

14. Графический редактор “Раскрашка”

   Применим полученные знания для выполнения довольно большого проекта - написания графического редактора “Раскрашка”. В этом редакторе можно закрашивать заложенные в программу контурные рисунки. Опишем схему работы программы.

   На экране находится контурный рисунок и палитра цветов. Для выбора цвета закраски передвигаем курсор - картинку-указатель на прямоугольник с нужным цветом и нажимаем Enter. Затем перемещаем курсор на основное поле так, чтобы он указывал на какую-нибудь область рисунка. После нажатия на Enter область закрашивается выбранным ранее цветом. Для правильной работы оператора закрашивания нужно, чтобы все границы были нарисованы одним и тем же цветом. Понятно, что этот цвет следует исключить из палитры, так как область, закрашенную цветом границы, нельзя будет перекрасить другим цветом.

   За основу “Раскрашки” возьмем программу “Рожица”. Загрузим программу и запишем ее в файл RASCRAS.BAS куда и будем вносить все изменения.

   Начнем с курсора. Зададим шаблон курсора-стрелки, отмечая точки курсора единичками.

  0 1 2 3 4 5 6 7
0 1              
1 1 1            
2 1 1 1          
3 1 1 1 1        
4 1 1 1 1 1      
5 1 1 1 1 1 1    
6 1 1 1 1 1 1 1  
7 1 1 1 1 1 1 1 1
8 1 1 1 1 1      
9 1 1 1 1 1      
10 1 1 1 1 1 1    
11 1       1 1    
12         1 1    
13         1 1 1  
14           1 1  
15           1 1  
‘Шаблон курсора-стрелки
 DATA 1, 0, 0, 0, 0, 0, 0, 0
 DATA 1, 1, 0, 0, 0, 0, 0, 0
 DATA 1, 1, 1, 0, 0, 0, 0, 0
DATA 1, 1, 1, 1, 0, 0, 0, 0
DATA 1, 1, 1, 1, 1, 0, 0, 0
DATA 1, 1, 1, 1, 1, 1, 0, 0
DATA 1, 1, 1, 1, 1, 1, 1, 0
DATA 1, 1, 1, 1, 1, 1, 1, 1
DATA 1, 1, 1, 1, 1, 0, 0, 0
DATA 1, 1, 1, 1, 1, 0, 0, 0
DATA 1, 1, 1, 1, 1, 1, 0, 0
DATA 1, 0, 0, 0, 1, 1, 0, 0
DATA 0, 0, 0, 0, 1, 1, 0, 0
DATA 0, 0, 0, 0, 1, 1, 1, 0
DATA 0, 0, 0, 0, 0, 1, 1, 0
DATA 0, 0, 0, 0, 0, 1, 1, 0

Как и раньше, выведем курсор на экран для дальнейшего запоминания в памяти, после чего экран очистим. Но цвет 1 - это синий цвет, и стрелка будет плохо видна на экране. Поэтому при выводе заменим цвет курсора на более яркий.


dx = 7: dy = 15

SCREEN 7: xmax = 319: ymax = 199
DIM a%(40)
FOR y = 0 TO dy
   FOR x = 0 TO dx
      READ c: IF c = 1 THEN c = 10  ‘Изменение цвета курсора
      PSET (x, y), c
   NEXT x
NEXT y

‘Запоминаем картинку в массиве и очищаем экран

GET (0, 0)-(dx, dy), a%
CLS

   Теперь рисуем рамку основного поля, палитру и индикатор.


LINE (0, 0)-(xmax, ymax), 15, B
LINE (80, 0)-(80, ymax), 15
LINE (10, 10)-(70, 160), 15, B<

‘Заполняем палитру красками

c = 14
FOR y = 20 TO 150 STEP 10
   LINE (10, y)-(80, y), 15
   PAINT (40, y-5), c, 15
   c = c - 1
NEXT y

‘Индикатор

CIRCLE (40,180), 10, 15

   Далее должна следовать часть программы, создающая контурный рисунок на основном поле. Нарисуем, например, “мишень”:


FOR r = 10 TO 100 STEP 15
   CIRCLE (200, 100), r, 15
NEXT r

   Чтобы контурный рисунок не мог нечаянно выйти за пределы основного поля, можно ограничить область вывода с помощью оператора VIEW:

   VIEW (x1, y1)-(x2, y2) - устанавливает прямоугольное окно вывода с новой системой координат, начало которой располагается в левом верхнем углу окна. Относительные (локальные) координаты позволяют не задумываться о том, в каком месте экрана будет в дальнейшем расположен рисунок. Если по каким-либо причинам требуется сохранить в окне систему координат экрана, то следует использовать вариант

   VIEW SCREEN (x1, y1)-(x2, y2).

   Чтобы восстановить возможность вывода на весь экран, следует применить оператор VIEW без параметров.

   Следующую часть программы - управление курсором - позаимствуем из программы “Рожица”, только в комментариях заменим “картинку” на “курсор”. Изменим и шаг перемещения курсора, чтобы можно было закрашивать маленькие области. (Оптимальный вариант - ввести переменную, значение которой можно было бы изменять, нажимая какие-то клавиши на клавиатуре, например, клавиши“<” и “>”).


‘Задаем константы

lf$ = CHR$(0) + CHR$(75)
rt$ = CHR$(0) + CHR$(77)
up$ = CHR$(0) + CHR$(72)
dn$ = CHR$(0) + CHR$(80)

‘Задаем исходное положение курсора и выводим его на экран

x0 = 165: y0 = 45: x = x0: y = y0
PUT (x0, y0), a%

‘Ждем нажатия клавиши

10 w$ = INKEY$: IF w$ = "" THEN GOTO 10

‘Вычисляем новое положение курсора

SELECT CASE w$
   CASE   lf$: x = x0 - 2: IF x < 0 THEN x = x0
   CASE  up$: y = y0 - 2: IF y < 0 THEN y = y0
   CASE  rt$: x = x0 + 2: IF x +  dx > xmax THEN x = x0
   CASE  dn$: y = y0 + 2: IF y + dy > ymax THEN y = y0
   CASE CHR$(27): STOP
   CASE ELSE: GOTO 10
END SELECT

‘Стираем курсор на старом и выводим на новом месте

PUT (x0, y0), a%
PUT (x, y), a%

‘Обновляем переменные

x0 = x: y0 = y
GOTO 10

   Добавим теперь в оператор выбора реакцию программы на нажатие клавиши Enter. Эту клавишу мы нажимаем в двух случаях: когда хотим выбрать цвет закрашивания, и когда указываем область для закраски. Различить эти случаи легко: в первом случае острие стрелки (точка x0, y0) находится в прямоугольнике (10, 10)-(70, 160) - это границы палитры; во втором - в прямоугольнике (80, 0)-(xmax, ymax) - это границы основного поля.


   CASE CHR$(13)
      IF x0 > 10 AND x0 < 70 AND y0 > 10 AND y0 < 160 THEN
        ‘Определяем цвет краски на палитре
         c = 15 - y0 \ 10
        ‘Прячем курсор
         PUT (x0, y0), a%
        ‘закрашиваем индикатор
         PAINT (40, 180), c, 15
        ‘и восстанавливаем курсор на том же месте
         PUT (x0, y0), a%
      END IF

   Получить формулу, которая связывает номер цвета с расположением краски на палитре, поможет следующая таблица:

Интервал

Номер
интервала

Цвет
10 < y < 20 1 14
20 < y < 30 2 13
30 < y < 40 3 12
... ... ...
150<y<160 15 0

   Легко видеть, что номер интервала и цвет в сумме равны 15 в любой строке таблицы, а номер интервала равен количеству полных десятков в числе y. Вычислить номер интервала можно с помощью операции целочисленного деления: n = y \ 10. После этого цвет краски получается по формуле c = 15 - n.

   Заметим, что простота формулы есть результат простой закономерности в расположении цветов палитры. В других случаях может оказаться проще “считывать” цвет непосредственно с экрана, используя функцию POINT.

   POINT(x, y) - возвращает цвет пикселя экрана с координатами (x, y).

   Зачем потребовалось стирать курсор перед закрашиванием индикатора? Дело в том, что при закраске области может оказаться, что курсор задевает ее границу. В этом месте граница исчезнет, и через образовавшуюся “дыру” краска вытечет за пределы области. Поэтому перед любым закрашиванием мы будем убирать курсор с экрана, а после - возвращать на экран. (“Прятать” курсор придется и при определении функцией POINT цвета точки (x0, y0), которая находится под курсором.)

   Займемся теперь основным полем.


      IF x0 > 80 AND x0 < xmax AND y0 > 0 AND y0 < ymax THEN
        ‘Прячем курсор
         PUT (x0, y0), a%
        ‘Закрашиваем область
         PAINT (x0, y0), c, 15
        ‘Восстанавливаем курсор
         PUT (x0, y0), a%
      END IF

   Задание. Придумать и вставить в программу свой рисунок для раскрашивания (ниже приведен пример выполнения задания).

 

15. Графические режимы монитора VGA

   При наличии монитора VGA дополнительно можно пользоваться графическими режимами SCREEN 10, 11, 12 или 13.

   SCREEN 10 - разрешение 640х350 точек, цветовая палитра - черно-белая с возможностью мигания ( 0 - черный цвет, 1 - белый цвет, 2 - мигающий ).

   SCREEN 11 - разрешение 640х480 точек, цветовая палитра - черно-белая ( 0 - черный цвет, 1 - белый цвет).

   SCREEN 12 - разрешение 640х350 точек, цветовая палитра - 16 цветов. В этом и следующем (SCREEN 13) режиме оператор COLOR имеет несколько другой синтаксис:

   COLOR цвет_рисования - устанавливает цвет “по умолчанию” для графических операторов PSET, LINE, CIRCLE и др.

   SCREEN 13 - разрешение 320х200 точек, цветовая палитра может содержать до 256 цветов (в Quick Basic - 248). По количеству точек этот режим совпадает с режимом SCREEN 7, но каждая точка может быть окрашена в один из 248 цветов.

   Познакомимся поближе с последним режимом. Если в программе “Раскрашка” заменить SCREEN 7 на SCREEN 13, то при выполнении оператора

GET (0, 0)-(dx, dy), a%

появится сообщение “Illegal function call”, что означает, что курсор не помещается в массив a%. А почему? Дело в том, что для задания любого из 16 цветов необходимо 4 бита информации (16 = 24), а для задания 256 цветов - 8 бит (256 = 28), т.е. при работе в режиме SCREEN 13 массив a% должен быть вдвое больше, чем в SCREEN 7. После этого программа заработает, но в ней все останется по-прежнему! Чтобы изменить палитру цветов нужно взять цвета с номерами, отличными от 0 - 15. Сразу же за этими номерами идет палитра оттенков серого цвета - от цвета номер 16 (черного) до цвета номер 31 (белого). Изменим начальное значение с = 14 на с = 31 (Quick Basic различает цвета с номерами 31 и 15, хотя “по виду” они одинаковы!) и перепишем фрагмент программы для определения цвета закрашивания:


        ‘Определяем цвет краски на палитре
        ‘Прячем курсор,
         PUT (x0, y0), a%
        ‘определяем цвет,
         c = POINT(x0, y0)
        ‘закрашиваем индикатор
         PAINT (40, 180), c, 15
        ‘и восстанавливаем курсор на том же месте
         PUT (x0, y0), a%

   На самом деле, здесь мы допустили небольшую ошибку - не учли, что курсор может показать на белую линию, разделяющую цвета в палитре. И хотя при запуске программа будет работать безошибочно, то только потому, что начальное положение курсора и шаг перемещения не позволят курсору “встать” на разделительную линию. При дальнейшей модификации программы скрытая ошибка может обнаружить себя. Поэтому, исправим ее теперь:


        ‘Определяем цвет краски на палитре
        ‘Прячем курсор,
         PUT (x0, y0), a%
        ‘определяем цвет,
         c0 = POINT(x0, y0)
         IF c0 <> 15 THEN
            c = c0
           ‘закрашиваем индикатор
            PAINT (40, 180), c, 15
         END IF
        ‘и восстанавливаем курсор на том же месте
         PUT (x0, y0), a%

   Цвета, идущие за палитрой серого цвета, можно разбить на 9 палитр по 24 цвета. Сходство цветов в палитрах хорошо видно, если их вывести на экран параллельными полосками.

   Задание. Напишите программу для вывода на экран всех палитр в режиме SCREEN 13. Подберите свою палитру цветов для программы “Раскрашка” и вставьте ее в программу с помощью оператора DATA. Измените программу так, чтобы она при рисовании палитры “читала” цвет из списка данных.


[ Назад | Оглавление ]









helloworld.ru © 2001-2021
Все права защищены