Вы находитесь на странице: 1из 87

Федеральное агентство связи

Федеральное государственное образовательное бюджетное учреждение


высшего профессионального образования
«Сибирский государственный университет телекоммуникаций и информатики»
(ФГОБУ ВПО «СибГУТИ»)

Форма утверждена научно-методическим


советом университета
Протокол №4 от 17.04.2013 г.

Кафедра ПМиК
Допустить к защите
зав. кафедрой: проф., д.т.н.
______________________Фионов А.Н.

ДИПЛОМНЫЙ ПРОЕКТ
Создание компьютерной игры для ПК
Пояснительная записка
ФИВТ.230105.001 ПЗ

Студент: Учайкин Евгений Александрович


Факультет ЗО Группа ЗП-01
Руководитель: Мерзлякова Екатерина Юрьевна

Консультанты:
- по экономическому обоснованию:
Казначеев Д.А.__________________________/_____________/

- по безопасности жизнедеятельности:
Симакова Н.Н. _________________________/_____________/

Рецензент: Фульман В.А. /_____________/

Новосибирск 2016 г.
Содержание

Введение...........................................................................................................4
1 Используемые языки програмирования и программное
обеспечение.....................................................................................................8
1.1 Язык C++ и библиотека Qt 5.5.1............................................................8
1.2 Среда разработки Qt Creator...................................................................11
1.3 Программное обеспечение.....................................................................12
2 Анализ предметной области...................................................................15
2.1 Основные понятия компьютерной игры...............................................15
2.2 История создания компьютерных игр...................................................17
2.3 Классификация компьютерных игр.......................................................22
3 Описание разработанного приложения..............................................25
4 Реализация программного продукта....................................................27
4.1 Создание игровой сцены.........................................................................27
4.2 Создание объектов QGraphicsItem.........................................................30
4.2.1 Создание главного героя...................................................................30
4.2.2 Создание врагов.................................................................................31
4.2.3 Создание монет..................................................................................32
4.3 Взаимодействие объектов.......................................................................32
4.3.1 Обнаружение коллизии героя............................................................32
4.3.2 Пуля.....................................................................................................33
4.3.3 Уничтожение врага............................................................................34
5 Расчётэкономическойчасти......................................................................35
6 Безопасность жизнедеятельности..........................................................40
6.1 Характеристика источника опасных и вредных факторов при работе с
ПЭВМ …………………………………..………………………………..40

2
6.2 Создание оптимальных условий труда на рабочем месте……………41
6.3 Профилактика зрительного утомления.................................................49
6.4 Электробезопасность..............................................................................49
6.5 Пожаробезопасность...............................................................................53
7 Заключение...................................................................................................57
Библиография.................................................................................................59
Приложение А. Листинг программы......................................................60
Приложение В. Упражнение для глаз110

3
Введение

На сегодняшний день рынок развлечений является одним из самых


популярных. С момента начала информационно-технической революции
мир стремительно движется в будущее, создавая все более совершенные
компьютерные системы, чтобы облегчить жизнь человека, а также занять
его досуг.
С появлением персональных компьютеров, с каждым годом, их роль в
жизни людей постоянно растет. Компьютер стал незаменимым помощником
не только в сфере экономических расчетов, но и является мощным центром
развлечений. Сферы влияния кино и литературы ощущают мощное
давление со стороны интерактивных развлечений, устройств дополненной
реальности и прочих, внедряемых, компьютерных технологий.
Современный человек иногда даже не задумывается, что и его
смартфон является аналогичным мобильным персональным компьютером.
С ростом роли компьютеров в жизни человека, компьютерная техника
существенно влияет и на модель поведения человека. По последним
исследованиям [1] средний возраст игрока компьютерных игр в России
составляет 33 года. Компьютерные развлечения делают жизнь человека
богаче, насыщеннее и, как следствие, - это мощная экономическая сфера,
приносящая огромные доходы. Поэтому не случайно, что особая роль в
жизни современного человека отводится компьютерным играм, первые из
которых существовали на самой заре развития компьютерной техники.
Можно сказать, что игры - это определенный вид искусства, схожий с
другими зрелищными жанрами. Игры могут нести не только
развлекательный характер. Их функционал достаточно широк: развитие,
образование, экономика, психология. Игра может заставить задуматься,
эмоционально переживать, поднимать серьезные глобальные или
психологические вопросы. С помощью игры можно найти и пути их

4
решения. Другими словами - игры - это современный вид искусства.
Компьютерные игры порой дарят эмоций не меньше, чем просмотр
кинофильма или театральной постановки.
Над современными играми работают огромные коллективы программистов
(до 650 человек), сценарии к играм пишут профессиональные писатели.
Компьютерные игры стали важной экономической составляющей. Прибыль
от игровых блокбастеров (Halo 4, Call of Duty и т.д.) превосходит сборы от
проката фильмов!
Десятка прибыльных компьютерных игр 2012 года принесла
создателям 7 миллиардов долларов.
Но в мире востребованы не только супер технологичные
компьютерные программы. Многие программисты-любители - инди-
разработчики создают небольшие игровые программы, которые не
обладают современной дорогостоящей высококлассной графикой и
звуковым сопровождением, как игры популярных компаний, но они часто
либо несут какие-то инновации в геймплее, либо обладают интересным
сюжетом, либо играют на ретро чувствах пользователя и т.д. В итоге они
так же пользуются большой популярностью и приносят создателям
достаточные для жизни доходы.
В мире существует чрезвычайно большое количество любителей
компьютерных игр с разным опытом в этой сфере. Есть начинающие
любители игр, есть ностальгирующие умудренные опытом игроки, поэтому
на этом рынке востребованы игровые проекты разной направленности.
Особенность настоящей работы заключается в том, что на основе Qt –
кроссплатформенного инструментария разработки ПО можно создавать
программы в наиболее короткие сроки. Это является актуальным в
постоянном режиме ускорения развития компьютерных технологий и
игровой индустрии.
В современном мире, очень важно поддерживать работу приложения
на разнообразных платформах. Типичным примером является программное
обеспечение, предназначенное для работы в операционных системах Linux

5
и Windows одновременно. Актуальность кроссплатформенности в игровой
индустрии успешно доказывает опыт американской компании Valve,
получившая тотальную известность, выпустив крайне успешную и хорошо
принятую критиками игру Half-Life. В настоящее время для разработчика
крайне важно поддерживать множество операционных систем для работы
приложения.
Qt – кроссплатформенный инструментарий разработки ПО на языке
программирования C++, именно он станет нашим главным «другом» на
момент написания дипломного проекта, так и в дальнейшей перспективе
разработки приложений.
Также созданная в ходе работы платформа, является основой
разработки более сложных версий данной игры.
Цель работы: создание игры в среде разработки Qt Creator
Объект исследования: казуальная компьютерная игра
Задачи исследования:
1. Изучить возможности библиотеки Qt.
2. Выявить особенности работы по созданию компьютерных игр
данной классификации и проанализировать опыт в области разработки
демонстрационных компьютерных игр.
3. Разработать программное приложение с помощью средств
библиотеки Qt.
Дипломная работа состоит из введения, трех разделов, заключения и
приложения. Во введении определена актуальность по данной проблеме,
цель и задачи дипломной работы.
В первом разделе описаны используемые средства программирования
Во втором разделе описан практический опыт работы по созданию
компьютерных игр, приведены примеры развития компьютерной
индустрии. Так же рассмотрена классификация компьютерных игр на
основе нескольких параметров.
Третий раздел включает в себя описание собственного опыта работы
по созданию компьютерной игры, произведен расчет экономических
показаний продукта, дано его краткое описание.
В заключении сделаны выводы по решению поставленных в работе
задач.

6
1. Используемые языки программирования и
программное обеспечение

1.1 Язык C++ и библиотека Qt 5.5.1

C++ поддерживает объектно-ориентированное программирование,


обобщённое программирование через шаблон, дополнительные типы
данных, встраиваемые функции, исключения и т.д... Возможности C++
включают объявления в виде выражений, преобразования типов в виде

7
функций, расширенное понятие константности, подставляемые функции,
аргументы по умолчанию, переопределения, пространства имён, классы.
Для проекта был выбран язык программирования С++/Qt. Qt
– (произносится [ˈkjuːt] (кьют) как «cute» или неофициально Q-T (кью-
ти)) — кроссплатформенный инструментарий разработки ПО на различных
языках программирования. Отличительная особенность Qt от других
библиотек — использование Meta Object Compiler (MOC) —
предварительной системы обработки исходного кода. MOC позволяет во
много раз увеличить мощь библиотек, вводя такие понятия,
как слоты и сигналы. Кроме того, это позволяет сделать код более
лаконичным. Утилита MOC ищет в заголовочных файлах на C++ описания
классов, содержащие макрос Q_OBJECT, и создаёт дополнительный
исходный файл на C++, содержащий мета объектный код[2].
Qt 5.5.1 предоставляет программисту не только удобный набор
библиотек классов, но и определённую модель разработки приложений,
определённый каркас их структуры. Следование принципам и правилам
«хорошего стиля программирования на C++/Qt» существенно снижает
частоту таких трудно отлавливаемых ошибок в приложениях, как утечки
памяти (memory leaks), необработанные исключения, незакрытые файлы
или неосвобождённые дескрипторы ресурсных объектов, чем нередко
страдают программы, написанные «на голом C++» без использования
библиотеки Qt.
Важным преимуществом Qt 5.5.1 является хорошо продуманный,
логичный и стройный набор классов, предоставляющий программисту
очень высокий уровень абстракции. Благодаря этому программистам,
использующим Qt, приходится писать значительно меньше кода, чем это
имеет место при использовании, например, библиотеки классов MFC. Сам
же код выглядит стройнее и проще, логичнее и понятнее, чем аналогичный
по функциональности код MFC или код, написанный с использованием
«родного» для X11 тулкита Xt. Его легче поддерживать и развивать. Qt
позволяет создавать собственные плагины и размещать их непосредственно

8
в панели визуального редактора. Также существует возможность
расширения привычной функциональности виджетов, связанной с
размещением их на экране, отображением, перерисовкой при изменении
размеров окна[3].
Qt 5.5.1 комплектуется визуальной средой разработки графического
интерфейса «Qt Designer», позволяющей создавать диалоги и формы в
режиме WYSIWYG. В поставке Qt есть «Qt Linguist» — графическая
утилита, позволяющая упростить локализацию и перевод программы на
многие языки; и «Qt Assistant» — справочная система Qt, упрощающая
работу с документацией по библиотеке, а также позволяющая создавать
кросс-платформенную справку для разрабатываемого на основе Qt ПО.
Программное обеспечение, построенное на этом инструментарии не
обязательно должно содержать графический интерфейс пользователя (GUI).
С помощью огромного количества всевозможных классов можно написать
приложение, работающее только через интерфейс командной строки
(CLI). Но в основном, конечно, Qt используется для построения
графических приложений, главная особенность которых -
кроссплатформенность.
Даже если программисту в данный конкретный момент не нужна
кроссплатформенность для его конкретного приложения (например,
планируется версия только для Windows или только для Macintosh), никто
не может знать, что понадобится завтра. Планы могут поменяться, и может
оказаться и нужным, и выгодным выпустить версию для другой
операционной системы или другой аппаратной платформы. В случае
использования Qt для этого понадобится всего лишь перекомпиляция
исходного кода. В случае же использования, например, MFC или «родных»
системных API понадобится много тяжёлой работы по портированию,
адаптации и отладке, а то и переписыванию с нуля существующего
исходного кода для другой ОС или аппаратной платформы. Qt является

9
полностью объектно-ориентированным, легко расширяемым и
поддерживающим технику компонентного программирования.
Основой построения графических интерфейсов на Qt, являются такие
компоненты, как виджеты. Каждый элемент в окне программы, будь то
кнопка или переключатель – это отдельный виджет. Виджеты генерируют
различные сигналы, которые могут вызывать слоты – специальные
функции, реагирующие на различные события в окне.
Многие компании-разработчики приложений Windows используют Qt
ещё по одной причине: даже если код пишется и в обозримом будущем
будет писаться только для платформы Windows и тестируется только на ней,
возможность откомпилировать один и тот же исходный код на одной и той
же платформе Windows двумя разными компиляторами (Microsoft Visual C+
+ и GCC/Win32) гарантирует лучшее качество исходного кода и лучшую его
совместимость со стандартом C++. Что немаловажно для кода, который
планируется длительно поддерживать и развивать.
У библиотеки Qt существуют «привязки» ко многим популярным
языкам программирования: Python, Java и другим. Эти «привязки»
позволяют многим программистам писать программы с графическим
интерфейсом, основанным на Qt на любимом языке, не вдаваясь во все
подробности C++.

1.2 Среда разработки Qt Creator

Для работы с библиотекой Qt можно использовать следующие среды


визуального программирования (Debian, Fedora, Gentoo, Mandriva, Ubuntu,
Qt Creator) [4]. Для создания казуальной игры была выбрана среда Qt
Creator.
Начиная с версии 4.5.0 в комплект Qt включена среда разработки «Qt
Creator», которая включает в себя редактор кода, справку, графические
средства «Qt Designer» и возможность отладки приложений. «Qt Creator»
может использовать GCC или Microsoft VC++ в качестве компилятора
и GDB в качестве отладчика. Для Windows версий библиотека

10
комплектуется компилятором, заголовочными и объектными файлами
MinGW.
Qt Creator - кроссплатформенная свободная IDE для разработки на С,
С++ и QML. Разработана Trolltech (Digia) для работы с фреймворком Qt.
Основная задача Qt Creator — упростить разработку приложения на разных
платформах. Поэтому среди возможностей, присущих любой среде
разработки, есть и специфичные, такие как отладка приложений на QML и
отображение в отладчике данных из контейнеров Qt, встроенный дизайнер
интерфейсов как на QML, так и на Qt Widgets. Qt Creator поддерживает
системы сборки qmake, cmake, autotools. Для проектов, созданных под
другими системами, может использоваться в качестве редактора исходных
кодов. Есть возможность редактирования этапов сборки проекта.
В Qt Сreator реализовано автодополнение, в том числе ключевых
слов, введённых в стандарте C++11, подсветка кода. Также есть
возможность задания стиля выравнивания, отступов и постановки скобок.
Реализован ряд возможностей при работе с сигнатурами методов, а
именно:
автогенерация пустого тела метода после его обновления;
возможность автоматически изменить сигнатуру метода в
определении, если она была изменена в объявлении и наоборот;
возможность автоматически поменять порядок следования
аргументов.
При навигации по коду доступно переключение между определением
и объявлением метода, переход к объявлению метода, переименование
метода как в отдельном проекте, так и во всех открытых. Также есть
возможность вызвать справку согласно текущему контексту. [5]

1.3 Программное обеспечение

В качестве редактора изображения при создании спрайта


использовался Adobe Photoshop. Это -
многофункциональный графический редактор, разработанный и
распространяемый фирмой Adobe Systems. В основном работает

11
с растровыми изображениями, однако имеет
некоторые векторные инструменты. Продукт является лидером рынка в
области коммерческих средств редактирования растровых изображений и
наиболее известным продуктом фирмы Adobe. Часто эту программу
называют просто Photoshop, на жаргоне российских пользователей —
«ФШ». В настоящее время Photoshop доступен на платформах OS
X, Windows, в мобильных системах iOS, Windows Phone и Android. [6]
Так же использовалась Faststone Image Viewer — программа Microsoft
Windows для просмотра изображений. Она включает в себя встроенный
эскизовый файловый менеджер и базу данных, поэтому она также может
быть использована в качестве менеджера изображений.
Основные возможности программы включают просмотр, управление,
сравнение изображений, удаление эффекта красных глаз, пересылку по
электронной почте, изменение размеров, обрезание, пакетная обработка,
пакетное переименование, улучшение цветов, colorspace management,
поворот изображений JPEG без ухудшения качества, база данных эскизов
(их кэш), и отсутствующая прежде у конкурентов, настраиваемая лупа.
Примечательна также функция слайд-шоу, включающая музыкальные
слайд-шоу и свыше 150 эффектов перехода. Начиная с версии 3.0
добавилась функция работы с картами памяти. Программа понимает
основные графические форматы: BMP, CUR, GIF, ICO, JPEG, JPEG
2000, PCX, PNG,PSD, TGA, TIFF, WMF, и некоторые Raw-форматы
популярных фотокамер: CRW, CR2, NEF, PEF, RAF, MRW, ORF, SRF и
DNG. [7]
Для обработки и прослушивания звука использовалась программа
JetAudio. Это интегрированный программный комплекс от
компании Cowon, который позволяет не только воспроизводить и
упорядочивать файлы мультимедиа на компьютере пользователя, но и
преобразовывать файлы из одного формата в другой, создавать диски,
прослушивать и создавать радиостанции, записывать звук с микрофона или
другого звукового устройства, а также многое другое. [8]

12
Для поиска информации в интернете использовался Google
Chrome — браузер, разрабатываемый компанией Google на основе
свободного браузера Chromium и движка Blink (до апреля 2013 года
использовался WebKit). Первая публичная бета-версия для Windows вышла
2 сентября 2008 года, а первая стабильная — 11 декабря 2008 года. По
данным StatCounter, Chrome используют около 300 миллионов интернет-
пользователей, что делает его самым популярным браузером в мире — его
рыночная доля в декабре 2015 года составила ▲54,04 %. По
данным LiveInternet, в декабре 2015 года с долей ▲41,8 % Chrome занимает
первое место и в Рунете. [9]

2. Анализ предметной области

2.1 Основные понятия компьютерной игры

13
Компьютерная игра – это программа, направленная на обеспечение
игрового процесса. Игра может служить для связи с игроками и выступать
сама в качестве партнёра. Для осуществления игрового процесса
используются различные устройства ввода, такие как: компьютерная мышь,
клавиатура, камера, джойстик и т.д.
Компьютерные игры созданы для развлечения, и широко
используются в коммерческих целях. Это могут быть различные
многопользовательские игры, промо-игры, программы, созданные с целью
привлечь потенциального покупателя.
В США игры признаны как предмет искусства, что позволяет им
конкурировать с кино.
Компьютерные игры могут быть использованы в качестве тренажёров
для различных видов профессий.
Вся игровая терминология в русском языке была заимствована из
английского. Очень сложно найти хорошую аналогию английским
терминам.
Но иногда возможно применять русскоязычные названия.
Texture – текстура. Это обычно двух мерное изображение, которое
можно использовать как для наложения её на трёхмерные модели, так и
отрисовки на экране как картинку.
2D-game – двумерная игра – игра, в которой используется только
двухмерное пространство.
3D-game – трёхмерная игра – использующая трехмерные модели и
трехмерный игровой мир.
Polygone (полигон, многоугольник) – пространственный
многоугольник, который используется для создания трехмерных объектов.
Как правило, в компьютерной графике используются треугольники.
Pixel (пиксель) – наименьший элемент растрового изображения,
точка, отображаемая на экране. Обычно в пикселях измеряют разрешение
текстур (например – 640х640), экранное разрешение монитора, размеры
игровых окон. Слово Pixel – это аббревиатура от Picture's Element.
Texture Filtering (фильтрация текстур) – уменьшение искажений при
наложении текстур на трехмерный объект.

14
Camera (камера) – Это проекция на игровой мир, которая имеет
ширину, высоту и угол поворота, так же она имеет координаты в
пространстве, будь то трёх мерное, будь то двух мерное. Камера играть
важную роль в представлении игры.
PvE/ПвЕ (от английского термина Player versus Environment) – это
один игрок против окружающей среды. Игры подобного жанра основаны на
отношении «Игрок-Мир». В игре данного характера игрок взаимодействует
с виртуальной окружающей средой, тем самым улучшая характеристики и
показатели своего персонажа двигаясь по сюжетной линии игры.
PvP/ПвП (от английского термина Player versus Player) – это игрок
против игрока. Игра данного жанра основана на отношении «Игрок-
Игрок». В играх подобного характера основную роль занимает фактор
коммуникации – противостояние и обмен игровыми предметами между
игроками.
PvE/PvP /ПвЕ/ПвП – разновидность компьютерной игры, которая
соединила в себе качества жанра ПвЕ и ПвП.
RvR /РвР (от английского термина Realm versus Realm) – это царство
против царства. В основу игр подобного жанра положено отношения
игроков (или группы игроков) против иной группы игроков, которые
сражаются за ресурсы, города и прочие ценности той или иной игры.
PvPvE/ПвПвЕ (от английского термина Playerversus Playerversus
Environment) – это игрок против игрока против окружающей среды. В
основу игр подобного характера заложено отношения между игроками
«Игрок-Игрок», которые сопровождаются вмешательством третьей
абстрактной стороны, что позволяет поддерживать баланс обеих игровых
сторон.
PvMP/ПвМП (от английского термина Player versus Monster Player) –
это игрок против игрока, который играет за монстра. [10]

2.2 История создания компьютерных игр

15
Компьютерные игры появились достаточно давно, и развиваются, по
сей день. История игр началась в 50-ые года прошлого столетия.
Великолепная тройка сделал первые шаги:
Ральф Баэр – инженер, в 1951 году предложил идею интерактивного
телевиденья;
Дуглас А.С. в 1952 году создал компьютерный аналог крестиков-
ноликов, который получил название «OXO»;
Уильям Хигинботем в 1958 году разработал компьютерную игру
«Теннис», в которую можно было играть втроём.
В 1962 году компания Digital Equipment Corporation разработала игру
культовую SpaceWar.
Как раз в 1970 году появляется мышь и патентуется человеком по
имени Дуглас Энгельбарт. На данный момент ни один компьютерные игрок
не может обойтись без этого манипулятора.
Позднее, в 1975 году Уильям Кроутер создал игру, которая является
отцом приключений с названием Colossal Cave Adventure в соответствии с
рисунком 2.2.1.К этой игре был проявлен большой интерес со стороны
общественности.

Рисунок 2.2.1 – Игра Colossal Cave Adventure

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

16
80-ые годы можно назвать эрой наступления компьютерных игр. Так
как персональные компьютеры сильно подешевели, их рынок стал серьезно
возрастать. Так же появились компании, специализирующиеся только на
компьютерных играх. Компанией Namco была выпущена многим известная
игра «Pac-Mac», в которой приходилось управлять круглым жёлтым
существом в соответствии с рисунком 2.2.2, перемещаясь по лабиринту,
попутно собирая овощи и фрукты, при этом избегая враждебных существ.

Рисунок 2.2.2 – Очень популярная игра Pac-man

В 1987 появились графически адаптеры VGA и SVGA, которые


позволили отображать до 256 цветов, чем 16 цветов прошедших лет.
В эти годы индустрия компьютерных игр стала расти всё сильнее и
сильнее. В 1993 году очень известная компания Id Software, выпустила
культовую игру Doom и именно она заложила основы жанра “Шутер”.
Начинания с 90-х бум компьютерных игр стал только набирать
обороты, а индустрия расти и расти. В 1993 году 10 декабря компанией Id
Software, был выпущен великий Doom. Игра, которая заложила основы
жанра шутер.
Самая первая игра с поддержкой сети появилась в 1994 под названием
Rise of the Triad. Первый 3D-квадзи шутер появляется на следующий год
под названием The Terminator: Future Shock. Но тогда ещё не было

17
поддержкой 3D, но частичный объем мира, врагов и свободный обзор
мышкой давал отличный эффект.

Рисунок 2.2.3 – Одна из первых 3D игр - Duke Nukem 3D

1996 год является эрой начала настоящих 3D игр. Появляетя первая в


мире карта с поддержкой 3D – Voodoo I. Такие технологии позволили
выпустить Duke Nukem 3D (рисунок 2.2.3) и Quake – первые в мире
полностью трехмерные игры. Так же в этом году появились такие игры, как
Super Mario, Command & Conquer: Red Alert (рисунок 2.2.4), Tomb Raider,
Resident Evil, Diablo и все-все-все.

18
Рисунок 2.2.4 – Стратегическая игра Command & Conquer: Red Alert.

В 1998 году появляются культовые игры StarCraft и Half-life. Их


продуманная механика позволила не терять к ним интерес на протяжение
нескольких лет и по сей день в эти игры играют.
В нашем веке игровая индустрия развивается в очень сильном темпе.
Ежегодно выпускаются тысячи игр, расходящиеся по всему миру
миллионами копий, а оборот составляет десятки миллиардов долларов.
Наиболее успешные игровые проекты собирают сотни миллионов долларов
от продаж. Например, такие как Crysis (рисунок 2.2.5)

Рисунок 2.2.5 – Современная игра Crysis

19
Развитие компьютеров тесно связанно с развитием игр. Именно для
них создаются мощные видео карты, процессоры, растет объем доступной
оперативной памяти.

2.3 Классификация компьютерных игр

Компьютерные игры можно классифицировать по различным


критериям:
Жанр: геймплей задает жанровую направленность, возможно
несколько разновидностей;
Режим игры: одиночный или многопользовательский;
Визуальное представление: игра может, как использовать
графические средства оформления, так и напротив, быть текстовой. Игра
также может быть двухмерной или трехмерной. Есть и звуковые игры — в
них вместо визуального представления используются звуки.
Платформозависимость: на каких платформах возможет запуск игры,
так же игры бывают платформонезависимыми (кроссплатформенными).

Классификация по жанрам:
Приключенческая игра или квест (Adventure) — игра с продуманным
и обычно линейным сюжетом. В этом направлении широко используют
различные головоломки.
Боевик (Action) — игра, требующая от игрока постоянных действий,
насыщенная боевыми сценами, драками и перестрелками.
Стратегическая игра (Strategy) — игра, представляющая собой
управление глобальными процессами, как например, развитие экономики,
создание армии, строительство парков и т. д. В данном жанре обычно
используется два режима игры: в реальное время или пошаговый режим.
Ролевые игры – это один из игровых жанров, который основан на
некоторых элементах игорного процесса ролевых настольных
традиционных игр. Отличительная черта данного жанра – это абсолютная
свобода определения пути прокачки игрового персонажа (либо же группки
персонажей), характера главного персонажа (персонажей) и сюжетного

20
поведения с предпочтениями самого же игрока, особенностями игровых
локаций, а также системы правил, которая действует в данной игре. Игра
этого жанра построена на том, что перед игроком постоянно постает вопрос
выбора (и в направлении развития героя, и в направлении сюжетной
линии), в результате которого игровой процесс может глобально измениться
вместе с финальным исходом игры в целом.
Гонки – это компьютерная игра, в основу которой заложено жанр
аркадных автогонок.
Браузерная игра – разновидность компьютерных игр, которая требует
постоянного соединения с сетью интернет и не требует установки
клиентской части игры. Самые распространенные игры данного жанра –
это флэш-игры. Их предшественниками были Java-игры. Игры подобного
жанра, как правило, являются однопользовательскими и достаточно просты
в освоении. Зачастую браузерные игры относят к разряду казуальных.
Клиентская игра – разновидность компьютерных игр, в которой для
доступа к игровому пространству игрок должен установить специальную
программу – так званую клиентскую часть игры.
Казуальные игры – разновидность компьютерных игр, которые
являются достаточно простыми по своей структуре. Зачастую игра
подобного жанра является весьма короткой и её можно пройти в рамках
одного интенет-сеанса. К казуальным играм можно отнести: пазлы,
головоломки, «стрелялки» и т.д. Как правило, игры подобного жанра
являются однопользовательскими.
Аркадные игры симуляторы – разновидность компьютерных игр,
которые относятся к упрощенной версии технических симуляторов,
зачастую с альтернативной физикой. Принципиальным отличием от аркад
является наличие физической модели. Зачастую – это симуляторы
автомобилей и космических кораблей.
Многопользовательские браузерные игры – разновидность
компьютерных игр, которые имитируют настольные игры, а именно:
карточные игры, нарды, шахматы и т.п. В игры подобного рода можно

21
играть как друг против друга, так и с несколькими оппонентами. Здесь
связь между игроками обеспечивает браузер.

3. Описание разработанного приложения

Это казуальная игра, предназначенная для широкого круга


пользователей. Термин «казуальная» происходит от лат. casualis, что
означает «случайный». Таким образом, казуальная игра - это игра, в
которую играют от случая к случаю, между делом, чаще всего - чтобы как-
то «убить» время. Ввиду своего предназначения такая игра, как правило,
обладает достаточно простыми правилами и не требует от пользователя
хорошего владения компьютером
В настоящее время определение таких игр по жанру чётких границ не
имеет и к казуальным относят игры, которые относительно невелики
размером и распространяются преимущественно посредством цифровой
дистрибуции.
Казуальные игры по своему уровню сложности годятся практически
для любой категории пользователей компьютера. Зачастую время на
прохождение таких игр невелико, либо совсем не имеет конца, а потому они
хорошо подходят для тех, кто не может уделять игре много времени.
Главным героем в игре является солдат, которому необходимо
сразиться с зомби в пустыне, и с пауками в пещере. В игре имеются два
уровня с разными врагами.
Цель игры набрать наибольшее количество очков собирая монеты.
Главный герой и враги нарисованы вручную, что делает данную игру
индивидуальной. Имеется аудио сопровождение.
В главном меню предстоит сделать выбор против кого будете
сражаться (рисунок 3).

22
Рисунок 3 - Главное меню игры

Битва проходит в интересной и по-настоящему увлекательной


системе «non-target», а значит будет требоваться постоянный контроль
игрока над схваткой.
Это очень динамичная игра, направленная на отдых и отвлечение от
работы.

4.Реализация программного продукта

4.1 Создание игровой сцены

Модель данных реализована с помощью объекта класса


QGraphicsScene библиотеки Qt 5.5.1. Элементами модели данных являются

23
графические примитивы (геометрические фигуры и растровые
изображения). Все графические примитивы реализованы с помощью
классов-потомков класса QGraphicsItem. Таким образом, объект класса
QGraphicsScene можно рассматривать как контейнер для набора объектов
классов-потомков QGraphicsItem. Для отображения модели, созданной в
QGraphicsScene, служит объект класса QGraphicsView. Работая в системе
GraphicsViewFramework, изображение не рисуется непосредственно в окне
QGraphicsView (хотя в принципе можно это делать). Вместо этого
осуществляется управляете объектами, хранящимися в модели
QGraphicsScene. Все изменения объектов модели автоматически
отображаются в окне QGraphicsView. При этом не нужно заботиться о
таких вещах как перерисовка изображения при изменении размеров окна.
Поскольку объект класса QGraphicsView связан с моделью, он знает, что
нужно отображать в окне, и обновляет содержимое окна автоматически.
Вторая важная задача, которую решает связка объектов QGraphicsView и
QGraphicsScene преобразование действий пользователя (таких, как щелчок
мышью, перемещение курсора мыши над объектом или нажатие клавиши) в
события модели. События модели могут быть переданы далее отдельным
примитивам, формирующим модель. Эта система передачи событий между
разными уровнями Graphics View Framework именуется в документации Qt
термином event propagation.
Упомянутые выше функции обнаружения столкновений и
геометрических преобразований реализованы в классах QGraphicsScene и
QGraphicsItem. Все эти операции выполняются независимо от уровня
отображения (на уровень отображения передается только конечный
результат операций). Так же, как и в системе Interview Framework, с одной
моделью Graphics View Framework может быть связано несколько объектов
отображения соответствии с рисунком 4.1.1.

24
Рисунок 4.1.1 – Схема Graphics View Framework

Далее выбираем файл формы главного окна приложения. В нём


создаём объект класса QGraphicsView в соответствии с рисунком 4.1.2.

25
Рисунок 4.1.2 – Создание QGraphicsView

В QGraphicsView задаём QGraphicsScene, на которой в дальнейшем


будут происходить все действия. Для этого необходимо в widget.h объявить
графическую сцену, а в widget.cpp произвести инициализацию графической
сцены и её размеров, также в графической сцене создаются границы поля,
где будет перемещаться герой и сделан фон сцены.

widget.cpp

scene = new CustomScene();
ui->graphicsView->setScene(scene);
ui->graphicsView->setRenderHint(QPainter::Antialiasing);
scene->setSceneRect(0,0,1270,945);

Подробнее смотреть приложение А.

4.2 Создание объектов QGraphicsItem

26
4.2.1 Создание главного героя

Для создания героя необходимо:


widget.h – объявить объект, добавить библиотеку героя.
widget.cpp – создать объект, задать месторасположения.
triangle.h – заголовочный файл отвечающий за графический объект
героя. Унаследовать класс от QObject для работы с сигналами и слотами, а
также от QGraphicsItem. Подключить заголовочный файл windows.h для
работы с функционалом.
triangle.cpp – нарисовать героя, создать слот для перерисовки
(обрабатываемый по таймеру) и произвести инициализацию первичного
повтора. Задать переменную (angle) для осуществления поворота,
установить функцию setRotation(), которая унаследуется от QGraphicsItem.
Для отслеживания состояния кнопок клавиатуры использовать функцию
из WinAPI, а именно GetAsyncKeyState(), которая по коду кнопки
определяет состояние нажатия.
widget.cpp

triangle = new Triangle();
scene->addItem(triangle);
triangle->setPos(200,200);

Подробнее смотреть приложение А.

4.2.2 Создание врагов

Для создания врагов необходимо:


widget.h – объявить таймер для создания врагов и слот для обработки
данного таймера, добавить библиотеку врага.
widget.cpp – создать таймер по которому будут появляться враги.
spider.h – заголовочный файл отвечающий за графический объект
врага. Унаследовать класс от QObject для работы с сигналами и слотами, а
также от QGraphicsItem. Задать цель за которой он будет следовать(герой)
spider.cpp – нарисовать героя, создать слот для перерисовки
(обрабатываемый по таймеру) и произвести инициализацию первичного
повтора. Задать переменную (angle) для осуществления поворота.

27
Отслеживать положение героя на игровом поле для разворота и
передвижения к персонажу.

spider.cpp

this->target = target;
void Spider::slotGameTimer()
{
QLineFlineToTarget(QPointF(0, 0),
mapFromItem(target, 0, 0));
qrealangleToTarget = ::acos(lineToTarget.dx() /
lineToTarget.length());
if (lineToTarget.dy() < 0)
angleToTarget = TwoPi - angleToTarget;
angleToTarget = normalizeAngle((Pi - angleToTarget) +
Pi / 2);

Подробнее смотреть приложение А.

4.2.3 Создание монет

Для создания монеты необходимо:


widget.h – объявить таймер для создания монет, добавить библиотеку
монеты.
widget.cpp – создать слот для появления монет на игровой сцене.
apple.h – заголовочный файл отвечающий за графический объект
врага. Унаследовать класс от QObject для работы с сигналами и слотами, а
также от QGraphicsItem. Создать слот nextFrame().
apple.cpp – создать sprite и реализовать nextFrame() для кручения
монет.
widget.cpp
void Widget::slotCreateApple()
{
Apple *apple = new Apple();
scene->addItem(apple);
apple->setPos((qrand()%(1200))*((qrand()%2==1)?1:-1),
(qrand()%(925))*((qrand()%2 == 1)?1:-1));
apple->setZValue(-1);
apples.append(apple);
}

Подробнее смотреть приложение А.

4.3 Взаимодействие объектов

28
4.3.1 Обнаружение коллизии героя

Для обнаружения колизии необходимо:


triangle.h – объявить слот игрового таймера.
triangle.cpp – переопределить функцию возвращения героя,
реализовать функцию collidingItems(). В данную фуекцию передаётся
объект для которого будет производится обнаружение коллизии.
triangle.cpp

void Triangle::slotGameTimer()
{
if(GetAsyncKeyState('A'))
{
this->setX(this->x() - 2);
if(!scene()->collidingItems(this).isEmpty())
{
this->setX(this->x() + 2);
}
}

Подробнее смотреть приложение А.

4.3.2 Пуля

Для реализации пули необходимо:


bullet.h – объявить функцию отвечающую за столкновение пули с
объектами.
bullet.cpp – создать слот где будет обрабатываться столкновение пули.
Вызываем sprite отвечающий за взрыв пули. Исходя из того с чем
столкнулась пуля, вызываются соответствующие функции.
bullet.cpp

QList<QGraphicsItem*>foundItems
= scene()->items(QPolygonF()
<<mapToScene(0,0)
<<mapToScene(-1,-1)
<<mapToScene(1,-1));
foreach (QGraphicsItem *item, foundItems)
{
if (item == this||item == hero||item->type() ==
(UserType + 1))
continue;
scene()->addItem(new Sprite(this->pos()));
callbackFunc(item);
this->deleteLater();

29
}

Подробнее смотреть приложение А.

4.3.3 Уничтожение врага

Для уничтожения врага необходимо:


widget.cpp – создать слот который будет отвечать за нанесение крона.
spider.h – объявить функцию для нанесения урона и переменные
отвечающие за состояние здоровья.
spider.cpp – установить количество здоровья, реализовать функцию
нанесения урона.
В заголовочном файле spider.h необходимо объявить функцию,
которая будет наносить урон мишени. А также объявим две переменных,
которые будут отвечать за здоровье мишеней. Первая переменная - это
будет текущее здоровье, а вторая переменная - это будет максимальное
здоровье.

spider.cpp

void Spider::hit(int damage)
{
health -= damage;
this->update(QRectF(-30,-30,60,60));
if(health<= 0) this->deleteLater();
}
Подробнее смотреть приложение А.

5.Расчёт экономической части

Целью работы является разработка программного обеспечения


предназначенного для рынка досуга и развлечений, а также создания
программной платформы для развития следующих проектов в этой сфере
имеющих перспективы получения прибыли.
Расчёт сметы затрат на разработку программного обеспечения

30
Для выполнения данной работы требуется 1 программист. При 4
часовом рабочем дне для создания данной программы потребуется около 2
месяцев.
В данном случае эту работу выполняет студент в счет своего
свободного личного времени и не получает за это зарплату, поэтому на
данном этапе разработки ПО затрат на программиста нет. Но в будущем,
когда будут создаваться новые программные продукты на основе созданной
в этой дипломной работе программной платформы, затраты будут
незначительны из-за наличия продуманной готовой программной
платформы. Так как у программиста не будет необходимости более
программировать подпрограммы взаимодействия с аппаратурой, он будет
сосредоточен только на реализации непосредственно программы используя
средства, предоставляемые платформой.
Так же для разработки необходима компьютерная техника: ноутбук.
Его преимущество по сравнению с персональным компьютером -
мобильность - можно показать часть выполненной работы, невысокая
стоимость, необходимость покупать дополнительно дорогостоящий
монитор.
Стоимость компьютера с характеристиками достаточными для
выполнения данной работ 15869 рублей. Это ноутбук Sumsung R540 со
следующими характеристиками:

Тип ноутбук
Операционная система Win 7 HomeBasic
Процессор Core i5 460M 2533 МГц
Ядро процессора Arrandale
Количество ядер процессора 2
Объем кэша L2 512 Кб
Объем кэша L3 3 Мб
Память 4 Гб DDR3
Количество слотов 2
Экран 15.6 дюймов, 1366x768, широкоформатный
Тип экрана глянцевый
Подсветка экрана светодиодная
Тип видеоадаптера встроенный

31
Видеопроцессор Intel GMA HD
Видеопамять SMA
Оптический приводDVD-RW внутренний
Объем накопителя (HDD) 320 Гб
Интерфейс накопителя Serial ATA
Скорость вращения жесткого диска 5400 об/мин
LAN/Modem сетевая карта 10/100 Мбит/c
Беспроводная связь Wi-Fi IEEE 802.11n, Bluetooth 3.0 HS
Интерфейсы USB 2.0x3, VGA (D-Sub),
HDMI, вход микрофонный, выход
аудио/наушники, LAN (RJ-45)
Устройство для чтения флэш-карт есть
Поддержка карт памяти SD, SDHC
Количество ячеек аккумулятора 6
Тип аккумулятора Li-Ion
Устройства позиционирования Touchpad
Встроенные колонки есть
Встроенный микрофон есть
Веб-камера есть
Особенности слот блокировки
Размеры (ДхШхТ) 379.8x255.5x36.2 мм
Вес 2.5 кг

Этот ноутбук относится к разряду начальных по мощности и это его


главное преимущество. Это ноутбук, обладающий среднестатистическими
параметрами. И это позволяет быть уверенным при разработке
программного обеспечения на этом ноутбуке, что итоговый продукт будет
хорошо идти на самом широком представленном парке машин, как на
самых современных, так и компьютерах 2-4 летней давности. Благодаря
бюджетному «железу» сразу видим все возможные будущие проблемы с
недостаточной производительностью и может изначально оптимизировать
программу обеспечив максимальное число положительных отзывов о
будущем программном продукте.
Ноутбук обладает достаточно комфортным по размеру диагонали
экраном - 15,6”, с достаточным разрешением 1366х768 точек на дюйм.
Для работы используются бесплатные программы:
Qt 5.5.1
Faststone Image Viewer
Photoshop CС пробная версия

32
JetAudio
Google Chrome

Программное обеспечение для создание программы данной


дипломной работы использовано бесплатно, поэтому затрат на его
приобретение нет.
Данная работа предлагает, не только игровой проект, но и платформу
для разработки игр имеющую широкие возможности и совместимость.
Реализующую многие современные эффекты, например масштабирование.
Использующую интересные методы для создания игровых, ситуаций.
Поэтому стоимость в 150 рублей за проект, как программную
платформу, с предоставлением исходных кодов, может оказаться
привлекательным большому количеству начинающих игровых
разработчиков. К тому же платформа сопровождается доступной
документацией и примерами применения различных методов (эта
дипломная работа). Платформа позволяет с минимальными изменениями
или совсем без них легко переносить программные продукты под другие
популярные операционные системы: Linux, MacOS, Pegasos и др.
Допустим, что в среднем наш неизвестный начинающий проект будут
приобретать около 7 человек в месяц.
Посчитаем, что за год пакет программа + платформа приобретут
7*12 = 84человек.
При стоимости 150 рублей посчитаем прибыль:
150 * 84 = 12600 рублей
Затраты на разработку программного обеспечения составили 15869
рублей.
Посчитаем рентабельность по формуле:
Pr / TC = ROE (прибыль / затраты = рентабельность)
12600/15869=0,8
Следует учитывать, что невысокая эффективность обусловлена лишь
большими начальными затратами на компьютерное оборудование, которое
в дальнейшем будет использоваться для множества других проектов.
Поэтому эффективность следующих программ и их экономическая

33
целесообразность будет определяться только их потребительскими
качествами.

6. Безопасность жизнедеятельности

6.1 Характеристика источника опасных и вредных факторов при


работе с ПЭВМ

Работающие на ПЭВМ могут подвергаться воздействию различных


опасных и вредных производственных факторов, основными из которых
являются:
1) физические: повышенные уровни: ультрафиолетового и
инфракрасного излучения; статического электричества; запыленности
воздуха рабочей зоны; повышенное содержание положительных аэроионов
в воздухе рабочей зоны; пониженное содержание отрицательных аэроионов

34
в воздухе рабочей зоны; повышенный или пониженный уровень
освещенности рабочей зоны, повышенная или пониженная яркость
светового изображения и др.;
2) химические: содержание в воздухе рабочей зоны оксида углерода,
озона, аммиака, фенола, формальдегида и полихлорированных фенилов;
3) психофизиологические: напряжение зрения, памяти, внимания;
длительное статическое напряжение; большой объем информации,
обрабатываемой в единицу времени; монотонность труда; нерациональная
организация рабочего места; эмоциональные перегрузки.
Работа с помощью ПЭВМ связана не только с восприятием
информации на экране монитора, но и с одновременным различением
текста печатных или рукописных материалов, зачастую с переадаптацией
зрения на различные расстояния, выполнением машинописных,
графических работ и других операций.
Особенности режима и характера работы, значительные умственные
напряжения и другие нагрузки при нерациональной конструкции и
расположении элементов рабочего места вызывают необходимость
поддержания вынужденной рабочей позы. Длительный дискомфорт при
работе вызывает развитие общего утомления и снижения
работоспособности.
Выполнение многих операций при работе на ПЭВМ требует
длительного статического напряжения мышц спины, шеи, рук, ног, что
приводит к быстрому развитию утомления. Указанные особенности работы
зачастую усугубляются неправильной планировкой рабочего.
Неблагоприятное влияние на условия труда работающих с ВДТ
оказывает нерациональное естественное и искусственное освещение
помещений и рабочих мест.
Длительная работа компьютера приводит к снижению концентрации
кислорода, повышению концентрации озона. Озон является сильным
окислителем, и концентрация его выше предельно допустимых величин
может привести к неблагоприятным обменным реакциям организма,
изменяя активность ряда ферментов, способствует нарушению зрения.

35
Важным фактором, оказывающим воздействие на состояние здоровья,
работающих на ПЭВМ, является аэроионный состав воздуха. Его
нарушение ухудшает состав крови, работу органа зрения, иммунной
системы. [17]

6.2 Создание оптимальных условий труда на рабочем месте

Помещение, где находятся компьютеры, должно быть достаточно


просторным и хорошо проветриваемым. Минимальная площадь на одно
рабочее место должна составлять 4,5м2 для ВДТ на базе плоских
дискретных экранов (жидкокристаллических (ЖК), плазменных,
минимальный объём – 20 м3.
Внедрение вычислительной техники на производстве даёт
положительный социально-экономический эффект, который выражается в
росте производительности, снижении доли рутинного, монотонного труда,
повышения скорости расчётов, скорости обмена информацией.
Отрицательное воздействие на человека вычислительной техники
менее выражено, сглажено многими положительными моментами. Однако у
людей, длительно использующих ПЭВМ могут быть отмечены такие
реакции как нарушение функций зрения, быстрое общее утомление. Для
того чтобы избежать вредного воздействия при работе с вычислительной
техникой необходимо соблюдать соответствующие меры безопасности,
правильно планировать рабочее место и режим работы.
Меры безопасности при работе ПЭВМ:
-освещенность рабочего места в лаборатории при использовании
люминесцентных ламп должна быть порядка 300 – 500 лк;
-правильное расположение дисплеев по отношению к окнам и
осветительным приборам;
-применение удобной мебели, рациональная рабочая поза;
-расстояние от работающего дисплея не менее 70 см от своего и не
менее 1,2 м от боковых и 2 м от одного видеомонитора и экрана другого
видеомонитора;

36
-периодическое расслабление работающего и движение в целях
стимуляции движения крови в организме.
По мнению многих специалистов, работа с дисплеем не связана с
вредным радиобиологическим воздействием. Допустимая мощность дозы
рентгеновского излучения перед экраном на расстоянии 5 см от его
поверхности равна 0.5 мр/ч. Интенсивность излучения экрана дисплея не
достигает предельно допустимой дозы радиации, следовательно, условия
труда можно отнести к безопасным. Однако, желательно принимать
следующие предосторожности: ограничить дневную продолжительность
рабочей деятельности перед экраном, не размещать дисплеи
концентрированно в рабочей зоне.
Располагать оборудованное дисплеем рабочее место необходимо
таким образом, чтобы в поле зрения оператора не попадали окна или
осветительные приборы; они не должны находиться и непосредственно за
спиной оператора. Следует добиваться уменьшения отражений на экране от
различных источников искусственного и дневного света. Когда
искусственный свет смешивается с естественным, рекомендуется
использовать лампы, по спектральному составу наиболее близкие к
солнечному свету. Соотношение яркости экрана и непосредственно
ближайшего окружения не должно превышать 3:1. Оптимальные нормы
микроклимата приведены в таблице 6.2.1.

Таблица 6.2.1 – Оптимальные нормы микроклимата для помещений с


ВДТ и ПЭВМ

Период года Категория Температура Относительная Скорость


воздуха С º,
работ влажность движения
не более
воздуха, % воздуха, м/с

Холодный Легкая – 1а 22-24 40-60 0,1

37
Легкая – 1б 21-23 40-60 0,1

Теплый Легкая – 1а 23-25 40-60 0,1

Легкая – 1б 22-24 40-60 0,2

Освещение

Работа с ПК зачастую происходит в помещениях с искусственным


освещением, которое должно обеспечивать правильную работу глаз и
приближать к оптимальным условиям зрительное восприятие, какое бывает
при естественном солнечном освещении.
Человек имеет как центральное (колбочковое), так и периферийное
(палочковое) зрение. Первое - для восприятия цветов и объектов малых
размеров, второе – для восприятия окружающего фона и крупных объектов.
Центральное зрение требует больших яркостей, а палочковое действует в
сумерках или полумраке. Учитывая, что при работе с дисплеями
задействовано именно центральное зрение, становится понятной
необходимость достаточного освещения помещения, где находится
компьютер. Самые общие правила организации освещения заключаются в
следующем:
1) Следует избегать большого контраста между яркостью экрана и
окружающего пространства. Оптимальным считается их выравнивание.
2) Запрещается работа с компьютером в темном или полутемном
помещении, Освещение в помещениях с ПК должно быть смешанным:
естественным – за счет солнечного света – и искусственным.
Хорошо, если окна, обеспечивающие естественное освещение, имеют
северную ориентацию. Если нет, необходимо принять меры, благодаря
которым интенсивный солнечный свет из южных или западных окон не

38
мешал бы работе. Так, например, оконные проемы можно оборудовать
жалюзи, занавесями, внешними козырьками.
В качестве источников общего искусственного освещения лучше
всего использовать осветительные приборы, которые создают равномерную
освещенность путем рассеянного или отраженного светораспределения и
исключают блики на экране монитора и клавиатуре. В соответствии с
санитарными нормами, это должны быть преимущественно
люминесцентные лампы типа ЛБ с рассеивателями или экранирующими
решетками. Следует отметить, что существуют специальные
люминесцентные лампы, например, фирмы «VitaLight R», которые
излучают свет различного «качества», имитируя, таким образом, полный
спектр естественного солнечного света. Эти лампы меньше раздражают,
чем любые другие лампы искусственного освещения.
Источники света необходимо равномерно распределять по комнате,
компонуя в сплошные или прерывистые линии. Линии должны
располагаться сбоку от рабочих мест параллельно линии зрения
пользователя – при рядном размещении компьютеров; локализовано над
рабочим столом – при размещении рабочих мест по периметру помещения.
Грамотная организация освещения способна повысить производительность
труда при зрительной работе средней трудности – на 5-6%, при очень
трудной – на 15%.

Расчет освещенности рабочего места

Правильный выбор и расчет освещенности рабочего места


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

39
Для рационального освещения необходимо выполнение следующих
условий:
–постоянная освещенность рабочих поверхностей;
–достаточная и равномерно распределенная яркость освещаемых
рабочих
поверхностей;
–отсутствие резких контрастов между яркостью рабочей
поверхностью и окружающего пространства;
–отсутствие в поле зрения светящихся поверхностей, обладающих
большим блеском, что достигается применением светильников с
рассеянным светом и увеличением высоты их подвеса.
Для рационального освещения производственных помещений и
рабочих мест большое значение имеет выбор цвета для окраски потолка,
стен и производственного оборудования.
Рассчитаем люминесцентное освещение кабинета, предназначенного
для выполнения работ с размером объекта различения от 0,3 мин до 1 мин.
Размеры помещений: А=4 м, В=3 м, Н=3 м. Площадь помещения
определяем по формуле:
S=A*B
Подставив значения получим:
S=4*3=12 м2
Освещение проектируется при помощи светильников ШОД
минимальной освещенностью Емин = 300 лк, средней удельной мощностью
17-23 Вт/м2. Высота подвеса над рабочей поверхностью Нр = 1,2 м.
Освещение выполняется лампами ЛБ-2*40, световой поток ламп Fл =2480
лм, длина 1.2 м, коэффициент запаса равен к=1.5.
Определим показатель помещения по формуле:
F=A*B/Hр(А+В)
Подставив значения получим:
F=4*3/1,2*(4+3) =1.42
Затем, для F=1,42, коэффициентов отражения потолка Рп=0,7, стен
Рс=0,5 и расчетной плоскости Рр=0,3 находим коэффициент использования
светового потока h=0,37. Потребное число светильников определяется по
формуле:
N=Eмин*S*K/Fл *h*Z*n
где n=2 общее число ламп в светильнике.

40
Подставив значения получим:
N=300*12*1,5/2480*0,37*0.9*2=3 штуки.
Общее количество ламп равно n=2*3=6.
Таким образом, выполнение перечисленных выше требований к
организации рабочего места обеспечит комфортные условия умственного
труда.

Планировка и оснащение рабочего места

Рабочее место это оснащенное техническими средствами (средствами


отображения информации, органами управления, вспомогательным
оборудованием) пространство, где осуществляется деятельность
пользователя (пользователей).
Рабочее место должно отвечать следующим требованиям:
- оборудование рабочего места (стол, стул, подставка для ног) должны
быть специальной конструкции, обеспечивающей возможность
индивидуальной регулировки;
- сиденье и спинка стула должны быть покрыты не
электризующимися полумягкими материалами;
- расположение рабочих поверхностей должно обеспечить
согласованность компоновки рабочего места и маршрута движений, а также
достаточную легкость для слежения за рабочими операциями,
- освещенность на поверхности стола в зоне размещения рабочего до-
кумента должна быть 300 - 500 лк (при комбинированном освещении).
Для операторов на рабочем месте было выделено 21
пространственных параметров, которые представлены в таблице 6.2.2 и на
рисунке 6.2.

Таблица 6.2.2 – Параметры рабочего места

Пространственные параметры L, мм

1 Высота сидения 400 - 550

41
2 Высота клавиатуры от пола 600-750

3 Угол наклона клавиатура 0-15°

4 Удаление клавиатуры от края стола 100-300

5 Удаленность экрана от края стола 500-700

6 Глубина пространства для ног в коленях <450

7 Глубина пространства на уровне ступней <650

8 Высота пространства для ног в коленях <600

9 Высота пространства на уровне ступней <100

10 Ширина пространства для ног на


<500
уровне

42
5

4
3
6
2
1 8
7
1
Рисунок 6.2 – Организация9рабочего места оператора ПЭВМ
0

6.3 Профилактика зрительного утомления

На утомляемость влияет четкость и резкость изображения. Эти


параметры зависят от разрешающей способности монитора. Чем выше
разрешающая способность, тем четче и точнее изображение на экране.
Так же на зрения влияет и яркость изображения на экране монитора.
Необходимо учитывать также, что внешнее освещение в рабочем
помещении в некотором смысле «конкурирует» со светом, излучаемый
монитором, снижая контраст изображения и ухудшая условия работы.
Хорошие показатели яркости могут помочь компенсировать этот фактор.
Проблемы снижения зрительного утомления решают с помощью
применения специальных защитных средств, правильной организации
рабочего места, режимов труда и отдыха, специальных упражнений для
снятия утомления. Комплекс упражнений для глаз смотреть в приложение
В.

6.4 Электробезопасность

Компьютер - обычный электроприёмник, работающий от однофазной


сети переменного тока 220В, 50Гц. При работе с любым
электроприемником может возникнуть опасность поражения

43
электрическим током. Поэтому при эксплуатации электроустановок
необходимо соблюдать определенные меры защиты. Прежде всего - это
требования к персоналу, занятому работой с ПК. Требуемый допуск по
электробезопасности зависит от того, какие операции с оборудованием
выполняет сотрудник (ремонт, обслуживание, настройка, управление,
пользование). С точки зрения обеспечения требований электробезопасности
при выполнении этих работ нет никакой разницы, работает специалист с
ПК или с любым иным производственным оборудованием с питанием от
сети 220В. Соответственно, никаких дополнительных «компьютерных»
требований к группе допуска не существует. Для пользователя ПК (того,
кто работает с ПК) достаточно 1 группы допуска в элекроустановках,
которая присваивается неэлектротехническому персоналу, выполняющему
работы, при которых может возникнуть опасность поражения
электрическим током. Если работник производит ремонт видеодисплейной
техники, обслуживание, настройку, то требования к допуску по
электробезопасности ужесточаются. Для персонала, работающего с ПК на
ЖК мониторах - II или III группа допуска в электроустановках до 1000В, а с
ПК на ЭЛТ - группа допуска в электроустановках выше 1000В. В ПК с
мониторами на электронно-лучевых трубках напряжение на самой трубке
достигает нескольких десятков киловольт. В связи с этим работа по ремонту
этих устройств должна классифицироваться как «работа с напряжением
выше 1000В».
Опасность поражения электрическим током существует уже при
нарушении правил подключения ПК к питающей сети. Есть определенные
правила подключения ПК к питающей сети с точки зрения безопасности
человека. Электрическое питание ПК осуществляется через блок питания.
Практически каждый блок питания или питающее устройство имеет
сетевой фильтр (рисунок 6.4.1). Конденсаторы этого фильтра
предназначены для шунтирования высокочастотных помех питающей сети
на землю через провод зануления и соответствующую трехполюсную вилку

44
и розетку. К розетке подключены три провода: один фазный, второй -
нулевой рабочий проводник и (N) третий - нулевой защитный проводник
(PE или НЗП) (рисунок 6.4.2). Нулевой защитный проводник соединен с
нулевым проводом сети. В системном блоке и мониторе объединены точки
с нулевым потенциалом (на платах). К этой точке присоединен нулевой
защитный провод, второй конец которого выведен на замыкающий контакт
вилки питающего шнура.
При занулении необходимо быть уверенным в том, что «нуль» не
станет фазой. Если же НЗП никуда не подключать, на корпусе системного
блока появится напряжение около110В (6.4.3). Это происходит потому, что
конденсаторы фильтра работают как емкостной делитель напряжения.

Рисунок 6.4.1 – Входные электрические цепи блока питания ПЭВМ

45
Рисунок 6.4.2 – Правильное подключение трехполюсной розетки к
двухпроводной однофазной сети с заземленным выводом источника тока:

Rо – заземление нейтральной точки источника тока;


TV – источник тока;
Ф – фазный провод;
Н – нулевой провод;
НЗП – нулевой защитный проводник

Рисунок 6.4.3 – Условия появления опасного напряжения на корпусе


системного блока

Для исключения опасности поражения электрическим током


электроустановки должны быть заземлены (занулены).
Схема подключения ПЭВМ к питающей сети согласно
классификации Международного электротехнического комитета приведена
на рисунке 6.4.4. Из рисунка видно, что нулевой защитный проводник (РЕ)
выполнен в виде отдельного проводника (N). НЗП связан с заземленной
нейтраль.

46
Рисунок 6.4.4 – Подключение системного блока ПЭВМ к
электропитающей сети

Rо- заземление нейтральной точки;


N-нулевой рабочий проводник;
РЕ- нулевой защитный проводник;
СФ- сетевой фильтр;
СБ- системный блок ПЭВМ
Выполнение требований безопасности при эксплуатации
персональных компьютеров является обязательным.

6.5 Пожаробезопасность

Пожарная безопасность обеспечивается системой предотвращения


пожара и системой пожарной защиты. Во всех служебных помещениях
обязательно должен быть «План эвакуации людей при пожаре»,
регламентирующий действия персонала и посетителей в случае
возникновения очага возгорании и указывающий места расположения
пожарной техники.
Для большинства помещений, где размещены ЭВМ, установлена
категория пожарной опасности В. Причинами возникновения пожара в
офисе могут стать:

47
1) неисправности электропроводки, розеток и
выключателей, которые могут привести к короткому
замыканию или пробою изоляции;
2) использование поврежденных (неисправных)
электроприборов;
3) использование в помещении электронагревательных
приборов с открытыми нагревательными элементами;
4) возникновение пожара вследствие попадания в
здание молнии;
5) возгорание здания вследствие внешних воздействий;
6) неаккуратное обращение с огнем и несоблюдение мер
пожарной безопасности.
Одно из условий обеспечения пожаробезопасности – ликвидация
возможных источников воспламенения. Для этого необходимо проводить
следующие мероприятия:
1) для исключения возникновения пожара по причине неисправного
электрооборудования, неисправности в электропроводке, розетках и
выключателях необходимо проводить плановый осмотр, вовремя выявлять
и своевременно устранять неисправности;
2) необходимые меры для исключения пожара из-за неисправных
электроприборов включают в себя своевременный и качественный ремонт
электроприборов, а также не использование неисправных приборов;
3) в целях профилактики пожара предлагается не проводить
обогревание помещения электронагревательными приборами с открытыми
нагревательными элементами, так как в помещении находятся бумажные
документы, справочная литература и т.п., а бумага –
легковоспламеняющийся предмет;
4) в целях уменьшения вероятности возникновения пожара
вследствие короткого замыкания необходимо, чтобы электропроводка была
скрытой;
5) в летний период времени во время грозы возможно попадание
молнии и возникновение пожара, во избежание этого необходимо
установить на крыше здания молниеотвод;

48
6) для устранения возможности возгорания из-за курения и
неосторожного обращения с огнем необходимо запретить курение в
офисном помещении и разрешить его только в строго отведенном для этого
месте.
Если вы находитесь в здание и обнаружили возгорание, то следует
действовать согласно предложенным инструкциям и выполнять
рекомендации МЧС.
Порядок действий:
1) позвоните по номеру 112 и сообщите о
пожаре, продиктуйте адрес
2) сообщите об угрозе находящимся в
здание людям. Сделайте всё необходимое для
срабатывания пожарной сигнализации
3) помогите находящимся в опасной зоне
людям покинуть её, не подвергая себя опасности
4) если под рукой есть необходимые
средства тушения пожара, то, не подвергая опасности
свою жизнь и здоровье, приступите к тушению огня
5) если распространения огня
предотвратить не удалось, покиньте здание
6) после того, как на место прибудут
спасатели, сообщите им всю необходимую
информацию о пожаре.

Рекомендации МЧС:
1) не поддавайтесь панике и своим поведением не
распространяйте панику среди других
2) передвигайтесь, по возможности не подвергая себя
опасности
3) при сильном задымлении защитите органы дыхания
влажной тканевой повязкой, нагнитесь или лягте на пол
4) закройте двери и окна, но не запирайте их на замок
5) перед тем как приступить к тушению
электропроводки, убедитесь в том, что она обесточена

49
6) отключите в здание или помещении вентиляцию.

В целях предотвращения пожара необходимо регулярно проводить с


сотрудниками противопожарный инструктаж, на котором знакомить
работников с правилами противопожарной безопасности, а также обучать
их использованию первичных средств пожаротушения.
К средствам тушения пожара, предназначенным для локализации
небольших загораний, относятся пожарные стволы, внутренние пожарные
водопроводы, огнетушители, и т.п. Необходимо оборудовать помещения
автоматическими датчиками - сигнализаторами о пожаре, например,
реагирующими на повышение температуры, а также при возможности
установками стационарного автоматического пожаротушения. [18]

Заключение

В ходе выполнения дипломной работы был изучен ряд источников по


практическому и профессиональному программированию. В результате
чего приобретены знания необходимые для создания собственного
продукта – демонстрационной казуальной игры. Так же в ходе решения
поставленных задач было осуществлено знакомство с принципами развития
индустрии компьютерных игр, проанализирован опыт работы в области
создания демонстрационных компьютерных игр.
Так же была изучена библиотека Qt 5.5.1. В результате чего стало
возможным создание небольшой казуальной игры. Этот процесс подробно
описан в работе.

50
Так же данная дипломная работа может рассматриваться как пособие
по практическому использованию возможностей библиотеки Qt. В ходе
работы была написана казуальная игра, в которую сможет играть любой
пользователь ПК разных возрастов. Так же были выявлены плюсы и
минусы работы на Qt 5.5.1.
К плюсам хотелось бы отнести удобное взаимодействие классов друг
с другом, с помощью слотов и сигналов создаваемые в библиотеках класса.
Кроссплатформенность Qt. Код данной программы был реализован на ОС
Windows и MAC. При компиляции проблем не возникало. Однако, отметим,
что версии Qt при этом должны быть одинаковы. Осваивая Qt большим
плюсом были встроенные в программу подробные и понятные для всех
видео уроки. Благодаря им удалось написать данную программу в более
короткое, чем предполагалось время.
К минусам можно отнести то, что готовое приложение будет занимать
много места. В зависимости от библиотек приложение может занимать от
15мб и больше. Особенно это плохо, если писать приложения для
мобильных платформ.
В результате работы удалось создать платформу для создания новых
приложений и версий игры. Таким образом при соблюдении общих правил
создания компьютерных игр и применении технологии создания
казуальных игр возможно создание продукта на основе которого можно
создавать дальнейшие версии игры без больших временных затрат.

51
Библиография

1. http://kanobu.ru/news/srednij-vozrast-rossijskih-gejmerov-
dostig-33-
let-371699/
2. https://ru.wikipedia.org/wiki/Qt
3. https://ru.wikibooks.org/wiki/Qt
4. https://www.ibm.com/developerworks/ru/library/l-qt_1/
5. https://ru.wikipedia.org/wiki/Qt_Creator#.D0.90.D1.80.D1.85.D0.B8.
D1.82.D0.B5.D0.BA.D1.82.D1.83.D1.80.D0.B0
6. https://ru.wikipedia.org/wiki/Adobe_Photoshop
7. https://ru.wikipedia.org/wiki/FastStone_Image_Viewer
8. https://ru.wikipedia.org/wiki/JetAudio
9. https://ru.wikipedia.org/wiki/Google_Chrome
10. http://cherrygame.ru/terminy-onlajn-igr-sleng
11. Бланшет, Саммерфилд. Qt 4 Программирование GUI на С+
+. 2ed.
– 2008
12. Шлее Макс. Профессиональное программирование на C++.
+CD. Qt 4.8. (В подлиннике) – 2012
13. Марк Саммерфилд. Qt Профессиональное
программирование
(Hightech) – 2011
14. Андрей Боровский. Qt 4.7+. Практическое
программирование на
C++ - 2012 Андрей Боровский - Qt4.7+. Практическое
программирование на C++ - 2012

52
15. Саммерфилд М. Qt Профессиональное программирование.
Символ-Плюс, 2011. 552 с.
16. Юрий Земсков - Qt4 на примерах
17. http://an-site.ru/dk/adpz16.htm
18. http://ria.ru/infografika/20130125/919320340.html

Приложение А. Листинг программы


Apple.h
#ifndefAPPLE_H
#define APPLE_H
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
class Apple : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Apple(QObject *parent = 0);
~Apple();
signals:
public slots:
private slots:
void nextFrame();
private:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOp
tionGraphicsItem *option, QWidget *widget);
private:
int color;
QTimer *timer;
QPixmap *spriteImage;
int currentFrame;
};
#endif
Apple.cpp
#include "apple.h"
Apple::Apple(QObject *parent)
: QObject(parent), QGraphicsItem()
{
currentFrame = 0;
spriteImage = new QPixmap("C:\\YPPPA\\moneta40.png");
timer = new QTimer();
connect(timer, &QTimer::timeout, this,
&Apple::nextFrame);
timer->start(50);
}

53
Apple::~Apple()
{
}
QRectF Apple::boundingRect() const
{
return QRectF(-20,-20,40,40);
}

void Apple::paint(QPainter *painter, const


QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawPixmap(-20,-20, *spriteImage,
currentFrame, 0, 40,40);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Apple::nextFrame()
{
currentFrame += 40;
if (currentFrame >= 280 ) currentFrame = 0;
this->update(-20,-20,40,40);
}
Bullet.h
#ifndef BULLET_H
#define BULLET_H
#include <QObject>
#include <QGraphicsItem>
#include <QTimer>
#include <QPainter>
#include <QGraphicsScene>
#include <QDebug>
#include <sprite.h>
class Bullet : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Bullet(QPointF start, QPointF end,
QGraphicsItem *hero, QObject *parent = 0);
~Bullet();
void setCallbackFunc(void (*func) (QGraphicsItem *
item));
signals:
public slots:
private:
QRectF boundingRect() const;
void paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget);
void (*callbackFunc)(QGraphicsItem * item);
private:
QTimer *timerBullet;
QGraphicsItem *hero;
private slots:

54
void slotTimerBullet();
};
#endif
Bullet.cpp
#include "bullet.h"
#include <math.h>
static const double Pi =
3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;
static qreal normalizeAngle(qreal angle)
{
while (angle < 0)
angle += TwoPi;
while (angle > TwoPi)
angle -= TwoPi;
return angle;
}
Bullet::Bullet(QPointF start, QPointF end, QGraphicsItem *
hero, QObject *parent): QObject(parent), QGraphicsItem()
{
this->hero=hero;
this->setRotation(0);
this->setPos(start);
QLineF lineToTarget(start, end);
qreal angleToTarget = ::acos(lineToTarget.dx() /
lineToTarget.length());
if (lineToTarget.dy() < 0)
angleToTarget = TwoPi - angleToTarget;
angleToTarget = normalizeAngle((Pi - angleToTarget) +
Pi / 2);
if (angleToTarget >= 0 && angleToTarget < Pi)
{
setRotation(rotation() - angleToTarget * 180 /Pi);
}
else if (angleToTarget <= TwoPi && angleToTarget > Pi)
{
setRotation(rotation() + (angleToTarget - TwoPi )*
(-180) /Pi);
}
timerBullet = new QTimer();
connect(timerBullet, &QTimer::timeout, this,
&Bullet::slotTimerBullet);
timerBullet->start(7);
}
Bullet::~Bullet()
{
}
QRectF Bullet::boundingRect() const
{
return QRectF(0,0,2,4);
}
void Bullet::paint(QPainter *painter, const

55
QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(Qt::black);
painter->setBrush(Qt::black);
painter->drawRect(0,0,2,4);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Bullet::slotTimerBullet()
{
setPos(mapToParent(0, -10));
QList<QGraphicsItem *> foundItems =
scene()->items(QPolygonF()
<< mapToScene(0, 0)
<< mapToScene(-1, -1)
<< mapToScene(1, -1));
foreach (QGraphicsItem *item, foundItems)
{
if (item == this || item == hero || item->type()
== (UserType + 1))
continue;
scene()->addItem(new Sprite(this->pos()));
callbackFunc(item);
this->deleteLater();
}
if(this->x() < 0)
{
this->deleteLater();
}
if(this->x() > 1200)
{
this->deleteLater();
}
if(this->y() < 0)
{
this->deleteLater();
}
if(this->y() > 925)
{
this->deleteLater();
}
}

void Bullet::setCallbackFunc(void (*func)


(QGraphicsItem *))
{
callbackFunc = func;
}
Customscene.h
#ifndef CUSTOMSCENE_H
#define CUSTOMSCENE_H
#include <QObject>

56
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
class CustomScene : public QGraphicsScene
{
Q_OBJECT
public:
explicit CustomScene(QObject *parent = 0);
~CustomScene();
signals:
void signalTargetCoordinate(QPointF point);
void signalShot(bool shot);
public slots:
private:
voidmouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent
*event);
};
#endif
Customscene.cpp
#include "customscene.h"
CustomScene::CustomScene(QObject *parent) :
QGraphicsScene()
{
Q_UNUSED(parent);
}
CustomScene::~CustomScene()
{
}
void CustomScene::mouseMoveEvent(QGraphicsSceneMouseEvent
*event)
{
emit signalTargetCoordinate(event->scenePos());
}

void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent
*event)
{
emit signalShot(true);
Q_UNUSED(event);
}
void CustomScene::
mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
emit signalShot(false);
Q_UNUSED(event);
}
Spider.h
#ifndef SPIDER_H
#define SPIDER_H
#include <QObject>

57
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QDir>
#include <QUrl>
class Spider : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Spider(QGraphicsItem * target, QObject
*parent = 0);
~Spider();
void pause();

void hit(int damage);


void setCallbackFunc(void (*func)
(QGraphicsItem * item));
signals:
void signalCheckGameOver();
void signalCheckItem(QGraphicsItem *item);
public slots:
protected:
QRectF boundingRect() const;
void paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget);
private:
qreal angle;
int steps;
int countForSteps;
QTimer *timer;
QGraphicsItem * target;
int health;
int maxHealth;
QMediaPlayer * player;
QMediaPlaylist * playlist;
QPainterPath shape()const;
void (*callbackFunc)(QGraphicsItem * item);
private slots:
void slotGameTimer();
};
#endif
Spider.cpp
#include "spider.h"
#include "math.h"
static const double Pi =
3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;

58
static qreal normalizeAngle(qreal angle)
{
while (angle < 0)
angle += TwoPi;
while (angle > TwoPi)
angle -= TwoPi;
return angle;
}
static int randomBetween(int low, int high)
{
return (qrand() % ((high + 1) - low) + low);
}
Spider::Spider(QGraphicsItem *target, QObject *parent) :
QObject(parent), QGraphicsItem()
{
angle = 0;
steps = 0;
countForSteps = 0;
setRotation(angle);
this->target = target;
timer = new QTimer();
connect(timer, &QTimer::timeout, this,
&Spider::slotGameTimer);
timer->start(15);
health = randomBetween(1,15);
maxHealth = health;
player = new QMediaPlayer(this);
playlist = new QMediaPlaylist(player);
player->setPlaylist(playlist);
playlist->addMedia(QUrl("qrc:/Zombi.wav"));
playlist
->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
player->setVolume(70);
}
Spider::~Spider()
{
}
QRectF Spider::boundingRect() const
{
return QRectF(-50,-50,95,135);
}
QPainterPath Spider::shape() const
{
QPainterPath path;
path.addEllipse(boundingRect());
return path;
}
void Spider::paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(QPen(Qt::black, 1));
if(steps == 0)
{

59
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-45,30, 20, 30);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-5,30, 20, 30);
QPolygon polygon;
polygon << QPoint(-42,56) << QPoint(-28,56)
<< QPoint(-20,30) << QPoint(-10,30)
<< QPoint(-2,56) << QPoint(12,56)
<< QPoint(4,30) << QPoint(-37,30);
painter->setBrush(Qt::black);
painter->drawPolygon(polygon);
}
else if (steps == 1)
{
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-45,55, 20, 30);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-5,-5, 20, 30);
QPolygon polygon;
polygon << QPoint(-42,81) << QPoint(-28,81)
<< QPoint(-20,30) << QPoint(-10,30)
<< QPoint(-2,21) << QPoint(12,21)
<< QPoint(4,30) << QPoint(-37,30);
painter->setBrush(Qt::black);
painter->drawPolygon(polygon);
}
else if (steps == 2)
{
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-45,-5, 20, 30);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-5,55, 20, 30);
QPolygon polygon;
polygon << QPoint(-42,21) << QPoint(-28,21)
<< QPoint(-20,30) << QPoint(-10,30)
<< QPoint(-2,81) << QPoint(12,81)
<< QPoint(4,30) << QPoint(-37,30);
painter->setBrush(Qt::black);
painter->drawPolygon(polygon);
}
QPolygon polygon;
polygon << QPoint(1,40) << QPoint(1,15)
<< QPoint(-7,-27) <<QPoint(1,-27)
<< QPoint(9,15) << QPoint(9,40);
painter->setBrush(Qt::black);
painter->drawPolygon(polygon);
painter->drawLine(-7,-27,-7,-37);
painter->drawLine(-5,-27,-5,-37);
painter->drawLine(-3,-27,-3,-37);
painter->drawLine(-1,-27,-1,-37);
painter->drawLine(1,-27,1,-37);
polygon << QPoint(-43,40) << QPoint(-43,15)
<< QPoint(-35,-27) << QPoint(-27,-27)

60
<< QPoint(-35,15) << QPoint(-35,40);
painter->setBrush(Qt::black);
painter->drawPolygon(polygon);
painter->drawLine(-35,-27,-35,-37);
painter->drawLine(-33,-27,-33,-37);
painter->drawLine(-31,-27,-31,-37);
painter->drawLine(-29,-27,-29,-37);
painter->drawLine(-27,-27,-27,-37);
painter->setPen(QPen(Qt::black,1));
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-45, 25, 55, 25);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-29.5, 10, 20, 30);
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::red);
painter->drawRect(-40, 30, (int)
40*health/maxHealth,3);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Spider::slotGameTimer()
{
QLineF lineToTarget(QPointF(0, 0),
mapFromItem(target, 0, 0));
qreal angleToTarget = ::acos(lineToTarget.dx() /
lineToTarget.length());
if (lineToTarget.dy() < 0)
angleToTarget = TwoPi - angleToTarget;
angleToTarget = normalizeAngle((Pi - angleToTarget) +
Pi / 2);
if (angleToTarget > 0 && angleToTarget < Pi)
{
if(angleToTarget > Pi / 5)
{
angle = -15;
}
else if(angleToTarget > Pi / 10)
{
angle = -5;
}
else
{
angle = -1;
}
}
else if (angleToTarget <= TwoPi && angleToTarget >
(TwoPi - Pi))
{
if(angleToTarget < (TwoPi - Pi / 5))
{
angle = 15;
}
else if(angleToTarget < (TwoPi - Pi / 10))

61
{
angle = 5;
}
else
{
angle = 1;
}
}
else if(angleToTarget == 0)
{
angle = 0;
}
setRotation(rotation() + angle);
if(lineToTarget.length() >= 40)
{
player->play();
setPos(mapToParent(0, -(qrand() % ((4 + 1) - 1) +
1)));
countForSteps++;
if(countForSteps == 10)
{
steps = 2;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 20)
{
steps = 1;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 30)
{
steps = 0;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 40)
{
steps = 1;
update(QRectF(-40,-50,80,100));
countForSteps = 0;
}
}
else
{
player->stop();
}
QList<QGraphicsItem *> foundItems =
scene()->items(QPolygonF()
<< mapToScene(-40, -50)
<< mapToScene(30, -50)
<< mapToScene(45, -35)
<< mapToScene(45, 40)
<< mapToScene(15, 130)
<< mapToScene(-25, 130)

62
<< mapToScene(-55, 40)
<< mapToScene(-55, -55));
foreach (QGraphicsItem *item, foundItems)
{
if (item == target)
{
callbackFunc(item);
}
}
if(this->x() - 30 < 0)
{
this->setX(30);
}
if(this->x() + 30 > 1200)
{
this->setX(500 - 30);
}
if(this->y() - 30 < 0)
{
this->setY(30);
}
if(this->y() + 30 > 925)
{
this->setY(500 - 30);
}
}
void Spider::hit(int damage)
{
health -= damage;
this->update(QRectF(-30,-30,60,60));
if(health <= 0) this->deleteLater();
}
void Spider::setCallbackFunc(void (*func)
(QGraphicsItem *))
{
callbackFunc = func;
}
Spider2.h
#ifndef SPIDER2_H
#define SPIDER2_H
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QDir>
#include <QUrl>
class Spider2 : public QObject, public QGraphicsItem
{

63
Q_OBJECT
public:
explicit Spider2(QGraphicsItem * target,
QObject *parent = 0);
~Spider2();
void pause();
void hit(int damage);
signals:
void signalCheckGameOver();
void signalCheckItem(QGraphicsItem *item);
public slots:
protected:
QRectF boundingRect() const;
void paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget);
private:
qreal angle;
int steps;
int countForSteps;
QTimer *timer;
QGraphicsItem * target;
int health;
int maxHealth;
QMediaPlayer * player;
QMediaPlaylist * playlist;
QPainterPath shape()const;
private slots:
void slotGameTimer();
};
#endif
Spider2.cpp
#include "spider2.h"
#include "math.h"
static const double Pi =
3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;
static qreal normalizeAngle(qreal angle)
{
while (angle < 0)
angle += TwoPi;
while (angle > TwoPi)
angle -= TwoPi;
return angle;
}
static int randomBetween(int low, int high)
{
return (qrand() % ((high + 1) - low) + low);
}
Spider2::Spider2(QGraphicsItem *target, QObject *parent) :
QObject(parent), QGraphicsItem()
{
angle = 0;

64
steps = 0;
countForSteps = 0;
setRotation(angle);
this->target = target;
timer = new QTimer();
connect(timer, &QTimer::timeout, this,
&Spider2::slotGameTimer);
timer->start(15);
health = randomBetween(1,15);
maxHealth = health;
player = new QMediaPlayer(this);
playlist = new QMediaPlaylist(player);
player->setPlaylist(playlist);
playlist->addMedia(QUrl("qrc:/WPaukiiW.wav"));
playlist->
setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
player->setVolume(70);
}
Spider2::~Spider2()
{
}
QRectF Spider2::boundingRect() const
{
return QRectF(-50,-50,95,135);
}
QPainterPath Spider2::shape() const
{
QPainterPath path;
path.addEllipse(boundingRect());
return path;
}
void Spider2::paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(QPen(Qt::red, 2));
if(steps == 0)
{
painter->drawLine(-24,-45,-28,-35);
painter->drawLine(-28,-35,-22,-10);
painter->drawLine(-22,-10,0,0);
painter->drawLine(24,-45,28,-35);
painter->drawLine(28,-35,22,-10);
painter->drawLine(22,-10,0,0);
painter->drawLine(-35,-38,-30,-18);
painter->drawLine(-30,-18,-25,-3);
painter->drawLine(-25,-3,0,0);
painter->drawLine(35,-38,30,-18);
painter->drawLine(30,-18,25,-3);
painter->drawLine(25,-3,0,0);
painter->drawLine(-35,38,-30,18);
painter->drawLine(-30,18,-25,3);
painter->drawLine(-25,3,0,0);
painter->drawLine(35,38,30,18);

65
painter->drawLine(30,18,25,3);
painter->drawLine(25,3,0,0);
painter->drawLine(-24,45,-28,35);
painter->drawLine(-28,35,-22,10);
painter->drawLine(-22,10,0,0);
painter->drawLine(24,45,28,35);
painter->drawLine(28,35,22,10);
painter->drawLine(22,10,0,0);
} else if (steps == 1)
{
painter->drawLine(-23,-40,-24,-30);
painter->drawLine(-24,-30,-19,-9);
painter->drawLine(-19,-9,0,0);
painter->drawLine(20,-50,23,-40);
painter->drawLine(23,-40,15,-12);
painter->drawLine(15,-12,0,0);
painter->drawLine(-30,-35,-27,-24);
painter->drawLine(-27,-24,-23,-5);
painter->drawLine(-23,-5,0,0);
painter->drawLine(40,-27,35,-10);
painter->drawLine(35,-10,28,-1);
painter->drawLine(28,-1,0,0);
painter->drawLine(-40,27,-35,10);
painter->drawLine(-35,10,-28,1);
painter->drawLine(-28,1,0,0);
painter->drawLine(30,35,27,24);
painter->drawLine(27,24,23,5);
painter->drawLine(23,5,0,0);
painter->drawLine(-20,50,-27,30);
painter->drawLine(-27,30,-20,12);
painter->drawLine(-20,12,0,0);
painter->drawLine(23,40,24,30);
painter->drawLine(24,30,19,9);
painter->drawLine(19,9,0,0);
}
else if (steps == 2)
{
painter->drawLine(-20,-50,-23,-40);
painter->drawLine(-23,-40,-15,-12);
painter->drawLine(-15,-12,0,0);
painter->drawLine(23,-40,24,-30);
painter->drawLine(24,-30,19,-9);
painter->drawLine(19,-9,0,0);
painter->drawLine(-40,-27,-35,-10);
painter->drawLine(-35,-10,-28,-1);
painter->drawLine(-28,-1,0,0);
painter->drawLine(30,-35,27,-24);
painter->drawLine(27,-24,23,-5);
painter->drawLine(23,-5,0,0);
painter->drawLine(-30,35,-27,24);
painter->drawLine(-27,24,-23,5);
painter->drawLine(-23,5,0,0);
painter->drawLine(40,27,35,10);

66
painter->drawLine(35,10,28,1);
painter->drawLine(28,1,0,0);
painter->drawLine(-23,40,-24,30);
painter->drawLine(-24,30,-19,9);
painter->drawLine(-19,9,0,0);
painter->drawLine(20,50,27,30);
painter->drawLine(27,30,20,12);
painter->drawLine(20,12,0,0);
}
painter->setPen(QPen(Qt::black, 1));
QPainterPath path1(QPointF(0, -20));
path1.cubicTo(0, -20, -5, -25, -3, -35);
path1.cubicTo(-3,-35,-15,-25,-8,-17);
path1.cubicTo(-8,-17,-5,15,0,-20 );
painter->setBrush(Qt::black);
painter->drawPath(path1);
QPainterPath path2(QPointF(0, -20));
path2.cubicTo(0, -20, 5, -25, 3, -35);
path2.cubicTo(3,-35,15,-25,8,-17);
path2.cubicTo(8,-17,5,15,0,-20 );
painter->setBrush(Qt::black);
painter->drawPath(path2);
painter->setBrush(Qt::yellow);
painter->drawEllipse(-10,-25,20,15);
painter->drawEllipse(-15, -15, 30, 30);
painter->drawEllipse(-20, 0, 40,50);
painter->setPen(QPen(Qt::white,3));
painter->drawLine(-10,25,10,25);
painter->drawLine(0,35,0,15);
painter->setPen(QPen(Qt::black,1));
painter->setBrush(Qt::red);
painter->drawEllipse(-8,-23,6,8);
painter->setBrush(Qt::red);
painter->drawEllipse(2,-23,6,8);
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::red);
painter->drawRect(-20, 30, (int)
40*health/maxHealth,3);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Spider2::slotGameTimer()
{
QLineF lineToTarget(QPointF(0, 0),
mapFromItem(target, 0, 0));
qreal angleToTarget = ::acos(lineToTarget.dx() /
lineToTarget.length());
if (lineToTarget.dy() < 0)
angleToTarget = TwoPi - angleToTarget;
angleToTarget = normalizeAngle((Pi - angleToTarget) +
Pi / 2);
if (angleToTarget > 0 && angleToTarget < Pi)
{

67
if(angleToTarget > Pi / 5)
{
angle = -15;
}
else if(angleToTarget > Pi / 10)
{
angle = -5;
}
else
{
angle = -1;
}
}
else if (angleToTarget <= TwoPi && angleToTarget >
(TwoPi - Pi))
{
if(angleToTarget < (TwoPi - Pi / 5))
{
angle = 15;
}
else if(angleToTarget < (TwoPi - Pi / 10))
{
angle = 5;
}
else
{
angle = 1;
}
}
else if(angleToTarget == 0)
{
angle = 0;
}
setRotation(rotation() + angle);
if(lineToTarget.length() >= 40)
{
player->play();
setPos(mapToParent(0, -(qrand() % ((4 + 1) - 1) +
1)));
countForSteps++;
if(countForSteps == 6)
{
steps = 1;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 12)
{
steps = 0;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 18)
{
steps = 2;

68
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 24)
{
steps = 0;
update(QRectF(-40,-50,80,100));
countForSteps = 0;
}
}
else
{
player->stop();
}
QList<QGraphicsItem *> foundItems =
scene()->items(QPolygonF()
<< mapToScene(-40, -50)
<< mapToScene(30, -50)
<< mapToScene(45, -35)
<< mapToScene(45, 40)
<< mapToScene(15, 130)
<< mapToScene(-25, 130)
<< mapToScene(-55, 40)
<< mapToScene(-55, -55));

foreach (QGraphicsItem *item, foundItems)


{
if (item == target)
{
emit signalCheckItem(item);
}
}
if(this->x() - 30 < 0)
{
this->setX(30);
}
if(this->x() + 30 > 1200)
{
this->setX(500 - 30);
}
if(this->y() - 30 < 0)
{
this->setY(30);
}
if(this->y() + 30 > 925)
{
this->setY(500 - 30);
}
}
void Spider2::hit(int damage)
{
health -= damage;

69
this->update(QRectF(-30,-30,60,60));
if(health <= 0) this->deleteLater();
}
Sprite.h
#ifndef SPRITE_H
#define SPRITE_H
#include <QObject>
#include <QGraphicsItem>
#include <QTimer>
#include <QPixmap>
#include <QPainter>
class Sprite : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Sprite(QPointF point, QObject *parent = 0);
enum { Type = UserType + 1 };
int type() const;
signals:
public slots:
private slots:
void nextFrame();
private:
void paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const;
private:
QTimer *timer;
QPixmap *spriteImage;
int currentFrame;
};
#endif
Sprite.cpp
#include "sprite.h"
Sprite::Sprite(QPointF point, QObject *parent) :
QObject(parent), QGraphicsItem()

{
this->setPos(point);
currentFrame = 0;
spriteImage =
new QPixmap("C:\\YPPPA\\sprite_sheet.png");
timer = new QTimer();
connect(timer, &QTimer::timeout, this,
&Sprite::nextFrame);
timer->start(25);
}
QRectF Sprite::boundingRect() const
{
return QRectF(-10,-10,20,20);
}
void Sprite::paint(QPainter *painter, const

70
QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawPixmap(-10,-10, *spriteImage,
currentFrame, 0, 20,20);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Sprite::nextFrame()
{
currentFrame += 20;
if (currentFrame >= 300 )
{
this->deleteLater
}
else
{
this->update(-10,-10,20,20);
}
}
int Sprite::type() const
{
return Type;
}
Triangle.h
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
#include <QPolygon>
#include <QTimer>
#include <QDebug>
#include <QCursor>
#include <QGraphicsScene>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QDir>
#include <QUrl>
#include <windows.h>
class Triangle : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Triangle(QObject *parent = 0);
~Triangle();
void hit(int damage);
signals:
void signalBullet(QPointF start, QPointF end);
void signalCheckItem(QGraphicsItem *item);
public slots:
void slotTarget(QPointF point);
void slotShot(bool shot);

71
private:
QRectF boundingRect() const;
void paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget);
QPainterPath shape()const;
private slots:
void slotGameTimer();
void slotBulletTimer();
private:
QMediaPlayer * player;
QMediaPlaylist * playlist;
bool shot;
QTimer *bulletTimer;
QTimer *gameTimer;
QPointF target;
int steps;
int countForSteps;
int health;
int maxHealth;
};
#endif
Triangle.cpp
#include "triangle.h"
#include <math.h>
static const double Pi =
3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;
static qreal normalizeAngle(qreal angle)
{
while (angle < 0)
angle += TwoPi;
while (angle > TwoPi)
angle -= TwoPi;
return angle;
}
Triangle::Triangle(QObject *parent) :
QObject(parent), QGraphicsItem()
{
setRotation(0);
target = QPointF(0,0);
shot = false;
steps = 1;
countForSteps = 0;
gameTimer = new QTimer();
connect(gameTimer, &QTimer::timeout, this,
&Triangle::slotGameTimer);
gameTimer->start(10);
bulletTimer = new QTimer();
connect(bulletTimer, &QTimer::timeout, this,
&Triangle::slotBulletTimer);
bulletTimer->start(1000/6);
countForSteps = 0;

72
steps = 0;
health = 100;
maxHealth = health;
player = new QMediaPlayer(this);
playlist =new QMediaPlaylist(player);
player->setPlaylist(playlist);
playlist->addMedia(QUrl("qrc:/RunningCleats.wav"));
playlist->
setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
player->setVolume(70);
}
Triangle::~Triangle()
{
}
QRectF Triangle::boundingRect() const
{
return QRectF(-50,-45,85,130);
}
QPainterPath Triangle::shape() const
{
QPainterPath path;
path.addEllipse(boundingRect());
return path;
}
void Triangle::paint(QPainter *painter, const
QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(QPen(Qt::black, 1));
if(steps == 0)
{
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-45,30, 20, 30);
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-5,30, 20, 30);
QPolygon polygon;
polygon << QPoint(-42,56) << QPoint(-28,56)
<< QPoint(-20,30) << QPoint(-10,30)
<< QPoint(-2,56) << QPoint(12,56)
<< QPoint(4,30) << QPoint(-37,30);
painter->setBrush(Qt::darkCyan);
painter->drawPolygon(polygon);
}
else if (steps == 1)
{
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-45,55, 20, 30);
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-5,-5, 20, 30);
QPolygon polygon;
polygon << QPoint(-42,81) << QPoint(-28,81)
<< QPoint(-20,30) << QPoint(-10,30)
<< QPoint(-2,21) << QPoint(12,21)
<< QPoint(4,30) << QPoint(-37,30);

73
painter->setBrush(Qt::darkCyan);
painter->drawPolygon(polygon);

}
else if (steps == 2)
{
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-45,-5, 20, 30);
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-5,55, 20, 30);
QPolygon polygon;
polygon << QPoint(-42,21) << QPoint(-28,21)
<< QPoint(-20,30) << QPoint(-10,30)
<< QPoint(-2,81) << QPoint(12,81)
<< QPoint(4,30) << QPoint(-37,30);
painter->setBrush(Qt::darkCyan);
painter->drawPolygon(polygon);
}
painter->setPen(QPen(Qt::black,1));
painter->setBrush(Qt::black);
painter->drawRect(-1,-40,4,12);
QPolygon polygon;
polygon << QPoint(17,30)<< QPoint(3,-10)
<< QPoint(0,30);
painter->setBrush(Qt::darkCyan);
painter->drawPolygon(polygon);
polygon << QPoint(-47,30) << QPoint(-40,-5)
<< QPoint(-2,-27)<< QPoint(-2,-15)
<< QPoint(-25,5) << QPoint(-30,30);
painter->setBrush(Qt::darkCyan);
painter->drawPolygon(polygon);
painter->setBrush(Qt::darkRed);
painter->drawEllipse(-4,-30, 10, 20);
painter->setBrush(Qt::darkRed);
painter->drawRect(-1,15,4,12);
painter->setBrush(Qt::gray);
painter->drawRect(-3,-15,9,30);
painter->setPen(QPen(Qt::black,1);
painter->setBrush(Qt::darkCyan);
painter->drawEllipse(-40, 27, 50, 25);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-50, 23, 35, 23);
painter->drawEllipse(-15, 23, 35, 23);
painter->setBrush(Qt::darkYellow);
painter->drawEllipse(-30, 20, 30, 30);
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::red);
painter->drawRect(-35, 35, (int)
40*health/maxHealth,3);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Triangle::slotTarget(QPointF point)

74
{
target = point;
QLineF lineToTarget(QPointF(0, 0),
mapFromScene(target));
qreal angleToTarget = ::acos(lineToTarget.dx() /
lineToTarget.length());
if (lineToTarget.dy() < 0)
angleToTarget = TwoPi - angleToTarget;
angleToTarget = normalizeAngle((Pi - angleToTarget) +
Pi / 2);
if (angleToTarget >= 0 && angleToTarget < Pi)
{
setRotation(rotation() - angleToTarget * 180 /Pi);
}
else if (angleToTarget <= TwoPi && angleToTarget > Pi)
{
setRotation(rotation() + (angleToTarget - TwoPi )*
(-180) /Pi);
}
}
void Triangle::slotGameTimer()
{
if(GetAsyncKeyState('A') ||
GetAsyncKeyState('D') ||
GetAsyncKeyState('W') ||
GetAsyncKeyState('S'))
{
if(GetAsyncKeyState('A'))
{
this->setX(this->x() - 2);
if(!scene()->collidingItems(this).isEmpty())
{
this->setX(this->x() + 2);
}
}
if(GetAsyncKeyState('D'))
{
this->setX(this->x() + 2);
if(!scene()->collidingItems(this).isEmpty())
{
this->setX(this->x() - 2);
}
}
if(GetAsyncKeyState('W'))
{
this->setY(this->y() - 2);
if(!scene()->collidingItems(this).isEmpty())
{
this->setY(this->y() + 2);
}
}
if(GetAsyncKeyState('S'))
{

75
this->setY(this->y() + 2);
if(!scene()->collidingItems(this).isEmpty())
{
this->setY(this->y() - 2);
}
}
countForSteps++;
if(countForSteps == 10)
{
steps = 2;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 20)
{
steps = 1;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 30)
{
steps = 0;
update(QRectF(-40,-50,80,100));
}
else if (countForSteps == 40)
{
steps = 1;
update(QRectF(-40,-50,80,100));
countForSteps = 0;
}
player->play();
}
else
{
player->stop();
}
QList<QGraphicsItem *> foundItems =
scene()->items(QPolygonF()
<< mapToScene(-40, -50)
<< mapToScene(30, -50)
<< mapToScene(45, -35)
<< mapToScene(45, 40)
<< mapToScene(15, 130)
<< mapToScene(-25, 130)
<< mapToScene(-55, 40)
<< mapToScene(-55, -55));
foreach (QGraphicsItem *item, foundItems)
{
if (item == this)
continue;
emit signalCheckItem(item);
}
if(this->x() - 30 < 0)
{
this->setX(30);

76
}
if(this->x() + 30 > 1200)
{
this->setX(1200 - 30);
}
if(this->y() - 30 < 0)
{
this->setY(30);
}
if(this->y() + 30 > 925)
{
this->setY(925 - 30);
}

QLineF lineToTarget(QPointF(0, 0),


mapFromScene(target));
qreal angleToTarget = ::acos(lineToTarget.dx() /
lineToTarget.length());
if (lineToTarget.dy() < 0)
angleToTarget = TwoPi - angleToTarget;
angleToTarget = normalizeAngle((Pi - angleToTarget) +
Pi / 2);
if (angleToTarget >= 0 && angleToTarget < Pi)
{
setRotation(rotation() - angleToTarget * 180 /Pi);
}
else if (angleToTarget <= TwoPi && angleToTarget > Pi)
{
setRotation(rotation() + (angleToTarget - TwoPi )*
(-180) /Pi);
}
}
void Triangle::slotBulletTimer()
{
if(shot) emit signalBullet(mapToScene(0,-36), target);
}
void Triangle::slotShot(bool shot)
{
this->shot = shot;
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QShortcut>
#include <QDebug>
#include <QTimer>
#include <QMessageBox>
#include <QList>
#include <QPixmap>

77
#include <QPainter>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QDir>
#include <QUrl>
#include <QBrush>
#include <QImage>
#include <QGraphicsTextItem>
#include <QGraphicsSceneMoveEvent>
#include <QKeyEvent>
#include <QTransform>
#include <QLabel>
#include <QImage>
#include <customscene.h>
#include <triangle.h>
#include <apple.h>
#include <spider.h>
#include <bullet.h>
#include <spider2.h>
#define GAME_STOPED 0
#define GAME_STARTED 1
namespace Ui
{
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
QPixmap *pi;
private:
Ui::Widget *ui;
CustomScene *scene;
Triangle *triangle;
QTimer *timerCreateApple;
QList<QGraphicsItem *> apples;
double count;
Spider * spider;
Spider2 * spider2;
int gameState;
QTimer *timerTarget;
static QList<QGraphicsItem *> targets;
static void slotHitTarget(QGraphicsItem *item);
static void slotHitTarget2(QGraphicsItem *item);
QMediaPlayer * m_player;
QMediaPlaylist * m_playlist;
QBrush *brush;
QPalette *palette;
private slots:
void slotDeleteApple(QGraphicsItem * item);
void slotCreateApple();

78
void slotBullet(QPointF start, QPointF end);
void slotCreateTarget();
void slotCreateTarget2();
void on_pushButton_clicked();
void on_pushButton_2_clicked();
};
#endif
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
static int randomBetween(int low, int high)
{
return (qrand() % ((high + 1) - low) + low);
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
this->resize(1270,945);
this->setFixedSize(1270,945);
count = 0;
ui->setupUi(this);
scene = new CustomScene();
ui->graphicsView->setScene(scene);
ui->graphicsView
->setRenderHint(QPainter::Antialiasing);
ui->graphicsView
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->graphicsView->
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scene->setSceneRect(0,0,1270,945);
scene->
setBackgroundBrush(QPixmap("C:\\YPPPA\\kniga.jpg"));
timerCreateApple = new QTimer();
gameState = GAME_STOPED;
};
QCursor cursor =
QCursor(QPixmap("C:\\YPPPA\\pricel.png"));
ui->graphicsView->setCursor(cursor);
ui->graphicsView->setMouseTracking(true);
m_player = new QMediaPlayer(this);
m_playlist = new QMediaPlaylist(m_player);
m_player->setPlaylist(m_playlist
m_playlist->addMedia(QUrl("qrc:/pulaochkorW.wav"));
m_playlist
->setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
m_player->setVolume(150);
}
Widget::~Widget()
{
delete ui;
}

79
void Widget::slotBullet(QPointF start, QPointF end)
{
Bullet *bullet = new Bullet(start,end,triangle);
bullet->setCallbackFunc(slotHitTarget);
scene->addItem(bullet);
m_player->play();
}
void Widget::slotCreateTarget()
{
Spider *target = new Spider(triangle);
target->setCallbackFunc(slotHitTarget);
scene->addItem(target);
target->setPos(qrand() % ((1200 - 80 + 1) - 80) + 80,
qrand() % ((925 - 80 + 1) - 80) + 80);
target->setZValue(-1);
targets.append(target);
}
void Widget::slotHitTarget(QGraphicsItem *item)
{
foreach (QGraphicsItem *targ, targets)
{
if(targ == item)
{
Spider *t = qgraphicsitem_cast <Spider *>
(targ);
t->hit(randomBetween(1,3));
Spider2 *m = qgraphicsitem_cast <Spider2 *>
(targ);
m->hit(randomBetween(1,3));
}
}
}
QList<QGraphicsItem *> Widget::targets;
void Widget::slotCreateTarget2()
{
Spider2 *target = new Spider2(triangle);
scene->addItem(target);
target->setPos(qrand() % ((1200 - 80 + 1) - 80) + 80,
qrand() % ((925 - 80 + 1) - 80) + 80);
target->setZValue(-1);
targets.append(target);
}
void Widget::slotDeleteApple(QGraphicsItem *item)
{
foreach (QGraphicsItem *apple, apples)
{
if(apple == item)
{
scene->removeItem(apple);
apples.removeOne(item);
delete apple;
ui->lcdNumber->display(count++);
QMediaPlayer *player1 =

80
new QMediaPlayer(this);
QMediaPlaylist *playlist1 =
new QMediaPlaylist(player1);
playlist1->addMedia
(QUrl("qrc:/WMonetaZzW.wav"));
player1->setPlaylist(playlist1);
playlist1-> setPlaybackMode
(QMediaPlaylist::CurrentItemOnce);
player1->setVolume(20);
player1->play();
}
}
}
void Widget::slotCreateApple()
{
Apple *apple = new Apple();
scene->addItem(apple);
apple->setPos((qrand() % (1200)) * ((qrand()%2 ==
1)?1:-1),
(qrand() % (925)) * ((qrand()%2 ==
1)?1:-1));
apple->setZValue(-1);
apples.append(apple);
}
void Widget::on_pushButton_clicked()
{
scene->setBackgroundBrush
(QPixmap("C:\\YPPPA\\pesok.jpg"));
scene->addRect(0,0,1250,15,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
scene->addRect(0,0,15,870,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
scene->addRect(0,865,1250,15,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
scene->addRect(1235,0,15,870,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
QMediaPlayer *player3 = new QMediaPlayer(this);
QMediaPlaylist *playlist3 =
new QMediaPlaylist(player3);
player3->setPlaylist(playlist3);
playlist3->addMedia
(QUrl("qrc:/WPustunyaFonWKor.wav"));
playlist3->setPlaybackMode
(QMediaPlaylist::CurrentItemInLoop);
player3->setVolume(150);
player3->play();
count = 0;
ui->lcdNumber->display(count);
triangle = new Triangle();
scene->addItem(triangle);
triangle->setPos(200,200);
timerTarget = new QTimer();
connect(timerTarget, &QTimer::timeout, this,

81
&Widget::slotCreateTarget);
timerTarget->start(3000);
connect(timerCreateApple, &QTimer::timeout, this,
&Widget::slotCreateApple);
timerCreateApple->start(1000);
connect(triangle, &Triangle::signalCheckItem, this,
&Widget::slotDeleteApple);
ui->pushButton->setEnabled(false);
ui->pushButton_2->setEnabled(false);
ui->pushButton->setStyleSheet ( "QPushButton
{Background:transparent;}");
ui->pushButton_2->setStyleSheet ( "QPushButton
{Background:transparent;}");
connect(scene, &CustomScene::signalTargetCoordinate,
triangle, &Triangle::slotTarget);
connect(scene, &CustomScene::signalShot, triangle,
&Triangle::slotShot);
connect(triangle, &Triangle::signalBullet, this,
&Widget::slotBullet);
gameState = GAME_STARTED;
}
void Widget::on_pushButton_2_clicked()
{
Scene->setBackgroundBrush
(QPixmap("C:\\YPPPA\\pautina2.jpg"));
scene->addRect(0,0,1250,15,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
scene->addRect(0,0,15,870,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
scene->addRect(0,865,1250,15,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
scene->addRect(1235,0,15,870,QPen(Qt::black, 1),
QBrush(QPixmap("C:\\YPPPA\\stena2.jpg")));
QMediaPlayer *player4 = new QMediaPlayer(this);
QMediaPlaylist *playlist4 =
new QMediaPlaylist(player4);
player4->setPlaylist(playlist4);
playlist4->addMedia(QUrl("qrc:/WWPescheraFONN.wav"));
playlist4->setPlaybackMode
(QMediaPlaylist::CurrentItemInLoop);
player4->setVolume(70);
player4->play();
count = 0;
ui->lcdNumber->display(count);
triangle = new Triangle();
scene->addItem(triangle);
triangle->setPos(200,200);
timerTarget = new QTimer();
connect(timerTarget, &QTimer::timeout, this,
&Widget::slotCreateTarget2);
timerTarget->start(3000);
connect(timerCreateApple, &QTimer::timeout, this,
&Widget::slotCreateApple);

82
timerCreateApple->start(1000);
connect(triangle, &Triangle::signalCheckItem, this,
&Widget::slotDeleteApple);
ui->pushButton->setEnabled(false);
ui->pushButton_2->setEnabled(false);
ui->pushButton->setStyleSheet ( "QPushButton
{Background:transparent;}");
ui->pushButton_2->setStyleSheet ( "QPushButton
{Background:transparent;}");

connect(scene, &CustomScene::signalTargetCoordinate,
triangle, &Triangle::slotTarget);
connect(scene, &CustomScene::signalShot, triangle,
&Triangle::slotShot);
connect(triangle, &Triangle::signalBullet, this,
&Widget::slotBullet);
}
Main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
Widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1273</width>
<height>860</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QGraphicsView" name="graphicsView">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>1251</width>
<height>881</height>

83
</rect>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>400</x>
<y>20</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>СЧЁТ</string>
</property>
</widget>
<widget class="QLCDNumber" name="lcdNumber">
<property name="geometry">
<rect>
<x>460</x>
<y>10</y>
<width>141</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>110</x>
<y>190</y>
<width>501</width>
<height>431</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">border-image:
url(:/button1.png);</string>
</property>
<property name="text">
<string/>

84
</property>
<property name="shortcut">
<string/>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
<property name="autoExclusive">
<bool>false</bool>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>690</x>
<y>190</y>
<width>501</width>
<height>431</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">border-image:
url(:/button2.jpg);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
<zorder>graphicsView</zorder>
<zorder>label</zorder>
<zorder>lcdNumber</zorder>
<zorder>pushButton_2</zorder>

85
<zorder>pushButton</zorder>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

Приложение В. Упражнение для глаз

Исходное положение: сидя или стоя.


Упражнение 1
Глаза закрыты. Круговыми движениями обеих рук массируйте
глазные яблоки в течение 10 с.
Упражнение 2
Взгляд прямо перед собой, затем вправо, вверх, влево, вниз - в
течение 10 с.
Упражнение 3
Усиленно зажмуривайте и открывайте глаза в течение 10 с.
Упражнение4
Отводите глаза сначала в одну, потом в другую сторону 2-3 раза,
затем закройте на 10 с.

86
87