скачать
МПС РОССИИ РОССИЙСКИЙ ГОСУДАРСТВЕННЫЙ ОТКРЫТЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ ПУТЕЙ СООБЩЕНИЯ
20/35/1
Одобрено кафедрой "Вычислительная техника"
| Утверждено деканом факультета «Автоматика, связь и вычислительная техника» |
Компьютерная геометрия и графика
Рабочая программа и задание на контрольную работу с методическими указаниями для студентов III курса специальности
071900. Информационные системы
 М о с к в а – 2 0 0 0
Рабочая программа разработана на основании примерной учебной программы данной дисциплины, составленной в соответствии с государственными требованиями к минимуму содержания и уровню подготовки инженера по специальности 071900.
С о с т а в и т е л ь – канд. техн. наук, доц. ^
Курс – 3 Всего часов – 20. Лекции - 12 ч. Лабораторные занятия - 8 ч. Самостоятельная работа - 67 ч. Контрольная работа -15 ч. Зачет - 6 семестр
Российский государственный открытый технический университет путей сообщения, 2000 ^ С О Д Е Р Ж А Н И Е 3 П р е д и с л о в и е 5 Рабочая программа 6 Цели и задачи дисциплины 6 Перечень тем лекционных занятий 8 ^ Перечень лабораторных занятий, их содержание и объем в часах 9 Название и краткое содержание работы 9 Кол-во часов 9 Задание на КОНТРОЛЬНую РАБОТу 10 Вариант 0 11 Вариант 1 11 Вариант 2 12 Вариант 3 12 Вариант 4 12 Вариант 5 12 Вариант 6 12 Вариант 7 13 Вариант 8 13 Вариант 9 13 ^ Фазы создания видеоигр 15 Специальные инструментальные средства конструирования игры 16 ^ Прототип процедуры 17 Установка видеорежимов 18 Перевод PC в режим 13h 18 Си-функция SETMODEC.C, тестирующая видеорежим (имеется на предоставляемой дискете) 19 Очистка экрана 19 Процедура FILLA.ASM, заполняющая экран (предоставляется на дискете) 20 ^ Использование встроенного ассемблера 21 Скан-коды 22 Статус клавиш 24 Устройство "мышь" 24 Двумерная графика 25 Использование матриц в играх 27 Основы контроля столкновений 27 Анимация 28 Тайминг 28 П р и л о ж е н и е 29 ЛР № 020307 от 28.11.91. 44 Тип. зак. Изд. зак. 177 Тираж 700 44 Подписано в печать 12.09.2000 Офсет. 44 Печ. л. 2,25 Уч.-изд. л. 2,5 Формат 60х90/16 44 Редакционно-издательский отдел, типография РГОТУПСа, 44 125808, Москва, ГСП-47, Часовая ул., 22/2 44
^
Компьютерная геометрия и графика - это два тесно связанных быстроразвивающихся направления современных информационных технологий. Спектр применения их чрезвычайно широк: мультфильмы, различные тренажеры и системы автоматизированного проектирования, издательские системы, рекламы и т. д. В настоящее время программисты самых высоких рангов создали множество графических систем, графических редакторов, пакетов прикладных программ, видеоигр. Эти готовые системы не требуют от пользователя знакомства с сутью, принципами и секретами той части, которая дает начало возникновению на экране мониторов картинок, пейзажей, чертежей. Чтобы понять это, нужно познакомиться с теоретическими основами компьютерной геометрии и графики. Знакомство с компьютерной графикой на лабораторных работах планируется начать с изучения современного пакета растровой графики Adobe Photoshop 4.0, далее продолжить знакомство с векторной графикой на примере работы с САПР AutoCad 14.0. В контрольной работе студентам предлагается, используя графический модуль Паскаля, написать программу, формирующую изображения различных столбиковых или круговых диаграмм. В настоящее время, особенно в среде молодежи, получил распространение мир информационных развлечений. Этот мир стремительно расширяется – в соответствии с прогрессом в вычислительной технике: появляются технические средства, приближающие нас к суперкачественному трехмерному синтезу. В контрольной работе студентам предлагаются основы программирования видеоигры. Таким образом, изучение курса "Компьютерная геометрия и графика" включает: прослушивание лекций; выполнение лабораторных работ; выполнение контрольной работы.
Изучать курс студент должен в соответствии с рабочей программой, конспектом лекций и рекомендуемой литературой.
^
Цели и задачи дисциплины
Цель изучения дисциплины "Компьютерная геометрия и графика" – получение знаний и практических навыков при освоении основных принципов, методов двух тесно связанных направлений современных информационных технологий - компьютерной геометрии и графики. Эта дисциплина опирается на предшествующие курсы: "Математика", "Информатика", "Периферийные устройства", "Основы технологии программирования" и является базой для многих дисциплин специальности и специализации. В результате изучения дисциплины студенты должны: 1.ЗНАТЬ теоретические основы компьютерной геометрии и графики. 2. УМЕТЬ работать с современными пакетами растровой и векторной графики, используя графический модуль языка программирования высокого уровня, уметь написать программу, формирующую изображения, программировать основы видеоигр. 3. ВЛАДЕТЬ сутью и секретами всех разделов геометрии и графики, чтобы грамотно применять их при дипломном проектировании и в инженерной деятельности. ^
Компьютерная геометрия и графика (КГГ) - направления информатики: проблемы, этапы развития, перспективы и возможности.
Т е м а 1. Математические и алгоритмические основы КГГ
Основы компьютерной графики: растровая и векторная графика. Геометрическое моделирование: объект моделирования, решаемые задачи, конструирование геометрических алгоритмов. Структура изображения и преобразование изображения. Методы компьютерной геометрии для построения кривых. Интерполяция и аппроксимация поверхностей (метод Кунса, поверхности тензорного произведения: Безье, В-сплайны и др.). Определение видимых и затененных точек. Цвет: системы цветов, индексированный цвет. Организация синтеза изображений. Л. [1,2,3,4].
^
2.1. Базовые программные средства компьютерной графики (графические объекты, примитивы и их атрибуты, графические возможности языков высокого уровня). 2.2. Дисплейный процессор. 2.3. Организация дисплейного файла и файла изображения. 2.4. Графические языки. 2.5. Современные стандарты КГГ. Форматы графических файлов. Графические компьютерные программы: программы САПР (AutoCad), программы векторной графики (Corel Draw), программы растровой графики (Photoshop), программы компьютерной мультипликации (3D STUDIO). Л. [5,6,9,10,11,12,13]. ^ Архитектура графических терминалов и графических рабочих станций (SAN). Реализация аппаратно-программных модулей графической системы. Л. [7,8].
^ Л. [14].
Перечень тем лекционных занятий № п/п | Наименование темы | Кол-во часов | 1 | Основы компьютерной графики: растровая графика | 2 | 2 | Основные понятия векторной графики | 1 | 3 | Методы компьютерной геометрии для построения поверхностей | 2 | 4 | Определение видимых и затененных точек | 2 | 5 | Цвет: системы цветов | 1 | 6 | Форматы графических файлов | 2 | 7 | Основные методы формирования графических объектов | 1 | 8 | Графические компьютерные программы | 1 |
^ Геометрическое моделирование. Структуры изображения и преобразование изображения. Методы для построения кривых. Организация синтеза изображений. Базовые программные средства компьютерной графики. Дисплейный процессор и организация дисплейного файла. Современные стандарты КГГ. Аппаратные средства КГГ. Применение интерактивной графики в информационных системах.
^ № п/п | Название и краткое содержание работы | Кол-во часов | 1 | PHOTOSHOP. Интерфейс пользователя. Сильные стороны пакета. Лаб. раб.№1 «Использование фильтров» | 2 | 2 | PHOTOSHOP. Лаб. раб. №2 “Работа с текстом. Создание рекламы” | 2 | 3 | Системы автоматизированного проектирования, на примере AutoCad. Лаб. раб. №3 «Главное меню. Работа в редакторе. Формирование чертежа. Создание графического изображения» | 4 |
^
Иванов В. П., Батраков А. С. Трехмерная компьютерная графика. - М.: Радио и связь, 1995. Корриган D. Компьютерная графика. - М.: Энтроп, 1995. Роджерс D. Алгоритмические основы машинной графики. - М.: Мир, 1989. А. Фокс, М. Пратт. Вычислительная геометрия. - М.: Мир, 1982. Коптева Л. Г. Компьютерная графика: Учебное пособие для студентов специальности 220100. – М.: РГОТУПС, 20/23/1, 1997. Ла Мот и др. Секреты программирования игр. - СПб.: ПИТЕР, 1995. Григорьев В.Л. Видеосистемы ПК фирмы IBM. - М.: Радио и связь, 1993. К. Айден и др. Аппаратные средства PC. - СПб.: BHV, 1996. Синграман Н. и др. Графический редактор Adobe Photoshop 3.0. для Windows. - М.: Мир, 1996. Кречко Ю. AutoCad: Программирование и адаптация. - М.: Диалог, 1995. Клементьев Н. Г. Пользователю Corel Draw 4.0. - СПб.: Макет, 1993. Комягин В. Б. Трехмерная компьютерная мультипликация 3D STUDIO от версии 2 к версии 4. Практическое пособие. - М.: ЭКОМ, 1995. Епанешников А., Епанешников В. Программирование в среде TurboPascal 7.0. 3-е Изд. - М.: Диалог - МИФИ, 1995. 14. Цветков В.Я. Геоинформационные системы и технологии. М.: Финансы и статистика, 1998.
^
Составить программы, выбрав вариант согласно последней цифре учебного шифра (его обозначение a0a1a2a3a4a5). Отчет по контрольной работе оформляется на листах писчей бумаги (формата А4) и должен содержать: титульный лист; постановку задач и исходные данные; в первой задаче – тексты программ, к командам программ дать комментарии; во второй задаче: твердые копии текстов программ игры Tombstone с изменениями студента; файл-заготовку charplat.pcx с внесенными изменениями на дискете. В конце отчета следует указать список использованной литературы. Листы контрольной работы должны быть скреплены. ЗАДАЧа 1
Используя графический модуль языка программирования высокого уровня Paskal [5, с. 6 - 16 или [13], написать программу, формирующую следующие изображения:
Вариант 0 Построить столбиковую диаграмму, для чего вводить с клавиатуры количество столбцов и процентные соотношения. Обеспечить закраску столбцов. Сделать надписи над столбцами (например, 10%, 31% и т. д.). Осуществить циклическое (2 раза) изменение цветов столбиков.
Вариант 1 Построить круговую диаграмму. В диалоге с клавиатуры вводить количество секторов (n<4), процентные соотношения. Сделать надписи процентов на диаграмме. Ввести коэффициенты масштабирования и увеличения изображения вдвое.
Вариант 2 Построить столбиковую диаграмму для следующих процентных соотношений 75, 8, 11, 6. Закрасить красным, зеленым, черным, желтым цветами. Сверху сделать надписи (75%, 8% и т. д.). Данные вводить в диалоге с клавиатуры. Осуществить в подпрограмме циклическое (3 раза) уменьшение области просмотра.
Вариант 3 Построить столбиковую диаграмму для следующих процентных соотношений: 39%, 15%, 20%, 26%. Надписи сделать внутри столбиков. Цвет пера - синий. Обеспечить диалоговый ввод с клавиатуры цветов столбиков. Поменять область просмотра.
Вариант 4 Нарисовать круговую диаграмму, отображающую следующие процентные соотношения: 64, 19, 17. Ввод процентных данных для секторов осуществлять с клавиатуры. Секторы закрасить желтым, красным, зеленым цветами соответственно. В подпрограмме сделать диалог для обеспечения изменения цвета двух секторов (64% и 17%). Внутри секторов сделать надписи процентов.
Вариант 5 Построить круговую диаграмму. В диалоге с клавиатуры вводить количество секторов (n<5) и процентные соотношения. Сделать надписи процентов на диаграмме. Поменять область просмотра.
Вариант 6 Нарисовать круговую диаграмму, отображающую следующие процентные соотношения: 52, 10, 20, 18. Ввод процентов осуществлять с клавиатуры. Закрасить второй (10%) и последний (18%) секторы. В подпрограмме сделать диалог для обеспечения изменения цвета одного сектора (20%). Сделать надписи процентов внутри секторов.
Вариант 7
Нарисовать круговую диаграмму, отображающую следующие процентные соотношения: 70, 7, 23. В диалоге с клавиатуры изменить процентные соотношения, чтобы можно было добавить: а) один сектор; б) два сектора. Закрасить в цикле (3 раза) сектора новыми цветами.
Вариант 8
Нарисовать столбиковую диаграмму для следующих процентных соотношений: 54, 31, 15. В диалоге с клавиатуры изменить процентные соотношения, чтобы можно было добавить: а) два столбика; б) три столбика. Закрасить столбики, сделать надписи над столбиками, ввести коэффициенты масштабирования и увеличения изображения в 2,5 раза. Вариант 9
Построить круговую диаграмму для шести секторов, имеющих следующие процентные соотношения: 39, 8, 4, 27, 10, 12. Обеспечить диалоговое изменение с клавиатуры цветов нечетных секторов (3 раза). Обеспечить в диалоге с клавиатуры задание и исчезновение надписей процентов внутри четных секторов. Поменять область просмотра.
ЗАДАЧа 2
В программе (см. прил.) при инициализации спрайта задать следующие параметры:
Вариант | SPRITE-WIDTH | SPRITE-HEIGHT | ac | as | mc | ms | 0 | 40 | 90 | 0 | 4 | 0 | 2 | 1 | 50 | 100 | 0 | 6 | 0 | 4 | 2 | 30 | 70 | 0 | 5 | 0 | 2,5 | 3 | 40 | 80 | 0 | 4 | 0 | 3 | 4 | 50 | 90 | 0 | 3 | 0 | 1,5 | 5 | 40 | 100 | 0 | 7 | 0 | 3 | 6 | 40 | 80 | 0 | 5 | 0 | 2 | 7 | 30 | 60 | 0 | 6 | 0 | 2,5 | 8 | 30 | 70 | 0 | 8 | 0 | 3 | 9 | 20 | 40 | 0 | 6 | 0 | 2 | Отобразить на экране вместо заданной в программе следующую строку символов, изменив ее цвет и местоположение: Вариант | X | Y | Цвет | Строка символов | 0 | 120 | 20 | 49 | Play TOMBSTONE | 1 | 121 | 21 | 50 | About cowboys | 2 | 122 | 22 | 13 | Modify TOMBSTONE | 3 | 123 | 23 | 8 | Play about cowboys | 4 | 124 | 24 | 49 | Study of plays | 5 | 125 | 25 | 5 | Example of plays | 6 | 126 | 26 | 6 | Example of play about cowboys | 7 | 127 | 25 | 50 | Example of modify TOMBSTONE | 8 | 128 | 24 | 9 | Study of TOMBSTONE | 9 | 129 | 23 | 4 | Play about cowboys |
При оживлении ковбоя в программе сделать следующие изменения:
Вариант | Cowboy.anim_speed | Cowboy.motion_speed | Время движен. | 0 | 3+rand ()%3 | 2+rand()%2 | 0 | 1 | 1+rand()%6 | 2+rand()%3 | 0,5 | 2 | 2+rand()%4 | 0,5+rand()%2 | 1 | 3 | 3+rand()%8 | 0,5+rand()%3 | 0 | 4 | 2+rand()%4 | 2+rand%2 | 0,5 | 5 | 1+rand()%5 | 1+rand()%2 | 1 | 6 | 1+rand()%6 | 1+rand()%1,5 | 1,5 | 7 | 2+rand()%8 | 1,5+rand()%2 | 0,5 | 8 | 4+rand()%4 | 1+rand()%2 | 0 | 9 | 2+rand()%3 | 1+rand()%3 | 1 |
В предоставляемом на дискете файле CHARPLATE.PCX дорисовать свои картинки и героев (заполнив белые квадраты – шаблоны для рисования).
^ Выбор режима видеоигры. Например, выбран режим высокого разрешения, но используются при этом только несколько цветов. Сложность графики: а) двумерная; б) трехмерная.
^ программа для рисования битовых образов; программа для анимации битовых образов; Си-код для бит-блиттинга, изменения видимого размера объектов - масштабирования и рисования линий; алгоритмы искусственного интеллекта для персонажей игры; средства для работы со звуком; Си-код для работы с устройствами ввода; инструменты для рисования уровней и сохранения их на диске; наборы MIDI - звуков для каждого из уровней.
При написании программы её разбивают на маленькие секции - куски: игровой мир и описывающие его структуры данных; система рендеринга; система ввода/вывода; система искусственного интеллекта; основной игровой цикл; интерфейс пользователя; система звука. Для написания программ ассемблер применяют тогда, когда нужна сверхскорость в графике, так как он намного быстрее программ на Си.
^ можно написать отдельную функцию и вызвать её из Си; можно использовать встроенный ассемблер. В функцию процессора входит перемещение данных в памяти и выполнение с ними некоторых преобразований. Процедуры ассемблера очень похожи на Си - функции. Рассмотрим Microsoft macro assembler (MASM) версий с 5.1 до 6.1, который имеет диррективы, упрощающие стыковку с программами на Си.
^ ; . . MODELMEDIUM; тип модели памяти . CODE; начало кода PUBLIC - function - name ; информация для компоновщика. Функция ; может экспортироваться f unction _ name PROC FAR ; название и тип функции (ближняя* или
функция начинается с этой диррективы ;дальняя**)
push BP ; готовим фрейм стека-пролог функции * * * mov BP, SP ; сохраним стек
; Работа функции pop BP ; восстанавливает фрейм стека-эпилог функции function _ name ENDP; конец процедуры конец процедуры END ; конец кода
* ближние используются для моделей памяти SMALL, COMPACT ** дальние применяются для моделей памяти MEDIUM, LARGE, HUGE *** процедура получает доступ к параметрам, передаваемым через стек.
Будем использовать модели памяти MEDIUM, которые имеют один 64-килобайтный сегмент для данных и несколько сегментов для кода, а также модель LARGE, имещую несколько сегментов как для кода, так и для данных.
^
Для установки видеорежима будем использовать базовую систему ввода/вывода (BIOS), чтобы избежать возможной несовместимости. Будем пользоваться графическим режимом с разрешением 320х200 точек при 256 цветах (обозначается 13h).
^
Ассемблерная функция, устанавливающая видеорежимы (SETMODEA.ASM, которая имеется на предоставляемой дискете).
. MODELMEDIUM .C; модель памяти - MEDIUM, соглашения языка Си . CODE; начало кодового сегмента PUBLIC Set_ Mode; объявляем функцию как общедоступную Set_Mode PROC FAR C Vmode : WORD ; функция получает один параметр
mov AH , 0 ; функция 0 прерывания 10h - установка режима mov AL, BYTE PTR Vmode; номер режима, который Вы хотите ;установить int 10h ; используем BIOS для установки режима ret ; возврат из процедуры Set_Mode ENDP; конец процедуры END ; конец кодового сегмента
^
# include # defineVGA256 0x13 # define TEXT_MODE 0x03 extern main (void) { //устанавливаем режим 320х200 точек, 256 цветов Set_Mode (VGA256); //ждем нажатия любой клавиши while (! Kbhit ( )) { } //возвращаем компьютер в текстовый режим Set_Mode (TEXT_MODE); } //конец функции main
Более медленно работает функция _setvideomode ( ) из графической библиотеки Microsoft C.
^
В видеоиграх экран перерисовывается от 15 до 30 раз в секунду, поэтому целесообразно быстро заполнять видеобуфер цветом фона. Процедура FILLA.ASM, заполняющая экран (предоставляется на дискете)
screen_ram EQU 0A000h ; видеопамять в этом режиме начинается по адресу A000 : 0000h . MODEL MEDIUM, C ; устанавливает модель памяти MEDIUM, ; соглашения по вызову языка Си . CODE ; начало кодового сегмента PUBLIC Fill_Screen ; объявляем процедуру общедоступной Fill_Screen PROC FAR C color: WORD; функция принимает один параметр mov AX, screen_ram ; ES : DI должно указывать на видео память xor di, di ; обнуляем DI mov CX , 320*200/2 ; количество слов, которое надо вывести mov AL , BYTE PTR color ; помещаем в регистр AL код цвета mov AH, AL; этот же код помещаем в регистр AH rep STOSW ; эта команда заполняет видеопамять ; выбранным цветом с максимально ;возможной скоростью RET ; выход из процедуры Fill_Screen ENDP ; конец процедуры END ; конец кодового сегмента
^
# include # define VGA256 0x13 # define TEXT_MODE 0x03 extern Set_Mode (int mode); extern Fill_Screen (int color); void main (void) { int t; //устанавливает режим 320х200 точек, 256 цветов (режим 13h) Set_Mode (VGA256); //заполняем экран цветом с кодом 1 (в палитре, устанавливаемой по //умолчанию, это соответствует синему цвету) for (t = 0; t < 1000; t++) Fill_Screen (1) ; //ждем нажатия любой клавиши while (! Kbhit ( ) ) { } //возвращаемся в текстовый режим работы экрана Set_Mode (TEXT_MODE); } //конец функции main
^
Это расширение стандарта Си, инструкции ассемблера можно включать в программы. Встроенный ассемблер объявляется следующим образом: _asm { инструкции ассемблера; }
Так как видеоигрой нужно удобно и несложно управлять, то большое значение имеют устройства ввода: джойстик; клавиатура (наиболее сложное устройство ввода, которое имеет свою собственную микросхему-контроллер ввода). Будем использовать функции Си и BIOS для работы с очередью клавиатуры (функции типа bios keyboard ( ). Обращения к BIOS вполне допустимы в функциях, некритичных по времени. BIOS поддерживает несколько функций, которые будем использовать (табл. 1). Таблица 1
Функция | 00h - чтение символа с клавиатуры | Вход: | AH : 00h | Выход: | AH - скан код | | AL - ASCH - символ | Функция | 01h - чтение статуса клавиатуры | Вход: | AH : 01h | Выход: | AH - скан код | | AL - ASCH - символ | | флаг z: если 0, то в буфере есть символ, если 1 - нет символа | Функция | 02h - Флаги, возвращаемые клавиатурой | Вход: | AH : 02h | Выход: | AL - байт статуса клавиатуры; | | бит 0 - нажат правый Shift; | | бит 1 - нажат левый Shift; | | бит 2 - нажата клавиша Ctrl; | | бит 3 - нажата клавиша Alt; | | бит 4 - Scroll Lock в положении ON; | | бит 5 - Num Lock в положении ON; | | бит 6 - Caps Lock в положении ON; | | бит 7 - Insert в положении ON |
Скан-коды
При нажатии клавиши обработчику посылается дважды скан-код: а) при нажатии; б) при отпускании клавиши. В видеоиграх нас интересуют не столько АSСII -коды, сколько нажатия следующих клавиш: А, S, Пробел, которые обычно отвечают за маневры, стрельбу и т.д. В табл. 2 перечислены скан-коды клавиш.
Таблица 2 Скан-коды Клавиша | Скан-код | Клавиша | Скан-код | Клавиша | Скан -код | ESC | 1 | A | 30 | F1 | 59 | 1 | 2 | S | 31 | F2 | 60 | 2 | 3 | D | 32 | F3 | 61 | 3 | 4 | F | 33 | F4 | 62 | 4 | 5 | G | 34 | F5 | 63 | 5 | 6 | H | 35 | F6 | 64 | 6 | 7 | J | 36 | F7 | 65 | 7 | 8 | K | 37 | F8 | 66 | 8 | 9 | L | 38 | F9 | 67 | 9 | 10 | ; | 39 | F10 | 68 | 0 | 11 | Апостроф | 40 | F11 | 133 | Минус (-) | 12 | ~ | 41 | F12 | 134 | Ровно (=) | 13 | Левый Shift | 42 | Num Lock | 69 | Back Space | 14 | \ | 43 | Scroll Lock | 70 | Tab | 15 | Z | 44 | Home | 71 | Q | 16 | X | 45 | Up | 72 | W | 17 | C | 46 | Pg Up | 73 | E | 18 | V | 47 | Серый- | 74 | R | 19 | B | 48 | Left | 75 | T | 20 | N | 49 | 5на цифр клавиатуре | 76 | Y | 21 | M | 50 | Right | 77 | U | 22 | Запятая | 51 | Серый+ | 78 | I | 23 | Точка | 52 | End | 79 | O | 24 | / | 53 | Down | 80 | P | 25 | Правый Shift | 54 | Pg Dn | 81 | [ | 26 | Print Screen | 55 | Ins | 82 | ] | 27 | Alt | 56 | Del | 83 | Enter | 28 | Пробел | 57 | | | Ctrl | 29 | Caps Lock | 58 | | | ^
Должна существовать возможность определить: была ли нажата клавиша; какая клавиша была нажата; статус клавиши Shift (это битовый вектор или последовательность). В [6, с. 66] приведен листинг программы получения статуса клавиш, в нем содержится информация о клавишах Shift, Alt, Ctrl и др. При вводе своего имени игрок может получить скан-коды и транслировать их в ASCII или сразу прочитать их. Демонстрационная программа работы с клавиатурой приведена в [6, с. 68].
^
Обычно подсоединяется к последовательному порту ПК, ее перемещение кодируется в последовательность импульсов, которая преобразуется в пакет, содержащий информацию о движении мыши и состоянии кнопок. Этот пакет посылается в серийный порт, к которому подсоединяется мышь, а затем интерпретируется программой. Будем использовать min функций для определения позиции мыши и статуса кнопок. Мышь отслеживает min расстояние, равное микки (mickey)≈ 1⁄200 дюйма. Таблица драйвера мыши приведена в [6, с. 73] . Автор[6] написал простую функцию для работы с мышью.
Squeeze_ Mouse ( ) #define MOUSE_ INT 0x33//номер прерывания #define MOUSE_ RESET 0x00//сброс мыши #define MOUSE_ SHOW 0x01//показать мышь #define MOUSE_ HIDE 0x02//погасить мышь #define MOUSE_ BUTT_ POS 0x03//возвратить координаты //и количество кнопок #define MOUSE_ SET_ SENSITIVITY 0x1A//установить //чувствительность в пределах 0-100 #define MOUSE_ MOTION_ REL 0x0B//установить //относительную чувствительность Для получения координат мыши нужно будет написать: Squeeze_ Mouse (MOUSE_ BUTT_ POS, & mouse_x, & mouse_ y, & mouse_buttons); 
локальные переменные для сохранения результатов
Драйвер мыши может возвращать абсолютные (на экране) и относительные (разница координат от предыдущей посылки) координаты. Листинг в [6, с. 75-79] позволяет рисовать на экране, нажимая на левую кнопку, и использовать правую для изменения цвета. В контрольной работе ограничимся двумерной графикой.
^
На Си программы рисующие:
Точки - POINTY.С (стр.83[6]) Линии - LINER.С (стр.85[6]) Многоугольники - POLYDRAW.C (стр.87[6]) (предоставляется на дискете)
Для хранения атрибутов объектов (кораблей, планет и т. д.) нужна структура данных, например, это многоугольник определенного цвета, расположенный в определенной позиции на экране (программа представлена в [6, с. 88]. ^ это перемещение, при котором не меняется угол поворота и размер объекта, например астероида (см. программу asteroid в [6, с. 91. Координаты вершин можно получить, загружая из файла, или сгенерировать. В AutoCade DXF-файл содержит списки вершин вместе с другими свойствами объекта, и после его загрузки координаты вершин считываются из него в соответствующие структуры. Если задать положение объекта на экране координатами xo,yo, то при перемещении:
xo = xo + dx;
yo = yo + dy.
^ представлена в [6, с. 92]. Если взять масштаб увеличения в 2 раза, то обращение к этой программе будет:
Scale_object((object_ ptr) &asteroid,2,0);
^ Нижеследующие формулы задают вращение произвольной точки (x,y) относительно оси z :
new x = x *cos(angle)-y* sin(angle)
new y = y *cos(angle)+x* sin(angle),
где angle - угол поворота точки (положительный - по часовой стрелке, отрицательный - против).
Си использует радианы, а не градусы. Для перевода написаны следующие макросы:
Deg _ To _ Rad (deg) {pi *deg/180};
Rad _ To _ Deg (rad) {180 *rad/pi}.
Пример программы вращения приведен в [6, с. 94], пример программы FIELD.С, содержащей поле астероидов, которые вращаются см. [6, с. 95-100]. Отсечение - рисование ограниченной части видеообраза, (например, имея ограниченную видимую часть, объект, дойдя до границы экрана, уходит). Отсечения могут производиться на двух "уровнях": уровне образа (т.е. проверка каждой точки в отсекаемой области); уровне объекта.
^
Умножение матриц эффективно, когда производятся множественные трансформации объекта с помощью единой, заранее подготовленной матрицы, включающей все операции над объектом.
^
В играх вычисление области пересечения изображения потребует слишком много времени, поэтому используют описывающие прямоугольники и контролируют столкновения между прямоугольниками (6, алгоритм 1.1, с.440, программа быстрого рисования точки выбранного цвета приведена в 6, на с.129). ^ - это когда количество пикселей одинакового цвета сохраняется вместе с позицией и цветом. Программа чтения файла формата РСХ приведена в [6, с. 142-144].
Анимация
В играх на ПК обновить экран можно двумя способами: - перерисовать весь экран целиком; - перерисовывать лишь участки экрана. Выбор способа зависит от типа игры (программы приведены в [6, с. 147]). Так как игры работают в графическом режиме, то текст нужно выводить по точкам, программа отображения любого символа представлена на стр. 154[ 6]. Тайминг
Для осуществления реалистичной анимации нужно уделять внимание таймингу - задержке между выводом кадров. Если образ имеет 10 анимационных кадров, они меняются слишком быстро, то персонаж будет не похож на оригинал, поэтому нужно иметь в программе счетчики. Используются 4 переменные для сохранения счетчиков движения и анимации: -anim _ clock; -anim _ speed; -motion _ clock; -motion _ speed. Таким образом, мы кратко познакомились со следующими вопросами: - применением встроенного ассемблера; VGA картой – узнали о режиме 13h, дающем лучшее разрешение и наиболее простом для программирования; как в режиме 13h программировать цвет, рисовать пиксели, загружать РСХ-файлы, перемещать битовые образы.
^
TOMB.C (игра Tombstone) (предоставляются на дискете) // ВКЛЮЧАЕМЫЕ ФАЙЛЫ /////////////////////////// # include # include # include # include # include # include # include # include # include # include // ОПРЕДЕЛЕНИЯ ////////////////////////// # define ROM_CHAR_SET_SEG 0xF000 // сегмент описания символов в //ПЗУ # define ROM_CHAR_SET_OFF 0xFA6E // смещение, соответствующее // описанию первого символа # define VGA 256 0x13 # define TEXT_MODE 0x03 # define PALETTE_MASK 0x3c6 # define PALETTE_REGISTER_RD 0x3c7 # define PALETTE_REGISTER_WR 0x3c8 # define PALETTE_DATA 0x3c9 # define SCREEN_WIDTH (unsigned int) 320 # define SCREEN_HEIGHT (unsigned int) 200 # define CHAR_WIDTH 8 # define CHAR_HEIGHT 8 # define SPRITE_WIDTH 24 # define SPRITE_ HEIGHT 24 # define MAX_SPRITE_FRAMES 16 # define SPRITE_DEAD 0 # define SPRITE_ALIVE 1 # define SPRITE_DYING 2 // СТРУКТУРЫ ДАННЫХ ///////////////////////// type struct RGB_color_typ { unsigned char red;// красная составляющая цвета (0-63) unsigned char green;// зеленая составляющая цвета (0-63) unsigned char blue;// синяя составляющая цвета (0-63) } RGB_color,* RGB_color_ptr; typedef struct pcx_header_typ { char manufacturer; char version; char encoding; char bits_per_pixel; int x,y; int width,height; int horz_res; int vert_res; Char ega_palette [48]; Char num_color_planes; int bytes_per_line; int palette_type; Char padding [58]; } pcx_header,*pcx_header_ptr; typedef struct pcx_picture_typ { pcx_header header; RGB_color palette [256]; Char far *buffer; }pcx_picture,*pcx_picture_ptr; typedef struct sprite_typ { int x,y; // текущая позиция спрайта int x_old, y_old; // предыдущая позиция спрайта int width, height; // размеры спрайта int anim_clock; // время анимации int anim_speed; // скорость анимации int motion_speed; // скорость движения int motion_clock; // время движения char far * frames [MAX_SPRITE_FRAMES]; // массив указателей на // образы int curr_frame; // отображаемый фрейм int num_frames; // общее число фреймов int state; // статус спрайта char far * background; // фон под спрайтом } sprite, *sprite_ptr; // ВНЕШНИЕ ФУНКЦИИ /////////////////////////////// extern Set_Mode (int mode); // ПРОТОТИПЫ ////////////////////////////// void Set_Palette_Register (int index, RGB-color_ptr color); void Plot_Pixel_Fast (int x, int y, unsigned char color); void PCX_Init (pcx_picture * image); void PCX_Delete (pcx_picture * image); void PCX_Load (char*filename, pcx_picture_ptr image, int enable_palette); void PCX_Show_Buffer (pcx_picture_ptr image); // ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ////////////////////////////////// unsigned char far *video_buffer = (char far *) 0xA0000000L; unsigned int far *video_buffer_w = (int far *) 0xA0000000L; unsigned char far *rom_char_set = (char far *) 0xF000FA6EL; // ФУНКЦИИ ///////////////////////////////// void Blit_Char (int [xc, int yc, char c, int color) { // эта функция отображает символ на экране, используя описание // символов размером 8х8 точек, хранящееся в ПЗУ int offset, x, y; unsigned char data; char far *work_char; unsigned char bit_mask = 0x80; // вычисляем смещение описания символа в ПЗУ work_char = rom_char_set + c * CHAR_HEIGHT; // вычисляем смещение символа в видеобуфере offset = (yc<<8)+(yc<<6)+xc; for (y=0; y { // сбросить битовую маску bit_mask = 0x80 for (x=0; x { // если бит равен 1, рисуем пиксель if ((*work_char & bit_mask)) video_buffer [offset + x] =color; // сдвигаем маску bit_mask = (bit_mask >>1); }// конец отрисовки строки // переходим к следующей строке offset + = SCREEN_WIDTH; work_char ++; }// конец рисования }// конец функции ////////////////////////////////////////// void Blit_String (int x, int y, int color, char *string) { // функция отображает на экране передаваемую строку символов // Расстояние между символами строки постоянно // Для отображения символов вызывается функция blit_char int index; for (index = 0; string [index] ! = 0; index ++) { Blit_Char (x+(index <<3), y, string [index], color); }// конец цикла for }// конец функции ///////////////////////////////////////// void Delay (int t) { float x=1; while (t-->0) x=cos (x); }// конец функции //////////////////////////////////////// void Set_Palette_Register (int index, RGB_color_ptr color) { // функция устанавливает элемент таблицы цветов, задаваемый //параметром index. Значения компонент цвета задаются полями // структуры color. // Указываем VGA-карте, что мы будем изменять регистр // палитры _outp (PALETTE_MASK, 0xff); // Теперь меняем значение компонентов. // Каждый раз используется один и тот же порт. -outp (PALETTE_DATA, color->red); -outp (PALETTE_DATA, color->green); -outp (PALETTE_DATA, color->blue); }// конец функции ////////////////////////////////////////// void PCX_Init (pcx_picture_ptr image) { // функция выделяет память для загрузки РСХ-файла if (!(image->buffer = (char far*) malloc (SCREEN_WIDTH *SCREEN_HEIGHT+1))) print f("\n could n`t allocate screen buffer"); }// конец функции ///////////////////////////////////////// void Plot_Pixel_Fast (int x, int y, unsigned char color) { // функция отображает на экране точку заданного цвета // вместо умножения используется сдвиг // пользуемся тем, что 320 * y = 256 * y + 64 * y = y<<8+y<<6 video_buffer [((y<<8)+(y<<6)+x] = color; }// конец функции /////////////////////////////////// void PCX_Delete (pcx_picture_ptr image) { // функция освобождает память, выделенную для загрузки РСХ-файла -ffree (image -> buffer); }//конец функции ///////////////////////////////// void PCX_Load (char *filename, pcx_picture_ptr image,int enable_palette) { //функция загружает РСХ-файл и заполняет поля структуры pcx-picture, //включая изображение (после декомпрессии), заголовок и палитру FILE *fp, *fopen (); int num_bytes, index; long count; unsigned char data; char far *temp_buffer; // открыть файл fp=f open (filename, "rb"); // загрузить заголовок temp_buffer = (char far*) image; for (index=0;index<128; index++) { temp_buffer [index] = getc(fp); }// конец цикла for // загрузить данные и декодировать их в буфере count=0; while (count<=SCREEN_WIDTH*SCREEN_HEIGHT) { // получить первую часть данных data=getc (fp); // это RLE? If (data >=192&&data <=255) { // сколько байт сжато? num_bytes=data-192; // получить значение цвета для сжатых данных data=getc(fp); // заполняем буфер полученным цветом while (num_bytes -- >0) { image -> buffer [count++]=data; }// конец цикла while }// конец обработки сжатых данных else { // поместить значение цвета в очередную позицию image -> buffer [count++]=data; }// конец обработки несжатых данных }// конец цикла while // перейти в позицию, не доходя 768 байт от конце файла f seek (fp, -768L, SEEK_END); // загрузить палитру for (index=0; index<256; index++) // красная составляющая image -> palette [index].red=(getc(fp)>>2); // зеленая составляющая image -> palette [index].green=(getc(fp)>>2); // синяя составляющая image -> palette [index].blue=(getc(fp)>>2); }// конец цикла for f close(fp); // если установлен флаг enable_palette, установить новую палитру if (enable_palette) { for (index=0; index<256; index++) { Set_Palette_Register (index, (RGB_color_ptr)&image->palette [index]); }// конец цикла for }// конец установки палитры }// конец функции ///////////////////////////////////////// void PCX_Show_Buffer (pcx_picture_ptr image) { // функция копирует буфер, содержащий изображение из РСХ-файла, в // видеопамять -f memcpy ((char far*) video_buffer, (char far*) image->buffer, SCREEN_WIDTH*SCREEN_HEIGHT); }// конец функции /////////////////////////////////////// void Sprite_Init (sprite-ptr sprite, int x, int y, int ac, int as, int mc, int ms) { // функция инициализирует спрайт int index; sprite -> x = x; sprite -> y = y; sprite -> x_old = x; sprite -> y_old = y; sprite -> width = SPRITE_WIDTH; sprite -> height = SPRITE_HEIGHT; sprite -> anim_clock = ac; sprite -> anim_speed = as; sprite -> motion_clock = mc; sprite -> motion_speed =ms; sprite -> curr_frame = 0; sprite -> state = SPRITE_DEAD; sprite -> num_frames = 0; sprite -> background = (char far*) malloc (SPRITE_WIDTH *SPRITE_HEIGHT+1); // устанавливаем все указатели в значение NULL for (index=0; index sprite -> frames [index] =NULL; }// конец функции /////////////////////////////////////////// void Sprite_Delete (sprite_ptr sprite) { // функция освобождает всю связанную со спрайтом память int index; ffree (sprite -> background); // освобождаем память, выделенную под кадры анимации for (index = 0; index ffree (sprite -> frames [index]); }// конец функции ///////////////////////////////////////// void PCX_Grap_Bitmap (pcx_picture_ptr image, sprite_ ptr sprite, int sprite_frame, int grab_x, int grab_y) { // функция выделяет один кадр из буфера РСХ-файла. Предполагается, // что изображение размером 320х200 пикселей в действительности //представляет собой массив 12х8 изображений, каждое размерностью // по 24х24 пикселя int x_off, y_off, x, y, index; char far *sprite_data; // вначале выделяем память для размещения спрайта sprite_data = sprite -> frames [sprite_frame]; // загружаем битовый образ в выделнную область памяти. Вначале // вычисляем, какое из изображений копировать. Помните: в действи- // тельности РСХ-файл представляет собой массив из отдельных эле- // ментов размером 24х24 пикселя. Индекс (0,0) соответствует левому // верхнему изображению, (11,7) - правому нижнему. x_off = 25 * grab_x+1; y_off = 25 * grab_y+1; //Вычисляем начальный адрес y_off = y_off * 320; for (y=0; y < SPRITE_HEIGHT; y++) { for (x=0; x < SPRITE_WIDTH; x++) { // берем очередной байт и помещаем его в текущую позицию буфера sprite_data [y * 24 + x] = image -> buffer [y_off + x_off + x]; }// конец копирования строки // переходим к следующей строке y_off + = 320; }// конец копирования // увеличиваем счетчик кадров sprite -> num_frames++; }// конец функции ////////////////////////////////////////////////// void Behind_Sprite (sprite_ptr sprite) { // функция сохраняет содержимое видеопамяти в той области, куда // будет выведен спрайт char far *work_back; int work_offset = 0, offset, y; // создаем альтернативный указатель для ускорения доступа work_back=sprite -> background; // вычисляем смещение в видеопамяти offset = (sprite -> y<<8) + (sprite ->y<<6) + sprite -> x; for ( y=0; y { // копируем очередную строку видеопамяти в буфер f memcpy ((char far*) & work_back [work_offset], (char far*) & video_buffer [offset], SPRITE_WIDTH); // переходим к следующей строке offset+ = SCREEN_WIDTH; work_offset + = SPRITE_WIDTH; }// конец цикла for }// конец функции //////////////////////////////////////////// void Erase_Sprite (sprite_ptr sprite) { // функция восстанавливает фон, сохраненный перед выводом спрайта char far *work_back; int work_offset = 0, ofset, y; // создаем альтернативный указатель для ускорения доступа work_back = sprite -> background; // вычисляем смещение в видеобуфере offset = (sprite -> y_old <<8) + (sprite -> y_old<<6) + sprite -> x_old; for (y=0; y< SPRITE_HEIGHT; y++) { // копируем в видеопамять очередную строку буфера -fmemcpy ((char far*) &video_buffer [offset], (char far*)&work_back [work_offset], SPRITE_WIDTH; // перейти к следующей строке offset + = SCREEN_WIDTH; work_offset + =SPRITE_WIDTH; }// конец цикла for }// конец функции ////////////////////////////////////////// void Draw_Sprite (sprite_ptr sprite) { // функция, рисующая спрайт на экране , вместо умножения использует // сдвиг char far *work_sprite; int work_offset =0, offset, x,y; unsigned char data; work_sprite =sprite -> frames [sprite ->curr_frame]; // вычислить смещение спрайта в видеобуфере offset = (sprite ->y<<8) + (sprite ->y<<6) +sprite ->x; for (y=0; y { for (x=0; x { // проверяем, не является ли пиксель "прозрачным" (с кодом 0), если // нет - рисуем if ((data = work_sprite [wjrk_offset +x])) video buffer [offset + x] = data; }// конец ввода строки // перейти к следующей строке в видеобуфере и буфере спрайта offset + = SCREEN_WIDTH; work_offset + = SPRITE_WIDTH; }// конец цикла по Y }// конец функции // ОСНОВНАЯ ПРОГРАММА////////////////////// void main (void) { long index, redraw; RGB_color color; int frame_dir =1; pcx_picture town, cowboys; sprite cowboy; // установить видеорежим 320х200х256 Set_Mode (VGA 256); // установить глобальные указатели на область памяти экрана Set_Screen_Pointers (); // загрузить фон PCX_Init ((pcx_picture_ptr) & town); PCX_Load ("town.pcx",(pcx_picture_ptr) & town,1); PCX_Show_Buffer ((pcx_picture_ptr) & town); PCX_Delete ((pcx_picture_ptr) & town); // вывести на экран заставку игры Blit_String (128, 24, 50, "TOMBSTONE"); // загрузить образы PCX_Init ((pcx_picture_ptr) & cowboys); PCX_Load ("cowboys.pcx", (pcx_picture_ptr) & cowboys, 0); // извлечь все образы из РСХ-файла Sprite_Init ((sprite_prt) & cowboy, SPRITE_WIDTH, 100,0,7,0,3); PCX_Grap_Bitmap ((pcx_picture_ptr)&cowboys, (sprite_ptr)& cowboy,0,0,0); PCX_Grap_Bitmap ((pcx_picture_ptr)&cowboys, (sprite_ptr)& cowboy,1,1,0); PCX_Grap_Bitmap ((pcx_picture_ptr)&cowboys, (sprite_ptr)& cowboy,2,2,0); PCX_Grap_Bitmap ((pcx_picture_ptr)&cowboys, (sprite_ptr)& cowboy); // главный цикл cowboy. state = SPRITE_ALIVE; while (! kbhit ()) { redraw =0; // используется как флаг необходимости перерисовки if (cowboy. state = = SPRITE_ALIVE) { // не пора ли поменять кадр? if (++cowboy. anim_clock > cowboy. anim_speed) { // сбрасываем счетчик времени cowboy. anim_clock =0; if (++cowboy. curr_frame > =cowboy. num_frames) { cowboy. curr_frame =0; }// конец обработки достижения последнего кадра redraw = 1; }// конец смены кадра // проверяем, не пора ли передвигать спрайт if (++cowboy. motion_clock > cowboy. motion_speed) { // переустановить счетчик движения cowboy. motion_clock =0; // сохранить старую позицию cowboy. x_old = cowboy. x; redraw = 1; // передвинуть спрайт if (++ cowboy. x >^ { Erase_Sprite ((sprite_ptr) & cowboy); cowboy. state = SPRITE_DEAD; redraw = 0; }// конец обработки достижения последнего кадра }// конец обработки движения спрайта }// конец обработки ситуации "ковбой жив" else { //пытаемся "оживить ковбоя" if (rand () % 100 = = 0) cowboy. state = SPRITE_ALIVE; cowboy. x = SPRITE_WIDTH; cowboy. curr_frame = 0; cowboy. anim_speed = 3+ rand () % 6; cowboy. motion_speed = 1 + rand () % 3; cowboy. anim_clock =0; cowboy. motion_clock = 0; behind_Sprite ((sprrite_ptr)) & cowboy); } }// конец процесса "оживления" // теперь состояние спрайта изменено if (redraw) { // удалить спрайт в старой позиции Erase_Sprite ((sptite_ptr) & cowboy); // сохранить фон в новой позиции Behind_Sprite ((sptite_ptr) & cowboy); // нарисовать спрайт в новой позиции Draw_Sprite ((sptite_ptr) & cowboy); // обновить старые координаты cowboy. x_old = cowboy. x; cowboy. y_old = cowboy. y; }// конец перерисовки Delay (1000); }// конец главного игрового цикла for (index =0; index<=300000; index++, Plot_Pixel_Fast (rand () % 320, rand () % 200,0)); // перейти обратно в текстовый режим Set_Mode (TEXT_MODE); }// конец функции main
Канд. тех. наук, доцент Л.Г. Коптева
Компьютерная геометрия и графика
Рабочая программа и задание на контрольную работу с методическими указаниями
Редактор Г.Ю. М и к р ю к о в а Комп. верстка Д.П. К у з м и н а
^ Печ. л. 2,25 Уч.-изд. л. 2,5 Формат 60х90/16 Редакционно-издательский отдел, типография РГОТУПСа, 125808, Москва, ГСП-47, Часовая ул., 22/2
Добавить документ в свой блог или на сайт
|