Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

ИСТОРИЯ ВОЗНИКНОВЕНИЯ И РАЗВИТИЯ ЯЗЫКА С, С++ и Java (ЯЗЫКИ ПРОГРАММИРОВАНИЯ C, C++, Java)

Содержание:

ВВЕДЕНИЕ

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

Существует огромное количество языков программирования различных типов: процедурные, функциональные, логические, объектно-ориентированные, скриптовые. Они могут иметь различные виды типизации, синтаксиса, и областей использования. Выполняться в собственной среде, интерпретироваться или компилироваться.

Цель данной работы, рассмотреть вопросы развития языков программирования, историю возникновения и современное представление таких языков общего назначения как С, С++ и Java, а также показать на примере способы проектирования и реализации программ на этих языках. Данные языки, безусловно, являются одними из самых распространенных, и непременно входят в десятку самых востребованных языков современности. Согласно индексу TIOBE, который оценивает популярность языков программирования по количеству поисковых запросов в сети интернет, первые строчки уже более 20 лет неизменно занимают языки С, С++, Java.[1]

Screenshot_47

Также, согласно статистическим данным, этого же источника, на сегодняшний день ситуация остается неизменной:

Screenshot_46

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

ГЛАВА 1. ЯЗЫКИ ПРОГРАММИРОВАНИЯ C, C++, Java

Язык программирования С

Язык C — это универсальный, компилируемый статически типизированный язык программирования общего назначения, разработанный в 1969—1973 годах сотрудником Bell Labs Деннисом Ритчи как развитие языка B. Для С характерны экономичность выражения, современный поток управления и структуры данных, богатый набор операторов. Отсутствие ограничений и общность языка делают его удобным и эффективным для многих задач. Согласно дизайну языка, его конструкции близко сопоставляются типичным машинным инструкциям, благодаря чему он нашёл применение в проектах, для которых был свойственен язык ассемблера, в том числе в операционных системах и в различном прикладном программном обеспечении для множества устройств. Язык программирования С оказал существенное влияние на развитие индустрии программного обеспечения, а его синтаксис стал основой для таких языков программирования, как C++, C#, Java и Objective-C. [2]

Создание языка С непосредственно связано с языком ALGOL, который был создан в 1958 году, в противовес языку FORTRAN, которые имел ряд определенных недостатков в своей структуре. В свою очередь Математическая лаборатория Кембриджского Университета совместно с Компьютерным отделом Лондонского университета, почерпнули немало идей из ALGOL-60, и создали в 1963 году язык CPL (Combined Programming Language).

Однако CPL посчитали сложным, и в в 1966 году Мартином Ричардсоном был создан язык BCPL, который изначально создавался для написания компиляторов. На момент создания, в связи с возможностью портировать язык на разные платформы, он играл важную роль в индустрии. BCPL послужил прародителем для языка B, разработанного в 1969 году, который был использован для написания самых ранних версий UNIX. Именно этот язык послужил непосредственным предшественником языка С.

В дальнейшем, история языка С неразрывно связана с операционной системой "UNIX". Он является ключевым языком данной системы, на нем было переписано ее ядро, и создано большое количество программного обеспечения. Это низкоуровневый язык, с возможностью управления памятью и простым, но достаточным набором синтаксических конструкций. Язык C является одним из наиболее распространённых языков и прародителем многих современных языков программирования.

В языке C изначально отсутствуют операции, имеющие дело непосредственно с составными объектами, такими как строки символов, множества, списки или с массивами, рассматриваемыми как целое. Язык не предоставляет никаких других возможностей распределения памяти, кроме статического определения и механизма стеков, обеспечиваемого локальными переменными функций. Также в С отсутствует “сборка мусора”, возможности ввода-вывода, и нет никаких встроенных методов доступа к файлам. Все эти механизмы высокого уровня должны обеспечиваться явно вызываемыми функциями. Отсутствие многих из этих возможностей было продиктовано желанием создателей сохранить небольшой размер языка, что дает определенные преимущества. Так как "C" относительно мал, он не требует много места для своего описания и может быть быстро выучен. Компилятор может быть простым и компактным, что позволяет реализовать его в короткие сроки, например для новых систем. Это обеспечивает высокую степень мобильности языка.[3]

С течением времени, язык развивался и в стандарте С99 он получил новые возможности, из которых в качестве наиболее значимых можно отметить массивы переменной длины и встраиваемые функции. А в стандарте C11 в язык добавили реализацию потоков и поддержку атомарных типов.[4]

История и особенности языка С++

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

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

Язык С++ является одним из наиболее широко распространенных языков программирования. Программы, написанные на языке С++, можно встретить всюду и на дне океана, и на поверхности Марса. Кроме того, существует точный и полный общедоступный международный стандарт языка С++, не защищенный правом собственности. Качественные и/или бесплатные реализации этого языка доступны для любых компьютеров. Большинство концепций программирования языка С++, можно непосредственно использовать и в других языках таких как С, С#, Fortran и Java.[5]

Язык программирования С++ был создан в начале 1980-х годов, сотрудником фирмы Bell Laboratories — Бьёрном Страуструпом. Он придумал ряд усовершенствований к языку программирования C, для собственных нужд. Т. е. изначально не планировалось создания языка программирования С++. Ранние версии языка С++, известные под именем «Cи с классами», начали появляться с 1980 года. Страуструп добавил возможность работы с классами и объектами к языку С. Язык Simula также называется среди основных источников идеи для реализации объектно-ориентированных возможностей языка C++, самим автором. Очевидно, самой важной чертой C with Classes, а позже и C++ была концепция класса. Синтаксис C++ был основан на синтаксисе C, так как Бьёрн Страуструп стремился сохранить совместимость с с этим языком.

Основной целью, по словам автора языка, было спроектировать язык достаточно простой для понимания, чтобы привлечь пользователей, и довольно простой в реализации, чтобы заинтересовать разработчиков компиляторов. С другой стороны, относительно несложная реализация должна была генерировать код, который не уступал бы C в корректности, скорости и величине. Пользователь, незнакомый с языком на практике и находясь в не очень «дружелюбной» среде разработки, тем не менее должен суметь воспользоваться компилятором в реальных проектах.[6] В 1998 году был ратифицирован международный стандарт языка C++: ISO/IEC 14882:1998 «Standard for the C++ Programming Language», а после принятия технических исправлений к стандарту в 2003 году — следующая версия этого стандарта — ISO/IEC 14882:2003.[7]

C++ добавляет к C объектно-ориентированные возможности. Он вводит классы, которые обеспечивают три самых важных свойства ООП: инкапсуляцию, наследование и полиморфизм.

Язык программирования Java

На сегодняшний момент язык Java является одним из самых распространенных и популярных языков программирования. Первая версия языка появилась еще в 1996 году. Java задумывался как универсальный язык программирования, который можно применять для различного рода задач. Это сильно типизированный объектно-ориентированный язык программирования, разработанный компанией Sun Microsystems. Одно из основных преимуществ языка Java — независимость от платформы, на которой выполняются программы, т.е. один и тот же код можно запускать под управлением операционных систем Windows, Solaris, Linux, Machintosh и др. Это действительно необходимо, когда программы загружаются через Интернет для последующего выполнения под управлением разных операционных систем. Другое преимущество заключается в том, что синтаксис языка Java похож на синтаксис языка C++, и программистам, знающим языки C и С++, его изучение не составляет труда.[8]

Для создателей языка было принципиально важно иметь возможность разрабатывать программы, не содержащие ошибок, на языке Java легче, чем на языке С++. Они снабдили язык Java средствами, позволяющими исключить саму возможность создавать программы, в которых были бы скрыты наиболее распространенные ошибки, характерные для прародителей, языков С и С++. Для этого в языке Java сделано следующее:

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

• Введены истинные массивы и запрещена арифметика указателей.

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

• Исключена возможность перепутать оператор присваивания с оператором сравнения на равенство.

• Исключено множественное наследование. Оно заменено новым понятием — интерфейсом, позаимствованным из языка Objective C. Интерфейс дает программисту почти все, что тот может получить от множественного наследования, избегая при этом сложностей, возникающих при управлении иерархиями классов. [9]

Платформа Java — это программное обеспечение, предоставляющее нам среду

времени исполнения. Это виртуальная машина Java (JVM), линкующая и выполняющая код в том виде, в каком он ей предоставляется. Код предоставляется в виде файлов классов, непригодных для чтения человеком. Иными словами, машина не интерпретирует непосредственно файлы с исходным кодом на языке Java, а требует предварительного преобразования этого кода в файлы классов.

Одна из основных причин успеха Java как системы ПО заключается в ее стандартизации. Java имеет спецификации, описывающие как должна работать платформа. Стандартизация позволяет различным производителям и участникам разнообразных проектов создавать реализации, которые теоретически должны работать одинаково. Такие спецификации не гарантируют, насколько высока будет производительность конкретной реализации одной конкретной задачи, но вполне гарантируют правильность результатов. В связи с чем Java широко используется для написания различного ПО во всех сферах деятельности, где присутствуют информационные системы и требования надежности выходят на первый план. [10]

ГЛАВА 2. РАЗРАБОТКА КОМПОНЕНТА ПРИЛОЖЕНИЯ НА ЯЗЫКЕ С++

2.1 Планирование разработки

В этой главе рассматривается практическое применение современного стандарта языка С++ на примере реализации задачи в среде Unreal Engine 4 (v4.20.3) с использованием API игрового движка и встроенных средств разработки и визуализации.

В общем виде проект представляет собой компонентный модуль приложения (игры), в жанре стратегии в реальном времени. Проект реализуется на игровом движке с открытым исходным кодом Unreal Engine 4 (далее по тексту UE4), который написан на языке C++, и удовлетворяет потребности профессионалов в области архитектуры, визуализации дизайна, дизайна продуктов, производства, приложений для сферы развлечений и игр. UE4 позволяет разрабатывать приложения под разные платформы, включая Windows PC, PlayStation 4, Xbox One, Mac OS X, iOS, Android, AR, VR, Linux, SteamOS, HTML5.[11]

Основные средства разработки, которые я использовал в работе - это Unreal Studio, которая является непосредственно средой разработки UE4, и Visual Studio 2017 Community, для написания кода на языке C++. Для остальных целей я выбрал онлайн инструмент для проектирования диаграмм Lucid Chart [12], систему контроля версий Git для отслеживания изменений в проекте, терминал GitBash для операционной системы Windows 10, а также приложение ResilioSync для синхронизации больших пакетов с ассетами графики, звука, материалов и т.д. Все выбранные мной средства являются условно бесплатными и позволяют реализовать задачу в полной мере.

Среда разработки движка UE4 предоставляет разработчику высокоуровневые библиотеки и API на языке C++, кроме того, позволяет использовать встроенный язык визуального программирования Blueprints Visual Scripting, более удобный для использования специалистами, работающими в проекте по другим задачам, например 3D художникам или дизайнерам уровней, которые не владеют навыками программирования на языке C++, а также в случае быстрого прототипирования или просто удобства использования для конкретной задачи. Такое разделение позволяет максимально эффективно распределить ресурсы, уменьшить порог вхождения для всех специалистов, участвующих в разработке и ускорить создание продукта в реальных условиях.

Для меня, как для одного из программистов команды разработки, стояла задача реализации системы разрушений объектов в реальном времени. Она должна чётко показывать переходы между состояниями объекта в зависимости от показателя его здоровья, которое выражается в условных единицах HealthPoints. Это не только красивые визуальные эффекты, но и одна из ключевых геймплей особенностей, поэтому очень важно видеть чётко данный переход, и отличать одно состояние здоровья объекта от другого. Графическое отображение объектов на сцене является индикатором, по которому игрок оценивает состояние юнитов и зданий в его управлении, и на основании этой информации принимает тактические и стратегические решения.

В документации, которая являлась основным источником информации и одновременно техническим заданием для программиста, были выделены основные требования реализации задачи:

  1. У каждого объекта указывается количество состояний от 0 до 5-ти включительно.
  2. У разных объектов могут быть разные точки перехода между состояниями.
  3. Для оптимизации достаточно использовать процент от HealthPoints в целочисленных значениях (integer).
  4. Юнит может быть не только поврежден, но и отремонтирован, т.е. может поменять свое состояние в лучшую сторону.
  5. У дизайнера должен быть удобный инструмент для редактирования состояний, выбора их количества и назначения атрибутов для этих состояний в редакторе Unreal Studio.
  6. В случае изменения состояния объекта, для визуализации будут использованы специально подготовленные 3D модель нового состояния, анимация, материал и текстуры.
  7. Смена состояния также сопровождается звуковыми эффектами, которые отличаются, в зависимости от улучшения или ухудшения состояния юнита.
  8. В случае повреждения объекта и перехода его в худшее состояние, проигрываются визуальные эффекты (ParticleEffects), которые скрывают момент подмены 3D модели и добавляют эффектности визуализации.

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

Так как одним из пунктов в документации была указана возможность редактирования данных из редактора Unreal Studio не техническими специалистами, необходимо было реализовать базу данных с интерфейсом, доступным из редактора, без необходимости открывать исходный код для внесения изменений. Поэтому мне необходимо было выбрать один из вариантов встроенных классов для хранения данных (UDataTable, UDataAsset), с готовым интерфейсом, понятным для 3D специалистов.

На данном этапе все численные характеристики объектов хранились в отдельной таблице, представленной в виде встроенного UE4 класса UDataTable.[13] Этот формат был выбран как удобный вариант для экспорта данных из таблиц MS Excel, в которых гейм-дизайнер проекта производил расчеты. Я рассматривал один из вариантов создания базы для системы разрушений в той же таблице, с целью централизованного хранения данных. Однако, после обсуждения с 3D художниками, было принято решение о разделении численных данных и данных, содержащих атрибуты визуализации для отображения разрушений, т.к. они имеют принципиально разное назначение, и разделение представляется логичным и позволяет максимально ускорить поиск, и удобство редактирования в процессе дальнейшей работы с компонентом.

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

Во-первых, композиция позволяет построить более гибкую систему, которая будет готова к изменениям в процессе исполнения программы. Во-вторых, она позволит инкапсулировать объект, т.е. скрыть реализацию и предоставить только необходимый интерфейс для пользователей компонента (black-box reuse).[14] В-третьих, архитектура UE4 позволяет использовать компонентно-ориентированный подход без специальной реализации связей в объектах.[15]

Для начала, в рамках системного анализа компонента, я построил его BlackBox диаграмму для определения входных и выходных данных:

Screenshot_17

В данном представлении мы можем определить, что на входе компоненту достаточно получить от объекта информацию о HealthPoints в процентном выражении, и на основании этих данных изменить текущее состояние объекта посредством подмены 3d модели и набора визуальных и звуковых эффектов, если это соответствует правилам, заданным дизайнером в редакторе. Компонент также должен иметь доступ к атрибутам состояний объекта, назначенных в редакторе.

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

Все объекты содержащие DestroyingComponent будут иметь набор состояний от 100% до 0%. При этом, для каждого состояния будет определен набор атрибутов, согласно документации, достаточный для реализации всех аудио и визуальных эффектов на сцене.

Screenshot_13

На следующем этапе работы я решил описать схематически, каким образом будет работать логика внутри нашего компонента:

Screenshot_15

Далее необходимо было принять решение, какими средствами будет реализован сам компонент. Я решил максимально скрыть содержимое объекта, описать всю логику работы компонента на С++, основу структуры данных также реализовать на C++ и предоставить пользователям интерфейс, через который было бы возможно редактирование атрибутов в Unreal Studio. Такой подход также был связан с большим количеством предполагаемых вызовов операций над объектами в реальном времени, и нагрузкой на процессор и GPU, где использование C++ предпочтительнее Blueprint по параметрам быстродействия.

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

Поэтому я создавал все С++ файлы с помощью средств редактора, которые позволяет автоматически сформировать все необходимые связи в проекте и включить новый компонент в систему “сборки мусора”.[16]

Screenshot_14

В своей работе я придерживался общих рекомендаций по практическому программированию [17], а также стандартов написания кода Unreal Coding Standard. [18]

Пошаговый план разработки компонента системы:

Screenshot_16

2.2. Реализация структуры данных

На данном этапе я завершил планирование разработки и приступил непосредственно к реализации. Я сравнил два варианта хранилища, которые предоставляет нам UE4 и сделал выбор в пользу DataAsset, по нескольким параметрам:

  1. Атрибуты состояния объекта хранят в основном ассеты, назначаемые в Blueprints, и DataAsset предоставляет более удобный интерфейс для пользователя компонента, в сравнении с DataTable, в котором все хранится в виде таблицы.
  2. В случае перемещения DataAsset в папках проекта, все связи обновляются автоматически, и нет необходимости менять ссылку на него в коде.
  3. Возможность хранить сложные типы данных, в данном случае структуры, позволяет удобно организовать хранение и уменьшить вероятность случайных ошибок.

Для создания DataAsset необходимо в первую очередь добавить базовый класс С++, в котором будем описана структура данных. Добавляем класс через редактор, для корректной работы UnrealBuildTool [19] и UnrealHeaderTool [20], и задаем базовый класс DataAsset:

Screenshot_18

Внутри класса UnitAsset необходимо создать структуру данных, которая будет хранить в себе ссылку на объект и соответствующую ему структуру с набором состояний для каждого уровня HealthPoints. Так как объекты уникальны, и не используются вставки и сортировки в runtime, то логичным представляется выбор контейнера типа Map. Таким образом, идентификатор класса будет являться ключом, а список его состояний - значением этого ключа. В библиотеке UE4 предоставляются свои классы для реализации контейнеров, поэтому я буду использовать шаблонный класс TMap< >. [21]

Для набора состояний объекта также будет удобно использовать этот контейнер, но только уже с уровнем HealthPoint в виде ключа и структурой с набором атрибутов в виде значения.

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

Screenshot_20

Здесь используется макрос USTRUCT() при объявлении структуры, и GENERATED_BODY() для корректной “сборки мусора”, также в теле структуры нам необходимо установить параметры в макросе UPROPERTY(), для отображения и возможности присваивания значения атрибутам в редакторе. [22]

Все указатели в структуре инициализируются значением nullptr, в целях предотвращения ошибок обращения к случайным участкам памяти. [23]

Необходимо также помнить о включении нужных заголовков для всех используемых классов:

Screenshot_21

В процессе разработки выяснилось, что UE4 имеет ограничение на создание вложенных контейнеров напрямую в шаблонных классах. Я пришел к решению создать структуру-обертку для набора состояний, и уже внутри этой структуры создать контейнер для хранения состояний, в котором ключом будет являться % от HealthPoints:

Screenshot_22

Это позволит вложить структуру в контейнер на следующем уровне.

Так как все объекты в UE4 наследуются от базового класса UObject, то используется такая возможность C++, как создание указателя на родительский класс, что позволит использовать данный указатель для всех объектов:

Screenshot_19

Далее, необходимо реализовать функцию получения данных из базы для конкретного объекта. Эта функция принимает на входе указатель на объект, и возвращает структуру с соответствующим списком состояний и набором атрибутов для каждого состояния. Объявляем public функцию в файле UnitAsset.h:

Screenshot_23

Здесь используется макрос UFUNCTION() с параметром BlueprintCallable, для возможности вызова этой функции из Blueprint. Для реализации этой функции я создал вспомогательную функцию, которая будет сравнивать объекты по идентификатору класса. Объявим эту функцию в разделе private:

Screenshot_24

В процессе создания объектов на сцене, идентификаторам класса добавляется суффикс вида _NN, где NN представляет собой номер ID назначенный UE4 для каждой новой сущности, поэтому реализация функции сравнения идентификаторов выглядит следующим образом:

Screenshot_56

Закомментированные строки 19 и 21 были использованы для тестирования корректности работы функции при разработке. Теперь мы можем реализовать функцию GetUnitHealthStates:

Screenshot_45

В реализации этой функции я использовал синтактические конструкции современного стандарта С++, такие как цикл перебора коллекции for ( : ) для каждого объекта в базе и идентификатор auto, для сокращения записи типов. [25] Поиск и инициализация ссылки на структуру будет происходить в компоненте DestroyingComponent. Также, все функции в базе объявляются константными, что гарантирует безопасность и защиту от каких-либо изменений в структуре. В случае попытки внесения изменений, компилятор выдаст сообщение об этом на этапе компиляции файла.

На данном этапе структура данных для компонента готова, теперь необходимо создать на ее основе DataAsset в редакторе, и протестировать корректность отображения данных в редакторе. Создаем DataAsset:

Screenshot_27Screenshot_28

Проверяем корректность отображения данных в редакторе и заполняем тестовый набор данных для юнита:

Screenshot_29

Screenshot_30

2.3. Реализация структуры данных

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

Screenshot_31

После создания компонета, необходимо создать указатель на структуру данных UnitAsset, для того чтобы иметь возможность обращаться к ней, и получать атрибуты состояний. Также, объявляется основная публичная функция SetDestroyingStatus:

Screenshot_34

После этого компонент отображается в редакторе, есть возможность создания компонента для объекта, и установка ссылки на базу данных UnitAsset:

Screenshot_32Screenshot_33

Так как имеется большой набор атрибутов, и необходимо совершить комплекс действий внутри функции SetDestroyingComponent, я решил разбить каждое действие на отдельные приватные функции, что улучшит надежность и читаемость кода:

Screenshot_40

Я добавил ряд приватных переменных для работы. В переменной UnitHealthAttributes будет храниться набор состояний объекта, полученный из UnitAsset, с целью сократить количество обращений к базе данных. UnitHealthStateArray будет использоваться для упорядоченного хранения состояний и правильного переключения, т.к. контейнер TMap< > не гарантирует возвращение ключей в процессе перебора в каком-либо порядке. [21] Также это гарантирует правильность исполнения кода, в случае если данные будут неверно изменены в редакторе пользователем компонента. Переменная Owner хранит ссылку на объект, который владеет компонентом, а переменная OwnerCurrentState хранит текущее состояние объекта.

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

Инициализируем приватные переменные в функции BeginPlay(), которая запускается при создании объекта на сцене:

Screenshot_36

Для инициализации данных UnitHealthAttributes вызывается функция GetUnitHealthStates из UnitAsset с параметром Owner. Таким образом возвращается набор состояний для объекта, если таковые существуют в базе. Далее, генерируется и упорядочивается список состояний в UnitHealthStateArray.

Алгоритм изменения состояний объекта:

Screenshot_39

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

Screenshot_41

Функции SetStatusHigher и SetStatusLower отличаются тем, что при ухудшении состояния срабатывает функция SpawnParticleEffect, и проигрываются различные звуковые эффекты. Также, перед выполнением инструкций повсеместно проводится проверка на нулевой указатель, для обеспечения безопасности операций.

В последующих функциях используется шаблонный компонент, предоставляемый UE4 AActor::FindComponentByClass< > [24], он позволяет найти необходимые компоненты. Если компоненты были найдены, и имеется новый вариант в атрибутах, происходит выполнение замены.

Функции смены 3D модели и анимации:

Screenshot_42

Функции смены материала и функция создания и визуализации эффекта частиц:

Screenshot_43

Функция проигрывания звуковых эффектов:

Screenshot_44

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

Я описал всю логику в нашем компоненте, скомпилировал проект и протестировал его работу на юнитах в проекте. Для этого я подключил вызов функции SetDestroyingStatus в тех функциях, где происходит изменение значений HealthPoint объекта, в базовом классе, от которого наследуют все целевые объекты в проекте - UnitBase.

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

ЗАКЛЮЧЕНИЕ

В данной курсовой работе был раскрыт вопрос развития языков программирования, в первой главе была представлена информация об аспектах исторического развития языков С, С++ и Java, их особенностях и задачах проектирования. А также предпосылках их возникновения, их возможностях и преимуществах, которые предоставляются разработчикам. Во второй главе была решена практическая задача, которая продемонстрировала возможности применения одного из этих языков в современных приложениях, с использованием передовых средств разработки. Раскрываются аспекты эволюции языка С++ и возможности использования улучшений, привнесенных в современный стандарт языка. Конечно, отдельно каждый из этих языков представляет собой целую экосистему из стандартных библиотек, расширений и фреймворков. Они используются для реализации задач в разных сферах, где-то пересекаются, где-то являются единственно предпочтительным вариантом. Однако, безусловно, каждый из них является уникальным, мощным и современным инструментом для разработчика. Каждый из них занимает особое положение среди языков программирования в историческом смысле. Можно убедиться, что несмотря на свою богатую историю, эти языки не перестают развиваться. Улучшаются их конструкции и возможности, для решения самых передовых задач, таким образом позволяя данным языкам программирования неизменно оставаться популярными и востребованными.

ЛИТЕРАТУРА И ИСПОЛЬЗУЕМЫЕ ИСТОЧНИКИ

  1. https://www.tiobe.com/tiobe-index/
  2. Брайан Керниган, Деннис Ритчи. Язык программирования C. — Москва: Вильямс, 2015, C. 9-12
  3. https://www.techopedia.com/the-history-of-the-c-programming-language/2/32996
  4. http://www.iso-9899.info/wiki/The_Standard
  5. Страуструп Б. Программирование: принципы и практика с использованием С++, 2-е изд. : Пер. с англ. - М. : ООО "И.Д. Вильяме", 2016, C. 26
  6. Дизайн и эволюция С++: Пер. с англ. – М.: ДМК Пресс, 2016, C. 30-46
  7. http://www.open-std.org/jtc1/sc22/wg21/docs/standards
  8. Java 2. Библиотек профессионала, то 1. Основы. 8- издание.: Пер. с англ. — М.: ОО "И.Д. Вильямс", 2012, С. 17-25
  9. https://docs.oracle.com/javase/specs/jls/se8/html/
  10. Java. Новое поколение разработки. — СПб.: Питер, 2014, С. 42
  11. https://www.unrealengine.com/en-US/faq
  12. https://www.lucidchart.com
  13. https://api.unrealengine.com/INT/API/Runtime/Engine/Engine/UDataTable/index.html
  14. Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приемы объектно-ориентированного проектирования. Паттерны проектирования. — СПб: Питер, 2017, С. 33-34
  15. https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Actors/Components
  16. https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Objects/Optimizations
  17. Керниrан, Брайан У., Пайк, Роб. Практика программирования. : Пер. с англ. - М. : ООО "И.Д. Вильямc", 2015, C. 17-39
  18. https://docs.unrealengine.com/en-us/Programming/Development/CodingStandard
  19. https://docs.unrealengine.com/en-US/Programming/BuildTools/UnrealBuildTool
  20. https://docs.unrealengine.com/en-us/Programming/BuildTools/UnrealHeaderTool
  21. https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/TMap
  22. https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Properties
  23. Страуструп Б. Программирование: принципы и практика с использованием С++, 2-е изд. : Пер. с англ. - М. : ООО "И.Д. Вильямc", 2016, C. 657-658
  24. https://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/AActor/FindComponentByClass/2/index.html
  25. Мейерс, Скотт. Эффективный и современный С++: 42 рекомендации по использованию С++ 11 и С++14.: Пер. с англ. - М. : ООО "ИЛ. Вильямc", 2016, С.49, С.69