Русский
Русский
English
Статистика
Реклама

Для начинающих

Перевод 30 английских аббревиатур, которые должен знать каждый начинающий веб разработчик

21.08.2020 12:12:17 | Автор: admin


Аве, Кодер!

Веб разработка, с ее сопутствующими практиками и инструментами переполнена таким количеством жаргонизмов и аббревиатур, что порою теряются не только начинающие, но и бывалые разработчики.
Я взял 30 таких аббревиатур и собираюсь рассказать, что они обозначают.

API (Application Programming Interface)


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

Мы можем выбирать из множества веб-API, например социальные сети и технологические сайты, такие как Facebook, Twitter и Google, также публикующие свои собственные API-интерфейсы.

LAMP


Linux, Apache, MySQL, PHP / Python / Perl: популярный веб-стек для создания динамических веб-сайтов.

Стек LAMP состоит из Linux в качестве операционной системы, Apache в качестве веб-сервера, MySQL в качестве программного обеспечения для управления базами данных и PHP, Perl или Python в качестве языка сценариев. Вариант Windows называется WAMP, а вариант OS X MAMP.

DOM (Document Object Model)


Объектная модель документа: API для документов HTML и XML, используемый браузерами для визуализации этих документов.

DOM определяет логическую структуру документа и представляет его в виде дерева узлов, в котором узлы являются объектами, представляющими разные части документа. Узлы могут быть созданы, изменены и удалены.

MVC


Model-View-Controller: архитектурный шаблон, используемый в объектно-ориентированном программировании.

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

FOSS (Free and Open-Source Software)


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

Иногда также упоминается абревиатура FLOSS Free Libre Open Source Software суть есть та же самая, но FLOSS и FOSS это какбэ два не всегда любящих друг друга лагеря, которые по разному видят то, как этот софт должен быть free.

OATH (Open Authentication)


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

OAuth часто используется как метод, позволяющий пользователям входить на сайт с помощью сторонних сервисов, таких как Facebook, Twitter или Google, что устраняет барьер при регистрации.

ARIA (Accessible Rich Internet Applications)


Или Доступные многофункциональные интернет-приложения: иногда также обозначаются как WAI-ARIA.

Спецификация ARIA представляет из себя Веб стандарты, опубликованные W3C консорциумом и определяет различные методологии интерфейса, которые делают веб-контент доступным для людей с ограниченными возможностями и, которые имеют доступ к Интернету с помощью вспомогательных технологий (так называемые, assistive technologies), например, таких, как программы чтения с экрана.

OOP (Object Oriented Programming)


Объектно-ориентированное программирование: парадигма программирования.

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

ECMAScript


(Сокращенно ES, а полностью European Computer Manufacturers Association Script)
Спецификация скриптового языка, на котором основан синтаксис JavaScript наряду с JScript и ActionScript.

ECMAScript получил свое название от Европейской ассоциации производителей компьютеров- организации, которая его стандартизировала.

REST (Representational State Transfer)


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

CSSOM (Cascading Style Sheets Object Model)


Дословный перевод объектная модель каскадных таблиц стилей: набор API, используемых браузерами для правильной визуализации стилей CSS на веб-странице.

CSSOM представляет все стили CSS (селекторы и их свойства) на веб-странице в виде карты узлов. CSSOM имеет структуру дерева, аналогичную DOM, но это своя уже отдельная модель данных.

WYSIWYG (What You See Is What You Get)


То, что вы видите- это то, что вы получаете: тип редактора контента, который позволяет пользователям редактировать текст, изображения и другие типы контента без написания какой-либо разметки.

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

AMP (Accelerated Mobile Pages)


Или Ускоренные мобильные страницы: мобильный веб-стандарт, инициированный Google с целью ускорения работы мобильных сайтов.

AMP ограничивает то, как мы можем использовать HTML, CSS и JavaScript для повышения производительности и предоставляет нам компоненты, которые мы можем использовать для загрузки внешних ресурсов и запуска сценариев через среду выполнения AMP.

SCM (Source Control Management)


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

SCM позволяет отслеживать изменения и предотвращать потерю информации. Самыми популярными системами SCM являются Git и SVN.

FTU (First Time Use)


Первое использование: пользователь впервые загружает программное обеспечение после установки и первый опыт его использования.

FTU является важной частью процесса принятия приложения, в широком смысле этого слова. Показатели удержания пользователей могут быть улучшены, если пользовательские настройки правильно спроектированы. Во время FTU мы можем показать как работает приложение, или заставить пользователей устанавливать важные параметры (часовой пояс, язык, настройки и т. д.).

REGEX (Regular Expressions)


Регулярное выражение: текстовый шаблон, используемый для сопоставления комбинаций символов в разных строках.

Regex позволяет легко искать определенные последовательности символов в тексте и проверять пользовательский ввод. Regex является частью многих популярных языков программирования, таких как JavaScript, PHP, Python, Ruby, Java и другие.

IIFE (Immediately Invoked Function Expression)


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

IIFE это выражение функции, которое выполняется сразу после его оценки. Его можно использовать для хранения кода, который должен быть выполнен только один раз, для пространства имен и создания закрытых переменных и замыканий.

IIFE использует следующий синтаксис:

(function(){    // code}());

SMACSS (Cascading Style Sheets Object Model)


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

SMACSS определяет 5 типов правил стиля (основа, макет, модуль, состояние, тема) и идентифицирует их с разными префиксами селектора.

ITCSS (Inverted Triangle Cascading Style Sheets)


Модель перевернутый треугольник для каскадных таблиц стилей. (Каскадные таблицы стилей с перевернутым треугольником): масштабируемая архитектура CSS для повторно используемого кода CSS.

ITCSS разделяет свойства CSS на уровни, в зависимости от их специфики и важности. Уровни представлены в виде перевернутого треугольника, в котором специфичность увеличивается от плоской вершины до кончика внизу.

MEAN


MongoDB, Express.js, Angular, Node.js: веб-стек только для JavaScript для создания динамических веб-сайтов и веб-приложений.

Стек MEAN состоит из базы данных NoSQL MongoDB, инфраструктуры веб-приложений Express.js, инфраструктуры веб-интерфейса Angular.js и среды выполнения Node JavaScript и работает в любой операционной системе.

GUI (Graphical User Interface)


Графический интерфейс пользователя: тип интерфейса пользователя, в противоположность командно-управляемым интерфейсам.

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

LTR / RTL


Left to Right / Right to Left: термины, используемые в интернационализации.

LTR и RTL это языковые свойства пользовательского интерфейса языка или страны. LTR означает слева направо, RTL означает справа налево. Они указывают направление текста.

Большинство языков являются LTR, и интерфейсы обычно предназначены для них, но вы можете легко добавить поддержку RTL для большинства CMS, таких как WordPress, с помощью файла rtl.css.

IDE (Integrated Development Environment)


Интегрированная среда разработки: программное приложение, которое предоставляет нам среду программирования, объединяющую различные инструменты, необходимые для разработки и тестирования, такие как редактор исходного кода, инструменты автоматизации сборки, компилятор или интерпретатор и отладчик. Xcode, Eclipse и Visual Studio являются примерами IDE.

JSON


JavaScript Object Notation: независимый от языка, понятный человеку формат данных для обмена данными.

JSON может хранить объекты, как коллекции пар имя-значение, а массивы как упорядоченные коллекции значений. Его синтаксис похож на JavaScript, поэтому он является наиболее распространенным форматом данных в приложениях на основе JavaScript.

CTA (Call To Action)


Призыв к действию: маркетинговый термин, часто используемый в веб-дизайне.

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

BEM (Block, Element, Modifier)


Или Блок, Элемент, Модификатор: соглашение об именах для написания читаемых, согласованных и поддерживаемых классов CSS.

Используя методологию BEM, мы создаем классы, которые на протяжении всего проекта, следуют синтаксису вида: (block__element--modifier) блок-элемент модификатор.

Блоки это названия автономных объектов, таких как меню или кнопка.

Элементы это разные части или функциональные возможности блоков, такие как успех или предупреждение.

Модификаторы меняют стиль блоков, таких как большие или маленькие. Например, .button__alert large будет правильным именем класса BEM.

CDN (Content Delivery Network)


Сеть доставки контента: сеть распределенных серверов, которые хранят дубликаты веб-контента.

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

ACSS (Atomic Cascading Style Sheets)


Или Атомарные каскадные таблицы стилей: методология написания CSS, разработанная Yahoo.

ACSS основан на многоразовых одноцелевых (атомарных) классах и коротких предсказуемых именах классов, которые позволяют напрямую стилизовать HTML.

CMS (Content Management System)


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

Большинство CMS используются для веб-публикации, такие как WordPress, Drupal и Joomla. CMS отделяют контент от представления и функционала, поэтому позволяют управлять веб-контентом без как-таковых знаний кодинга.

CRUD (Create, Read, Update, Delete)


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

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

Java Core для самых маленьких. Часть 1. Подготовка и первая программа

11.02.2021 22:07:58 | Автор: admin

Вступление. Краткая история и особенности языка.

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

Начало разработки языка было положено еще в 1991 году компанией Sun Microsystems, Inc. Вначале язык был назван Oak (Дуб), но в 1995 он был переименован в Java. Публично заявили о создании языка в 1995 году. Причиной создания была потребность в независящем от платформы и архитектуры процессора языке, который можно было бы использовать для написания программ для бытовой электротехники. Но поскольку в таких устройствах применялись различные процессоры, то использование популярных на то время языков С/С++ и прочих было затруднено, поскольку написанные на них программы должны компилироваться отдельно для конкретной платформы.

Особенностью Java, которая решила эту проблему, стало то, что компилятор Java выдает не машинный исполняемый код, а байт-код - оптимизированный набор инструкций, которые выполняются в так называемой виртуальной машин Java (JVM - Java Virtual Machine). А на соответствующую платформу предварительно устанавливается JVM с необходимой реализацией, способная правильно интерпретировать один и тот же байт-код. У такого подхода есть и слабые стороны, такие программы выполняются медленнее, чем если бы они были скомпилированы в исполняемый код.

Установка программного обеспечения - JDK

В первую очередь, нам нужно установить на компьютер так называемую JDK (Java Development Kit) - это установочный комплект разработчика, который содержит в себе компилятор для этого языка и стандартные библиотеки, а виртуальную машинуJava (JVM) для вашей ОС.

Для того чтобы скачать и установить JDK открываем браузер, и в строке поиска Google вводим download JDK или переходим по этой ссылке.

Скролим ниже и находим таблицу с вариантами скачивания JDK. В зависимости от нашей операционной системы выбираем файл для скачивания.

Процесс установки для ОС Windows имеет несколько этапов. Не стоит пугаться, все очень просто и делается в несколько кликов. Вот здесь подробно описан процесс установки. Самое важное для пользователей Windows это добавить системную переменную JAVA_HOME. В этой же статье достаточно подробно расписано как это сделать (есть даже картинки).

Для пользователей MacOS также стоит добавить переменную JAVA_HOME. Делается это следующим образом. После установки .dmg файла JDK переходим в корневую папку текущего пользователя и находим файл .bash_profile. Если у вас уже стоит zsh то ищем файл .zshenv. Открываем этот файл на редактирование и добавляем следующие строки:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Homeexport PATH=${PATH}:${JAVA_HOME}

Здесь обратите внимание на версию JDK указанную в пути - jdk1.8.0_271.jdk. Могу предположить, что у вас она будет отличаться, поэтому пройдите по указанному пути и укажите свою версию. Сохраняем изменения и закрываем файл, он нам больше не понадобится.

Теперь важно проверить правильность установки JDK. Для этого открываем командную строку, в случае работы на Windows, или терминал для MacOS. Вводим следующую команду: java -version Если вы все сделали правильно, вы увидите версию установленного JDK. В ином случае вы, скорее всего, допустили где-то ошибку. Советую внимательно пройтись по всем этапам установки.

Установка IDE

Теперь нам нужно установить среду разработки, она же IDE (Integrated development environment). Что собой представляет среда разработки? На самом деле она выглядит как текстовый редактор, в котором мы можем вводить и редактировать текст. Но помимо этого, этот текстовый редактор умеет делать проверку синтаксиса языка на котором вы пишете. Делается это для того чтобы на раннем этапе подсказать вам о том, что вы допустили ошибку в своем коде.

Также среда разработки содержит в себе компилятор. Компилятор - это специальный инструмент, который будет превращать код, который вы пишете, в машинный код или близкий к машинному коду.

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

Для начала нам нужно выбрать и среду разработки. Их довольно таки много, и самыми популярными из них являются: IntelliJ IDEA, NetBeans, Eclipse. Для себя я выбираю IntelliJ IDEA. Она является самой удобной на мой взгляд, и хоть она и платная, на официальном сайте можно найти бесплатную версию которая называется Community. Этой версии будет вполне достаточно для изучения основ Java. Вообщем будем работать в IntelliJ IDEA.

Итак, открываем браузер, в поисковой строке вводим "Download IntelliJ IDEA Community" или переходим по этой ссылке. Выбираем версию ОС и качаем версию Community.

В установке IntelliJ IDEA нет ничего военного. На крайний случай на ютубе есть множество видео о том, как установить эту программу.

Первая программа

Теперь мы готовы создать нашу первую программу. В окошке запустившийся IDE нажимаем New Project.

В новом окошке в левой панели выбираем Java.

Обратите внимание! В верхнем окошке, справа, возле надписи "Project SDK:" должна находится версия Java, которую вы установили вместе с JDK. Если там пусто, то вам нужно будет указать путь к вашему JDK вручную. Для этого в выпадающем списке нажмите "Add JDK..." и укажите путь к вашему JDK, который был предварительно установлен.

Теперь можем нажать на кнопку Next. В следующем окошке, вверху, поставьте галочку Create project from template и выберите Command Line App. И снова нажимаем Next.

Дальше нам нужно указать имя программы. У меня это будет Hello World, желательно чтобы имя проекта было введено латиницей, и на английском языке.

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

После указываем путь к проекту программы.

Далее, нам нужно указать базовый пакет нашей программы. О пакетах я расскажу вам позже, обычно компании используют свое имя Интернет-домена в обратном порядке, но вы можете написать, например, свои имя и фамилию через точку в нижнем регистре (маленькими буквами), тоже латиницей. Я же использую псевдоним. Когда все поля будут заполнены - нажимаем Finish.

После этого вы увидите главное окно IDE, в котором уже будет создана ваша первая, почти готовая консольная программа.

Это окно, то что вы будете видеть 80-90%, а иногда и 100% времени, работая программистом.

Для того чтобы закончить ваше первое приложение, останется добавить строчку кода System.out.print("Hello world!"); как показано на скриншоте.

Чтобы скомпилировать и запустить на выполнение вашу программу, вам нужно нажать кнопочку с зеленым треугольничком на верхней панели справа, или в меню найти пункт Run -> Run Main. И внизу на нижней панели, под окном редактора, в консоли, вы увидите результат выполнения вашей программы. Вы увидите надпись Hello World! Поздравляю, вы написали свою первую программу на Java.

Разбираем первую программу

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

Пройдемся по порядку:

В начале мы видим package com.zephyr.ventum; - это объявление пакета, и это постоянный атрибут файлов с исходным кодом в Java. Простыми словами, это локация вашего файла в проекте и любой .java файл должен начинаться с подобной строки.

Ниже, public class Main { - это стандартное объявление класса в Java, где public - это модификатор доступа который дает программисту возможность управлять видимостью членов класса, class - является ключевым словом объявляющим класс, Main - это имя класса. Все определение класса и его членов должно располагаться между фигурными скобками { }. Классы мы рассмотрим немного позже, только скажу что в Java все действия программы выполняются только в пределах класса.

Ключевое слово - это слово зарезервированное языком программирования. Например, package - это тоже ключевое слово.

Еще ниже, public static void main(String[] args) { - эта строка является объявлением метода main. Метод (или часто говорят функция) main это точка входа в любой java-программер. Именно отсюда начинается выполнение вашего кода. В проекте может быть несколько методов main, но мы должны выбрать какой-то один для запуска нашей программы. В следующих статьях мы еще вернемся к этому. Сейчас же у нас только один метод main.

Фигурные скобки {} у метода main обозначаю начало и конец тела метода, весь код метода должен располагаться между этими скобками. Аналогичные скобки есть и у класса Main.

Следующая строка является // write your code here однострочным комментарием.

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

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

/* write  your  code here */

Мы просто располагаем несколько строк между символами /* и */

System.out.print("Hello world!"); - строка которая находится внутри метода main является командой, которая выводит в консоль строку "Hello world!"

Обратите внимание что в конце стоит точка с запятой, в языке Java команды должны заканчиваться точкой с запятой.

Затем мы закрываем тело нашего метода main } а также закрываем класс Main }.

На этом статья подходит к концу. Автором конкретно этого материала является Егор и все уменьшительно ласкательные формы слов сохранились в первозданном виде.

В следующей статье мы поговорим о типах данных в Java.

Подробнее..

Java Core для самых маленьких. Часть 2. Типы данных

15.02.2021 14:04:42 | Автор: admin

Вступление

В этой статье мы не будем использовать ранее установленную IDE и JDK. Однако не беспокойтесь, ваш труд не был напрасным. Уже в следующей статье мы будет изучать переменные в Java и активно кодить в IDEA. Эта же статья является обязательным этапом. И в начале вашего обучения вы, возможно, будете не раз к ней возвращаться.

1998 - пин-код от моей кредитки является ничем иным как числом. По-крайней мере для нас - для людей. 36,5 - температура, которую показывают все термометры в разных ТРЦ. Для нас это дробное число или число с плавающей запятой. "Java Core для самых маленьких" - а это название данной серии статей, и мы воспринимает это как текст. Так к чему же я веду. А к тому, что Джаве (так правильно произносить, на тот случай если кто-то произносит "ява"), как и человеку, нужно понимать с чем она имеет дело. С каким типом данных предстоит работать.

Фанаты матрицы и, надеюсь, остальные читатели знают, что на низком уровне, вся информация в ЭВМ представлена в виде набора нулей и единиц. А вот у человеков, на более высоком уровне, есть высокоуровневые языки программирования. Они не требуют работы с нулями и единицами, предоставляя возможность писать код понятный для людей. Одним из таких языков программирование и является Java. Мало того, Java - это строго-типизированный язык программирования. А еще бывают языки с динамической типизацией данных (например Java Script). Но мы здесь учим нормальный язык программирования, поэтому не будем отвлекаться.

Что для нас означает строгая типизация? Это значит, что все данные и каждое выражение имеет конкретный тип, который строго определен. А также то, что все операции по передаче данных будут проверяться на соответствие типов. Поэтому давайте поскорее узнаем какие типы данных представлены в Java!

Примитивы

В языке Java существует 8, оскорбленных сообществом, примитивных типов данных. Их также называют простыми. И вот какие они бывают:

  • Целые числа со знаком: byte, short, int, long;

  • Числа с плавающей точкой: float, double;

  • Символы: char;

  • Логические значения: boolean.

В дальнейшем комбинируя эти самые примитивы мы сможем получать более сложные структуры. Но об этом нам еще рано беспокоиться. Сейчас же рассмотрим каждый из примитивов подробнее.

Тип byte

Является наименьшим из целочисленных. 8-разрядный тип данных c диапазоном значений от -2^7 до 2^7-1. Или простыми словами может хранить значения от -128 до 128. Используется для работы с потоками ввода-вывода данных, эта тема будет рассмотрена позже.

Тип short

16-разрядный тип данных в диапазоне от -2^15 до 2^15-1. Может хранить значения от -32768 до 32767. Самый редко применяемый тип данных.

Тип int

Наиболее часто употребляемый тип данных. Содержит 32 разряда и помещает числа в диапазоне от -2^31 до 2^31-1. Другими словами может хранить значения от -2147483648 до 2147483647.

Тип long

64-разрядный целочисленный тип данных с диапазоном от -2^63 до 2^63-1. Может хранить значения от -9223372036854775808 до 9223372036854775807. Удобен при работе с большими целыми числами.

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

Тип float

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

Тип double

На хранение требуется 64 бита. Рационально пользоваться double когда нужно сохранить точность многократно повторяющихся вычислений или манипулировать большими числами.

Тип char

16-разрядный тип данных в диапазоне от 0 до 2^16. Хранит значения от 0 до 65536. Этот тип может хранить в себе полный набор международных символов на всех известных языках мира (кодировка Unicode). То есть по сути каждый символ представляет из себя какое-то число. А тип данных char позволяет понять, что это число является символом.

Тип boolean

Может принимать только 2 значения true или false. Употребляется в условных выражениях, к примеру 1 > 10 вернет false, а 1 < 10 - true.

На этом примитивные типы данных в Java закончились. В следующей статье мы будем объявлять переменные конкретного типа данных. Поговорим о том, что такое литералы. А еще узнаем, что такое приведение типов данных. Вообщем следующая статья будет очень насыщенной и познавательной!

Подробнее..

Из песочницы 9 ключевых алгоритмов машинного обучения простым языком

03.07.2020 20:16:17 | Автор: admin
Привет, Хабр! Представляю вашему вниманию перевод статьи 9 Key Machine Learning Algorithms Explained in Plain English автора Nick McCullum.

Машинное обучение (МО) уже меняет мир. Google использует МО предлагая и показывая ответы на поисковые запросы пользователей. Netflix использует его, чтобы рекомендовать вам фильмы на вечер. А Facebook использует его, чтобы предложить вам новых друзей, которых вы можете знать.

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

Эта статья познакомит вас с фундаментальными концепциями в области машинного обучения. А конкретнее, мы обсудим основные концепции 9ти самых важных алгоритмов МО на сегодняшний день.

Система рекомендаций(Recommendation system)


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

Но не беспокойтесь scikit-learn библиотека Python позволяет довольно просто построить СР. Так что вам не потребуется таких уж глубоких познаний в линейной алгебре, чтобы построить рабочую СР.

Как работает СР?


Существует 2 основных типа система рекомендаций:

  • Основанная на контенте(Content-based)
  • Коллаборативная фильтрация(Collaborative filtering)

Основанная на контенте система дает рекомендации, которые базируются на схожести элементов, уже использованных вами. Эти системы ведут себя абсолютно так, как вы ожидаете СР будет себя вести.

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

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

Коллаборативная фильтрация СР также обладает уникальной особенностью, которой нет в основанной на контенте ситстеме. А именно, у них есть способность обучаться фичам самостоятельно.

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

Существует 2 подкатегории коллаборативной фильтрации:

  • Основанная на модели
  • Основанная на соседстве

Хорошая новость: вам не обязательно знать разницу в этих двух типах коллаборативной фильтрации СР, чтобы быть успешным в МО. Достаточно просто знать, что существует несколько типов.

Подведем итог


Вот краткое резюме того, что мы узнали о системе рекомендаций в данной статье:

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

Линейная регрессия (Linear Regression)


Линейная регрессия используется для предсказаний некоторого значения y основываясь на некотором множестве значений x.

История линейной регрессии


Линейная регрессия(ЛР) была изобретена в 1800 году Френсисом Гальтоном. Гальтон был ученым, изучающим связь между родителями и детьми. А конкретнее, Гальтон исследовал связь между ростом отцов и ростом их сыновей. Первым открытием Гальтона стал тот факт, что рост сыновей, как правило, был приблизительно таким же как рост их отцов. Что не удивительно.

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

Гальтон даль этому феномену название регрессия. В частности, он сказал: " Рост сына имеет тенденцию к регрессии(или к смещению в направлении) среднего роста".

Это привело к целой области в статистике и машинном обучении под названием регрессия.

Математика линейной регрессии


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

Типичный пример такого подхода метод наименьших квадратов линейной регрессии, с помощью которого рассчитывают близость линии в направлении верх-низ.

Пример для иллюстрации:



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

Логистическая регрессия (Logistic Regression)


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

Что такое логистическая регрессия?


Логистическая регрессия это модель машинного обучения, использующаяся для решения задач классификации.

Ниже представлено несколько примеров классификационных задач МО:

  • Спам электронной почты(спам или не спам?)
  • Претензия по страховке автомобиля (выплата компенсации или починка?)
  • Диагностика болезней

Каждая из этих задач имеет четко 2 категории, что делает их примерами задач двоичной классификации.

Логистическая регрессия хорошо подходит для решения задач двоичной классификации мы просто назначаем разным категориям значения 0 и 1 соответственно.

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

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



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

Вот почему логистическая регрессионная модель полезна. У нее есть изгиб к линии лучшего соответсвия, что делает ее(модель) гораздо более подходящей для предсказаний качественных(категорийных) данных.

Вот пример, который иллюстрирует сравнение линейной и логистической регрессионых моделей на одних и техже данных:



Сигмоида (The Sigmoid Function)


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

Для вас не обязательно досконально запоминать сигмоиду, чтобы преуспеть в МО. Но все-таки иметь некоторое представление об этой функции будет полезно.

Формула сигмоиды:



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

Использование логистической регрессионной модели для предсказаний


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

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

Использование матрицы ошибок для измерения эффективности логистической регрессии


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

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



В этой таблице TN означает истинно отрицательно, FN ложно отрицательно, FP ложно положительно, TP истинно положительно.

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

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

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

Подведем итог


В этом разделе у вас было первое знакомство с моделью МО логистической регрессией.
Вот краткое содержание того, что вы узнали о логистической регрессии:

  • Типы задач классификации, которые подходят для решения с помощью логистической регрессии
  • Логистическая функция (сигмоида) всегда дает значение от 0 до 1
  • Как использовать точки отсечения для предсказания с помощью модели логистической регрессии
  • Почему матрица ошибок полезна для измерения эффективности модели логистической регрессии

Алгоритм k-ближайших соседей (K-Nearest Neighbors)


Алгоритм k-ближайших соседей может помочь решить задачу классификации, в случае, когда категорий больше, чем 2.

Что из себя представляет алгоритм k-ближайших соседей?


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

Представьте, что у вас есть данные по высоте и весу футболистов и баскетболистов. Алгоритм k-ближайших соседей может быть использован для предсказания является ли новый игрок футболистом или баскетболистом. Чтобы это сделать, алгоритм определяет К точек данных, ближайших к объекту исследования.

Данное изображение демонстрирует этот принцип с параметром К = 3:



На этом изображении футболисты изображены голубыми отметками, а баскетболисты оранжевыми. Точка, которую мы пытаемся классифицировать, покрашена в зеленый цвет. Так как большинство (2 из 3) ближайших к зеленой точке отметок окрашены в голубой (футбольные игроки), то значит алгоритм К-ближайших соседей предсказывает, что новый игрок тоже окажется футболистом.

Как построить алгоритм К-ближайших соседей


Основные шаги для построения данного алгоритма:

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

Важность переменной К в алгоритме К-ближайших соседей


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

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

Представленная ниже иллюстрация отлично показывает этот эффект:



Плюсы и минусы алгоритма К-ближайших соседей


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

Плюсы:

  • Алгоритм прост и его легко понять
  • Тривиальное обучение модели на новых тренировочных данных
  • Работает с любым количеством категорий в задаче классификации
  • Легко добавить больше данных в множество данных
  • Модель принимает только 2 параметра: К и метрика расстояния, которой вы хотели бы воспользоваться (обычно это Евклидово расстояние)

Минусы:

  • Высокая стоимость вычисления, т.к. вам требуется обработать весь объем данных
  • Работает не так хорошо с категорическими параметрами

Подведем итог


Краткое содержание того, что вы только что узнали о алгоритме К-ближайших соседей:

  • Пример задачи на классификацию(футболисты или баскетболисты), которую может решить алгоритм
  • Как данный алгоритм использует Евклидово расстояние до соседних точек для прогнозирования к какой категории принадлежит новая точка данных
  • Почему значения параметра К важно для прогнозирования
  • Плюсы и минусы использования алгоритма К-ближайших соседей

Дерево решений и Случайный лес (Decision Trees and Random Forests)


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

Что такое древовидный метод?


Перед тем, как мы нырнем в теоретические основы древовидного метода в МО, будет нелишним начать с примера.

Представьте, что вы играете в баскетбол каждый понедельник. Более того, вы всегда приглашаете одного и того же друга пойти поиграть с вами. Иногда друг действительно приходит, иногда нет. Решение приходить или нет зависит от множества факторов: какая погода, температура, ветер и усталость. Вы начинаете замечать эти особенности и отслеживать их вместе с решением вашего друга играть или нет.

Вы можете использовать эти данные для предсказания придет ли ваш друг сегодня или нет. Одна из техник, которой вы можете воспользоваться это дерево решений. Вот как это выглядит:



У каждого дерева решений есть 2 типа элементов:

  • Узлы (Nodes): места, где дерево разделяется в зависимости от значения определенного параметра
  • Грани (Edges): результат разделения, ведущий к следующему узлу

Вы можете видеть, что на схеме есть узлы для прогноза (outlook), влажности (humidity) и ветра
(windy). И также грани для каждого потенциального значения каждого из этих параметров.

Вот еще парочка определений, которые вы должны понимать перед тем, как мы начнем:

  • Корень (Root) узел, с которого начинается разделение дерева
  • Листья (Leaves) заключительные узлы, которые предсказывают финальный результат

Теперь у вас есть базовое понимание что такое дерево решений. Мы рассмотрим как построить такое дерево с нуля в следующем разделе.

Как построить дерево решений с нуля


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

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

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

Выгоды использования случайного леса


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

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

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

Подведем итог


Итак, краткое содержание того, что вы только что узнали о деревьях решений и случайных лесах:

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

Метод опорных векторов(Support Vector Machines)


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

Что такое метод опорных векторов?


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

Как МОВ работает?


Давайте капнем поглубже в то, как действительно работает МОВ.

Нам дан набор тренировочных примеров, какждый из которого промаркирован как принадлежащий к одной из 2х категорий, и с помощью этого набора МОВ строит модель. Эта модель распределяет новые примеры в одну из двух категорий. Это делает МОВ невероятностным двоичным линейным классификатором.

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

Вот пример визуализации, который поможет вам понять интуицию МОВ:



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

Давайте посмотрим следующее визуальное представление МОВ:



На этой диаграмме гиперплоскость обозначена как оптимальная гиперплоскость (optimal hyperplane). Теория метода опорных векторов дает такое определение оптимальной гиперплоскости это гиперплоскость, которая максимизирует поле между двумя ближайшими точками данных из разных категорий.

Как вы видите, граница поля действительно затрагивает 3 точки данных 2 из красной категории и 1 из синей. Эти точки, которые соприкасаются с границей поля, и называются опорными векторами откуда и пошло название.

Подведем итог


Вот краткий очерк того, что вы только что узнали о методе опорных векторов:

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

Метод К-средних (K-Means Clustering)


Метод К-средних это алгоритм машинного обучения без учителя. Это значит, что он принимает непомеченные данные и пытается сгруппировать кластеры подобных наблюдений ваших данных. Метод К-средних крайне полезен для решения реальных прикладных задач. Вот примеры нескольких задач, подходящих для этой модели:

  • Сегментация клиентов для маркетинговых групп
  • Классификация документов
  • Оптимизация маршрутов доставки для таких компаний, как Amazon, UPS или FedEx
  • Выявление и реагирование на криминальные локации в городе
  • Профессиональная спортивная аналитика
  • Прогнозирование и предотвращение киберпреступлений

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

Вот визуальное представление того, как это выглядит на практике:



Мы изучим математическую составляющую метода К-средних вследующем разделе этой статьи.

Как работает метод К-средних?


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

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

  • Вычисление центроида (центр тяжести) каждого кластера взяв средний вектор точек в этом кластере
  • Переотнести каждую точку данных к кластеру, центроид которого ближе всего к точке

Выбор подходящего значения К в методе К-средних


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

Для использования этого метода, первое, что вам необходимо сделать, это вычислить сумму квадратов отклонений(sum of squared errors) СКО для вашего алгоритма для группы значений К. СКО в методе К-средних определена как сумма квадратов расстояний между каждой точкой данных в кластере и центром тяжести этого кластера.

В качестве примера этого шага, вы можете вычислить СКО для значений К 2, 4, 6, 8 и 10. Далее вы захотите сгенерировать график СКО и этих значений К. Вы увидите, что отклонение уменьшается с увеличением значения К.

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

Как пример, вот график СКО относительно К. В этом случае, метод локтя предложит использовать значение К примерно равное 6.



Важно, что К=6 просто оценка приемлемого значения К. Не существует лучшего значения К в методе К-средних. Как и многие вещи в области МО, это очень зависящее от ситуации решение.

Подведем итог


Вот краткий очерк того, что вы только что узнали в этом разделе:

  • Примеры задач МО без учителя, которые возможно решить методом К-средних
  • Базовые принципы метода К-средних
  • Как работает метод К-средних
  • Как использовать метод локтя для выбора подходящего значения параметра К в данном алгоритме

Метод главных компонент (Principal Component Analysis)


Метод главных компонент используется для преобразования набора данных c множеством параметров в новый набор данных с меньшим количеством параметров и каждый новый параметр этого набора данных это линейная комбинация раннее существующих параметров. Эти преобразованные данные стремятся обосновать большую часть дисперсии оригинального набора данных с гораздо большей простотой.

Что такое метод главных компонентов?


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

На основании этого описания вы можете подумать, что МГК очень схож с линейной регрессией. Но это не так. На самом деле, эти 2 техники имеют несколько важных отличий.

Различия линейной регрессии и МГК


Линейная регрессия определяет линию наилучшего соответствия через набор данных. Метод главных компонентов определяет несколько ортогональных линий наилучшего соответствия для набора данных.

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

Взгляните на метки осей на этом изображении. Главный компонент оси х объясняет 73% дисперсии в этом наборе данных. Главный компонент оси у объясняет около 23% дисперсии набора данных.

Это означает, что 4% дисперсии остается необъясненными. Вы можете уменьшить это число добавляя больше главных компонент в ваш анализ.

Подведем итог


Краткое содержание того, что вы только что узнали о методе главных компонент:

  • МГК пытается найти ортогональные факторы, которые определяют изменчивость в наборе данных
  • Разницу между линейной регрессией и МГК
  • Как выглядит ортогональные главные компоненты, визуализированные в наборе данных
  • Что добавление дополнительных главных компонент может помочь объяснить дисперсию более точно в наборе данных
Подробнее..

Эффект дождя. Частицы в Unity 3D

31.01.2021 22:19:51 | Автор: admin

Учебные материалы для школы программирования. Часть9

Spoiler

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

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

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

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

Перейдем от слов к делу.

Порядок выполнения

На занятии рассмотрим несколько принципов работы с системой частиц, и создадим эффект дождя.

В проект импортируем приложенный ассет. Ассет содержит текстуры, звук и стандартный контроллер игрока.
Создадим простую карту, поставим игрока, и внутри него на высоте около 30 метров создадим три системы частиц.

Назовём их Rain, Dust и Storm.

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

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

Также, стоит поставить галочку ColorOverLifetime и выставить ему такое значение, чтобы дождь плавно исчезал и появлялся.

Создадим и настроим материал в соответствии со скриншотом.

Теперь, настроим рендер. Первое, что нужно сделать это закинуть материал и выставить ему режим отрисовки, как Stratched Billboard с растяжкой по длине 2. Обязательно нужно поменять MaxParticleSize, иначе частицы не будут апскейлиться и будет эффект, как будто они нас облетают.

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

На этот раз, настроек чуть меньше.

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

Самое интересное начинается в материале. Он отличается от остальных, т. к. будет анимирован.

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

Перейдем к грозовым облакам.

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

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

Также, нельзя обойти стороной и Color Over Lifetime. Он придаст нашим облакам эффект грозовых.

Далее, всё по стандарту создаём материал и настраиваем. Использована стандартная текстура дыма из Unity, она отлично пойдёт в качестве облаков.

Рисуем методом Horizontal Billboard, данный тип не поворачивает спрайт на игрока.
На сцену добавляем звук ливня. Звук довольно сильно добавляет эффект, подчёркивая систему частиц.

Дождь готов!

Подробнее..

Жидкий персонаж на Unity 3D

04.02.2021 18:19:53 | Автор: admin

Учебные материалы для школы программирования. Часть11

Spoiler

На сегодняшнем занятии мы познакомимся с физикой на джоинтах движка BOX 2D, на примере создания персонажа, похожего на главного героя Gish или Slime Laboratory.

Порядок выполнения

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

Для начала, создадим новую сцену и поместим в неё 10 сфер с радиусом 0.5, таким образом, чтобы получилась "ромашка":

Установим на каждую сферу Rigidbody2D массой 0.5 и CircleCollider2D. Центральная сфера имеет массу 0.05 и drag = 1 и не имеет коллайдера.

Добавим между соседними сферами по одному SpringJoint2D. Обратите внимание на параметр Frequency - это частота опроса пружины, чем частота выше, тем пружина будет сильнее возвращаться на своё место. Damping - демпфирование пружины (предотвращение колебаний, смягчающий эффект).

Таким образом, мы не даём нашей заготовке разлетаться на куски или, наоборот, излишне сжиматься. Тем не менее, форму она держать не будет.

Для придания формы используем среднюю точку. От каждой, из 9-и окружающих её сфер, создадим ещё по одному джоинту.

Данная конструкция позволяет нам держать форму, при этом, она может сработать некорректно, если при сильном ударе центр вылетит за пределы круга. Более того, данная модель не учитывает поверхностное натяжение между удалёнными точками. Для этого, создадим систему из джоинтов по такому принципу:

Итоговая система джоинтов должна выглядеть примерно так:

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

Теперь придадим "лизуну" очертания. Для этого в ассет приложена 3д-модель со скелетом, каждая из 9-и костей которого управляет по одному вертексу по периметру.
Для неё написан скрипт Goo, который управляет привязкой и отвечает за перемещение нашего главного героя.

Закинем модель на сцену и назначим ей скрипт. Конфигурируем его таким образом. На сцене создадим уровень из спрайтов и назначим ему коллайдеры.

Разберём немного сам скрипт:

using System.Collections;using System.Collections.Generic;using UnityEngine; public class Goo: MonoBehaviour {    public ConstantForce2D ForceObject; // центральная точка как объект приложения силы    public float maxForce = 4f; // сила передвижения publicTransform[] bones; // массив костей    public Transform[] go; // массив сфер    public float sphereRadius; // радиус сферы, можно брать автоматически, но в данном случае выставляем вручную    public Transform center; // центральная точка как трансформ    ConstantForce2D[] frc; // все объекты приложения силы      // Use this for initialization    void Start() {        frc = newConstantForce2D[9]; // инициализируем        // находим все объекты приложения силы        for (int i = 0; i < 9; i++) {             frc[i] =go[i].GetComponent<ConstantForce2D>();        }    }    // Update is called once per frame     void Update() {        for (int i = 0; i < 9; i++) {             // выставляем кости по точкам с небольшим смещение            bones[i].position = go[i].position + (go[i].position - center.position).normalized * sphereRadius / 2f;            // добавляем всем точкам силу по горизонтали            frc[i].force = newVector2(Input.GetAxis("Horizontal") * maxForce, 0f);         }        // и центральной точке тоже        ForceObject.force = newVector2(Input.GetAxis("Horizontal") * maxForce, 0f);        // нажали пробел        if (Input.GetKeyDown(KeyCode.Space)) {            foreach(Transformrig ingo) {                rig.GetComponent<Rigidbody2D>().velocity += new Vector2(0, 6f); // прыжок            }        }    }}

После отключения MeshRenderer у сфер, можно увидеть, что всё адекватно работает. Для полноты картины, фон и камеру прикрепляем к центральному объекту. У риджитбади центрального объекта нужно запретить вращение по Z. Можно добавить, на свое усмотрение, пару глаз.

На серые объекты вешаем скрипт RandomColor и выставим ему палитру.

using System.Collections;using System.Collections.Generic;using UnityEngine; public class RandomColor: MonoBehaviour {    SpriteRenderer rndr;     public Color32[] colors;        // Use this for initialization    void Start() {        rndr = GetComponent<SpriteRenderer>();         rndr.color = colors[Random.Range(0, colors.Length)];    }}

Теперь при старте уровень приобретёт цвет.

На этом, сборка нашего проекта завершена!

Подробнее..

Стики и работа с Event System в Unity 3D

10.02.2021 22:13:33 | Автор: admin

Учебные материалы для школы программирования. Часть12

Предыдущие уроки можно найти здесь:

Этот материал состоит из двух частей:

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

Познакомимся с использованием Event System в разрезе работы с UI и реализации пользовательской обработки реакции на указатель мыши/тачпада.

Далее, перейдем ко второй, где создадим скрипт, реализующий доступ к другим объектам посредством Event System.

По ходу дела, попробуем свои силы в работе со static-переменными для реализации удобной имплементации модулей в проект, и узнаем о глобальных и локальных координатах RectTransform.

Обе части занятия являют собой продолжение работы над проектом "Жидкий персонаж".

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

Порядок выполнения

Создадим новую панель со следующими параметрами:

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

Внутри панели создадим 2 Image согласно иерархии на скриншотах - Joy и Mushroom Joy тело нашего стика, Mushroom его грибок.

Их параметры:

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

Создадим скрипт. Скрипт необходимо закинуть на панель. Его полный листинг выглядит так (если в таком формате совсем неудобно, пишите в комментах - перенаберу исходный код):

Разберём его подробнее
Для начала подключим пространство имён для обработки событий:

using UnityEngine.EventSystems;

За обработку нажатий отвечают методы OnPointerDown и OnPointerUp. Для их работы необходимы следующие интерфейсы: IpointerDownHandler и IpointerUpHandler.

Чтобы работать с информацией о конкретном нажатии (а в случае мультитача данных нажатий может быть несколько) объявляем поле private PointerEventData eventData;

При нажатии на экран вызывается OnPointerDown и складывает информацию о нажатии в eventData.

В дальнейшем это позволяет нам работать с eventData из метода Update().

Для того, чтобы понимать, актульна ли информация о нажатии, введена булева переменная OnScreen. Если мы нажали на экран, то переменная принимает значение true, объект Joy становится в точку нажатия и объекты Joy и Mushroom становятся видимыми.

Метод OnPointerUp отключает видимость Joy и Mushroom и переводит переменную OnScreenв false.

Остальная обработка возникает в Update().
Там мы выставляем Mushroom по глобальной точке нажатия и меряем её локальные координаты.

Принцип такой: нажали, грибок и джой выставились в току нажатия.
Передвинули палец/указатель и грибок сместился относительно джоя. Это смещение мы и берём из локальных координат. Его и используем как результат.

Теперь, в любом скрипте, который используем методы типа GetAxis строку типа Input.GetAxis("Horizontal")меняем наCustomStick.horizontal

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

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

Хочется напомнить, все материалы рассчитаны на использование в составе проекта с главным героем - желе.

Перейдем ко второй части.

Использование своих типов эвентов через код

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

Создадим новый скрипт. Его листинг:

Несмотря на то, что скрипт очень лёгкий, он может многое. Скрипт требует коллайдера в режиме триггера и реагирует на игрока.

Если мы выложим его на пустой объект на сцене, мы можем увидеть привычное окно системы эвентов.

Рассмотрим пару вариантов использования этого скрипта. Вариант первый создание потайной двери-стены, открывающийся ключом. Для этого нам понадобится спрайт стены с обычным коллайдером и спрайт или модель ключа с коллайдером в режиме триггера.
Также можно добавить ещё один пустой объект и закинуть на него звук, создав тем самым AudioSource. Уберём у AudioSource галочку вопроизведения при старте и закинем в него ключ и стены.

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

Это самый простой пример логики. Рассмотрим посложнее.

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

Создать её будет сложнее. Кратко, логику можно описать так: у нас есть стенка, которая включается, чтобы не дать игроку выйти. (изначально она выключена, чтобы игрок вошёл).

Стенку включает триггер, находящийся прямо возле неё. (Тоже изначально выключен)

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

Создадим кнопку. Для этого импортируем приложенное извображение и разрежем на 2 спрайта.

Расположим их в мире в одной точке, зелёный выключим и назовём его "Вкл", Красный назовём "Выкл".

Создадим ещё один пустой объект, закинем на него коллайдер, выставим коллайдеру режим триггера и расположим на кнопке. Настроим следующим образом:

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

Сюда же можно добавить звук нажатия кнопки, закинув его на пустой объект или на сам спрайт зелёной кнопки и оставив галочку Play On Awake.

На этом этапе занятие можно считать завершённым.

Пишите комменты, делитесь полезными ссылками, как можно улучшить проект!

Пожалуйста, поддержите инициативу - нажимайте нравится и поделиться!

Подробнее..

Синтезатор на Unity 3D

09.04.2021 12:18:12 | Автор: admin

Учебные материалы для школы программирования. Часть13

Предыдущие уроки можно найти здесь:

При тематическом планировании уроков, мы сталкиваемся с интересной задачкой: в нашей группе учатся и мальчишки и девчонки. У них разные вкусы, разные любимые герои, жанры. И если все занятия будут на тему гонок или Silent Hill - ряды девочек на ваших занятиях, - поредеют. Эту ситуацию мы решаем двумя способами:

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

  • чередуем и комбинируем. Мы стараемся чередовать "спокойные" и "агрессивные" проекты. Например, в этом месяце мы делаем лабиринт ужасов, но после его защиты - приступаем к созданию острова с лесом и домиком. При комбинировании, мы предлагаем всем ребятам уделить внимание визуальной составляющей (раскрасить, добавить элементов, составить композицию и пр.), и девочки с большим энтузиазмом берутся за такую задачу.

Сегодня мы сделаем проект из категории: спокойный, для девчат. Мальчишкам тоже хорошо заходит - особенно момент, когда в конце урока получается звуковая какофония =)

Рассмотрим следующие темы:

  • выставление вращения объектов в локальной системе координат посредством конверсии из углов Эйлера в кватернионы;

  • события объектов OnMouseEnter и OnMouseExit;

  • метод POW класса Mathf - возведение в степень;

  • парсинг float из имени объекта через системный метод Parse ;

  • стек постэффектов от Unity Technologies;

  • функция движка RequireComponent.

Особое внимание обратим на:

  • изменение скорости воспроизведения и высоты звука через Pitch;

  • использование аудиомикшера и постэффектов на мастер-канале микшера, в частности, реверберации и эмуляции комнаты.

Порядок выполнения

Создаётся новый проект, импортируется приложенный ассет, открывается сцена piano (в проекте заранее заготовлена сцена, ключевыми объектами которой являются клавиши, расположенные на сцене в "Пианино/Клавиши").
Клавиши пронумерованы в соответствии с полутонами, начиная с ноты "до" и заканчивается нотой "фа" следующей октавы, т.е. "до", "до диез", "ре", "ре диез", "ми", "фа" и т.д.

Клавиши расположены с начала октавы в той же последовательности, что и на реальном пианино.

Весь проект умещается в один скрипт. Полный листинг содержит пояснения:

using System.Collections;using System.Collections.Generic;using UnityEngine;using System;[RequireComponent(typeof(AudioSource))] // необходимо для того, чтобы скрипт требовал установленный аудиосорсpublic class Piano : MonoBehaviour {public KeyCode Key; // энумератор для выбора клавиши клавиатуры, на которую реагирует скриптAudioSource src; // Аудиосорс, приват-переменная     void Start () {src = GetComponent<AudioSource>(); // получаем аудиосорс        src.pitch = Mathf.Pow(1.059462f, float.Parse(name) - 1f); // высота звука равна 1.059462f в степени (имя_клавиши - 1).}    void Update () { // Для уменьшения отклика стоит использовать FixedUpdateif (Input.GetKeyDown(Key)) { // если нажали клавишу.playNote(); // играем        }        if (Input.GetKeyUp(Key)) { // если отпустили клавишу.stopNote(); // не играем        }}    private void OnMouseEnter() { // если мышь над коллайдером клавиши        playNote(); // играем}    private void OnMouseExit() { // если мышь вышла из коллайдера клавиши         stopNote(); // не играем}    private void playNote() { // играемtransform.localRotation = Quaternion.Euler(-3, 0, 0); // ставим локальный угол поворота на -3 градуса по Хsrc.Play(); // Включаем звук с начала}    private void stopNote(){ // не играемtransform.localRotation = Quaternion.Euler(0, 0, 0); // ставим локальный угол поворота на 0 градусов по всем осям    src.Stop(); // Останавливаем звук    }}

Особое внимание стоит уделить строке:

src.pitch = Mathf.Pow(1.059462f, float.Parse(name) - 1f);//высота звука равна 1.059462f в степени (имя_клавиши - 1).

Число1.059462высчитано математически и является простой заменой логарифмической функции, делящей одну октаву на 12 полутонов. Таким образом, каждый последующий полутон в 1.059462 раза выше предыдущего по частоте, что при количестве 12 полутонов даёт умножение частоты на 2 с ошибкой в 0.00003 Гц на октаву. С учётом того, что динамический диапазон нашего пианино не превышает полторы октавы, звук практически не искажается.

Тем не менее, звуки пианино плохо ложатся в микс, при отпускании клавиши отсутствует затухание, потому было принято решение немного "размазать" всё реверберацией с небольшой задержкой и эмуляцией большой комнаты, которая добавит "хвостов" затухания резко прерывающимся звукам.

Создана новая группа аудиомикшера, на мастер-канал которой установлена реверберация со следующими параметрами.

А всем аудиосорсам в качестве output установлен мастер-канал аудиомикшера.

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

Далее, немного оформляем сцену и добавляем следующие эффекты:

  • SSAO - подчеркнёт тени между клавишами, добавит глубины картинке.

  • Bloom - высветлит светлые участки ещё сильнее, сделает картинку более приятной на глаз, интенсивность нужно выбрать довольно низкую.

  • Антиалиасинг, чтобы убрать пикселизацию.

  • Винетка, чтобы затенить края, выделив основной объект.

    Можно добавить SSR, для легкого отражения на вертикальных плоскостях, что немного улучшит картинку.

Готово!

Подробнее..

Регдоллы на Unity 3D

16.04.2021 18:11:03 | Автор: admin

Учебные материалы для школы программирования. Часть15

Предыдущие уроки можно найти здесь:

Регдоллы - физика тряпичных кукол, основная задача которых - реалистичное падение тел со скелетом. Регдоллы применяются везде - от шутеров (падающие враги) до гонок. Допустим, в Goat Simulator регдоллы являются важнои частью геимплея.

Goat SimulatorGoat Simulator

В данном занятии рассмотрены следующие аспекты:

  • работа со стандартным генератором регдоллов;

  • понимание скелета гуманоидных моделеи;

  • исправление неверно выставленных коллаидеров на Rigidbidy посредством дополнительных объектов в иерархии.

Порядок выполнения

Создадим новыи проект и импортируем в него приложенныи ассет.
Ассет содержит стандартную юнити-модель робота Каила, модель лестницы и демо-сцену (но вы можете выбрать любую другую "человекоподобную" модель, и самостоятельно разработать дизайн окружения).

Создадим новую сцену, установим на нее плеин или квад в качестве пола. На пол поставим лестницу, на лестницу - модель робота Каила.

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

Перед созданием регдолл-системы необходимо выставить модель в Т-позу. Поворачиваем 2 этих объекта в локальнои системе координат до нужного угла.

должно быть так:

Далее, нажимаем в окне объектов Create->Ragdoll и конфигурируем его следующим образом:

Жмем Create и упираемся в одну проблему. Как можно заметить, модель имеет неверные коллаидеры.

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

После всех этих манипуляции, модель должна падать корректно, а именно, мягко и естественно.

Готово!

Подробнее..

Судно на воздушной подушке на Unity 3D

16.04.2021 18:11:03 | Автор: admin

Учебные материалы для школы программирования. Часть14

Предыдущие уроки можно найти здесь:

Сегодня мы настроены на отдых и развлечения! Поэтому, этот урок будет простой и "короткий". Мы не будем работать с графикой (но вас никто не ограничивает в праве усовершенствовать проект), уделим внимание управлению и работе с физикои, на примере создания судна на воздушнои подушке.

Порядок выполнения

Создадим новыи проект, импортируем в него приложенныи ассет. В данном ассете содержится модели, звук и простая сцена.

Первое, что нам необходимо сделать - это установить на сцену модели карты и СВП, затем создать материал с нулевым трением и назначить его юбке СВП

На само судно устанавливаем Rigidbody со следующими параметрами:

Обратите внимание, что на коллаидерах установлена галочка Convex, а Rigidbody не имеет галочку использования гравитации. Вместо нее используется ConstantForce с довольно большим значением, направленная вниз.

Как видите, на скриншоте уже наложен скрипт. Но до того, как приступать к нему, необходимо установить рулевые лопатки.
Также, на модель в точках установки рулевых лопаток, установлены пустые геим-обджекты с названием Gizmo, в них и уложены сами лопатки.

Скрипт конфигурируется согласно позапрошлому скриншоту. Полныи листинг скрипта выглядит таким образом:

using UnityEngine;using System.Collections; public class Howercraft: MonoBehaviour {    public Rigidbody HowercraftRigidbody; // риджитбади     public Transform CenterOfMass; // центр масс    public float power = 25000; // мощность вперёд/назад    public float torque = 25000; // мощность влево/вправо    float finAngle; // угол отклонения лопаток     float pitch; // питч для звука    public Transform[] Fins; // массив с лопатками    public AudioSource mainEngine; // звук основного двигателя       public AudioSource pushEngine; // звук турбин     // Use this for initialization     void Start() {        HowercraftRigidbody.centerOfMass = CenterOfMass.position - HowercraftRigidbody.position; // устанавливаем центр масс    }     // Update is called once per frame    void Update() {                float inpFB = Input.GetAxis("Vertical"); // ввод вперёд/назад        float inpLR = Input.GetAxis("Horizontal"); // и влево/вправо              Vector3 vely = new Vector3(HowercraftRigidbody.transform.forward.x, 0, HowercraftRigidbody.transform.for ward.z); // находим вектор приложения силы          float gain = Mathf.Clamp01(HowercraftRigidbody.transform.up.y); // если перевёрнуты, силы будут равны нулю             HowercraftRigidbody.AddForce(vely * power * inpFB * gain, ForceMode.Force); // добавляем линейные силы              HowercraftRigidbody.AddRelativeTorque(0, torque * inpLR * inpFB * gain, 0, ForceMode.Force); // и поворот              finAngle = Mathf.Lerp(finAngle, -45 * inpLR, Time.deltaTime / 0.2f); // угол лопаток            foreach(Transform Fin in Fins) {            Fin.localEulerAngles = new Vector3(0, finAngle, 0); // выставляем угол         }        mainEngine.pitch = 0.9f + HowercraftRigidbody.velocity.magnitude / 60f; //высота звука основного двигателя               pitch = Mathf.Lerp(pitch, Mathf.Abs(inpFB) * 1.3f, Time.deltaTime / 0.5f); // высчитываем высоту звука турбины               pushEngine.pitch = 1f + 2f * pitch;        pushEngine.volume = 0.3f + pitch / 3f;    }}

При этом скрипт лучше давать последовательно, сначала физическии движок, потом звуковои.

Готово!

Подробнее..

Игровые механики на уроке геометрии или векторы на Unity 3D

20.04.2021 16:13:49 | Автор: admin

Учебные материалы для школы программирования. Часть16

Предыдущие уроки можно найти здесь:

В этой статье, мы обратим свой взор в прошлое, и вспомним, с чего начиналась детская школа программирования Step to Science. Первоначальная идея проекта состояла в том, чтобы быть не просто кружком технического творчества, а стать для детей ответом на вопрос, "зачем учиться в школе?"

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

С возрастом, перейдя на другую сторону баррикад, я поняла что хочу ребятам объяснить, показать, доказать, что учиться в школе действительно важно! И игровой проект, который мы разберем сегодня - один из цикла занятий по изучению школьных предметов через игры на Unity 3D.

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

Порядок выполнения

На примере создания 2D игры баскетбол, рассмотрим векторы (скорости, сил, локальнои и глобальнои систем координат). Разберем принципы представления систем координат и представления векторов. Также будет затронута работа с LineRenderer и многокамерность.

Поехали!

Создадим новыи проект и импортируем в него приложенныи ассет.
Ассет содержит в себе все ресурсы, необходимые для создания полноценного 2D приложения.

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

Конечно, необходимо выставить правильныи Order in layer у спраитов. Добавим мяч, применим к нему Circle collider и Rigidbody.

Внутри мяча должен находиться пустои объект с Audio Source, настроенным на воспроизведение звука удара.

Чтобы воспроизводить этот звук, напишем простои скрипт, закинем его на мяч и сконфигурируем.

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Ball : MonoBehaviour {    public AudioSource hitSound;    public Rigidbody2D rig;    // Use this for initialization    void Start () {    }    // Update is called once per frame    void FixedUpdate() {    }    private void OnCollisionEnter2D(Collision2D other) {        if (other.relativeVelocity.magnitude > 1f) {            hitSound.Play();            hitSound.volume = Mathf.Clamp01(other.relativeVelocity.magnitude / 10);            rig.velocity *= 0.8f;        }    }}

В скрипте нет автопоиска Rigidbody, так что придется закинуть его руками. Если нажать на Play, наш мяч упадет, издавая звуки. Чтобы мяч отскакивал, создадим физическии материал и закинем его на коллаидер мяча.

Теперь подумаем о том, чтобы мяч показывал свое направление. Для этого создадим скрипт, которыи рисует стрелки: нам понадобятся два пустых объекта с LineRenderer, один в другом.

Создадим материал для стрелки:

И добавим скрипт, которыи будет выставлять вершины LineRenderer'ов, делая из них стрелки:

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Arrow : MonoBehaviour {   public Vector3 showVector;    public LineRenderer lrenderer1;    public LineRenderer lrenderer2;    Transform myTransform;    // Use this for initialization    void Start () {        //lrenderer1 = GetComponent<LineRenderer>();        myTransform = transform;    }   // Update is called once per frame    void Update () {        showVector = new Vector3(showVector.x, showVector.y, 0f);        lrenderer1.SetPosition(0, myTransform.position);        lrenderer1.SetPosition(1, myTransform.position + showVector);          if (showVector.magnitude >= 2f) { // длинная стрелка            lrenderer2.SetPosition(0, myTransform.position + showVector - showVector.normalized);        } else {            lrenderer2.SetPosition(0, myTransform.position + showVector * 0.5f);        }        lrenderer2.SetPosition(1, myTransform.position + showVector);        if (showVector.magnitude < 0.1f) {            lrenderer1.enabled = lrenderer2.enabled = false;        } else {            lrenderer1.enabled = lrenderer2.enabled = true;        }    }}

Закинем скрипт на объект-родитель стрелки и настроим его.

Теперь надо написать скрипт, которыи будет вектор скорости передавать в наш скрипт "показывания" стрелки. Он очень простои:

using System.Collections;using System.Collections.Generic;using UnityEngine;public class VectorVelocity : MonoBehaviour {    public Rigidbody2D rig;    public Arrow arrow;    // Use this for initialization    void Start () {     }    // Update is called once per frame    void Update () {        if (rig.bodyType == RigidbodyType2D.Dynamic) {            arrow.showVector =  rig.velocity / 5f;        }    }}

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

Теперь вектор скорости показывается верно. Вектор скорости уменьшен в 15 раз, чтобы его было хорошо видно. А для того, чтобы было видно траекторию мяча - добавим ему Trail Renderer на любои привязанныи к мячу объект.

Теперь сделаем так, чтобы мяч можно было кидать. Для этого необходимо выставить ему тип Rigidbody как Kinematic и написать небольшои скрипт.

Листинг скрипта:

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.EventSystems;public class Spawner : MonoBehaviour {    public Rigidbody2D ball;    public TrailRenderer tr;    Quaternion oldRotation;    Vector3 oldPosition;    public bool readyToShoot = true;    // Use this for initialization    void Start () {        oldPosition = ball.transform.position;        oldRotation = ball.transform.rotation;    }    // Update is called once per frame    public void Respawn () {        ball.transform.position = oldPosition;        ball.transform.rotation = oldRotation;        ball.velocity = Vector3.zero;        ball.angularVelocity = 0;        ball.bodyType = RigidbodyType2D.Kinematic;        readyToShoot = true;        tr.Clear();    }    public void Shoot(Vector3 speed) {        if (!readyToShoot) {            return;        }        ball.bodyType = RigidbodyType2D.Dynamic;        ball.velocity = speed;        readyToShoot = false;    }}

Скрипт выкладываем на пустои объект в мире и устанавливаем ему наш мяч в качестве риджитбади и его треил.

Этот скрипт сам по себе ничего не делает. Чтобы он работал, необходимо организовать ввод. Создадим UI -> Panel на сцене, выставим панели нулевую альфу и установим на него скрипт TouchPanel.cs , приложенныи в проект.

Внутри панели должен лежать спраит со следующими параметрами (обратите внимание на привязку):

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

Для того, чтобы сделать включение/выключение стрелок, используется скрипт Toggle, которыи реализован через эвент-систему юнити. Его необходимо закинуть на кнопку и сконфигурировать следующим образом.

Готово!

P.S. Делитесь ссылкой на статью с коллегами, друзьями и любопытными учениками. Будет здорово, если вы попробуете провести один из уроков в своей школе или в кружке детского технического творчества, и напишите пару слов обратной связи о том, как прошел урок по Unity 3D. Успехов!

Подробнее..

Бильярд на Unity 3D

31.01.2021 22:19:51 | Автор: admin

Учебные материалы для школы программирования. Часть10

Spoiler

Дорогой читатель! (произносить голосом Николая Дроздова)

Мы на юбилейном, десятом, проекте! Сегодня, стараясь избежать столкновения с полицией нравов, рассмотрим создание игры - бильярд. На этом занятии мы будем работать с системой материалов, освещением, и научимся использовать компоненты и скрипты без программирования.
В этой статье дано описание на примере полностью готового проета, но порядка выполнения работ это не меняет.

Порядок выполнения

Создадим новый 3D-проект, импортируем в него приложенный ассет. Ассет содержит звуки, скрипты и текстуры.

На сцену выставим плейн и зададим ему размер примерно 100х1х100. На плейн установим модель бильярдного стола.

Далее, создадим новый материал, применим ему текстуру ковра, уберём блеск, изменим тайлинг (см. скриншот) и закинем на Plane.

Настроим освещение: перейдем во вкладку Light, уберём скайбокс, и выставим заполняющий цвет потемнее.

Настроим туман, чтобы размыть края поля.

Добавим сверху стола источник света типа Spot и выставим ему мягкие тени.

Создадим новую сферу, добавим к ней Rigidbody и закинем, в поле физического материала коллайдера, материал Rubber.
Добавим скрипт Ball и настроим его.

Чтобы шар не был белым, создадим новый материал и настроим в соответствии со скриншотом.

Чтобы шар отражал мир, надо добавить на сцену новую Reflection Probe и запечь.

Удалим стандартную камеру. Следующим шагом будет добавление своей камеры на сцену. Для этого используем префаб FreeLookCameraRig. Настроим его, чтобы он следил за шаром, добавим скорости линейной и поворота.

Сразу же настроим камеру. Выставим ей очистку экрана цветом, в качестве цвета возьмём чёрный.

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

Для звука ударов шаров служит скрипт ImpactSound. Его необходимо добавить игроку и каждому шарику.

Теперь, необходимо добавить прицел. Создадим UI->Image, привяжем к ценру экрана и закинем в него картинку прицела.

На данном этапе, шар должен свободно кататься по полю по нажатию пробела, бить другие шары и издавать звук удара.
Далее, создадим пустой объект и закинем на него скрипт GameLogic.
Не забудьте создать AudioSource, выставить звук часов и галочки PlayOnAwake и Loop.

Скрипт следит за временем и ловит попавшие в него шары. Для того, чтобы скрипт мог это делать, необходимо выставить ему коллайдер и поставить галочку is Trigger.

Триггер большой, размером 200х1х200 метров, расположен чуть ниже уровня стола, триггер ловит шары и считает их, а в случае попадания шара игрока он перезагружает уровень. Для того, чтобы наш скрипт мог отличать игрока от других шаров, необходимо выставить игроку тег Player.

Скрипт требует двух текстовых полей для отображения времени и количества шаров.
Для начала создадим панель, закинем на неё Event Trigger и настроим на метод Shoot внутри скрипта игрока. Альфу выставим в ноль, чтобы панели не было видно.

Далее, создадим внутри ещё одну панель, привяжем её внизу экрана и создадим внутри два текста:

Настроим скрипт GameLogic, используя эти два текстовых поля. Также, закинем звук попадания в лузу.

Теперь добавим ещё один скрипт - Score.

Как видно, он тоже требует 2 текста. Можно продублировать прошлую панель, привязать её к верху экрана и настроить скрипт на неё.

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

Таже можно добавить максимальный счёт. Создав ещё одно текстовое поле.

Закинем скрипт MaxScore на объект с GameLogic и настроим его на созданное текстовое поле.

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

Подробнее..

Django Rest Framework для начинающих создаём API для чтения данных (часть 2)

15.06.2021 12:07:46 | Автор: admin

В прошлой части мы в общих чертах рассмотрели, как устроен REST API на DRF при работе на чтение. Едва ли не самый сложный для понимания этап сериализация. Вооружившись исходным кодом, полностью разберем этот этап от приема набора записей из модели до их преобразования в список словарей.


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


Код учебного проекта, который используется в этой статье, доступен в репозитории на Гитхабе.



Как создаётся сериалайзер, работающий на чтение


Создание экземпляра сериалайзера мы описывали следующим образом:


# capitals/views.py        serializer_for_queryset = CapitalSerializer(            instance=queryset,  # Передаём набор записей            many=True # Указываем, что на вход подаётся набор записей        )

Благодаря many=True запускается метод many_init класса BaseSerializer.


class BaseSerializer(Field):           def __new__(cls, *args, **kwargs):        if kwargs.pop('many', False):            return cls.many_init(*args, **kwargs)        return super().__new__(cls, *args, **kwargs)

Подробнее о методе many_init:


  • При создании экземпляра сериалайзера он меняет родительский класс. Теперь родителем выступает не CapitalSerializer, а класс DRF для обработки наборов записей restframework.serializers.ListSerializer.
  • Созданный экземпляр сериалайзера наделяется атрибутом child. В него включается дочерний сериалайзер экземпляр класса CapitalSerializer.

 @classmethod    def many_init(cls, *args, **kwargs):        ...        child_serializer = cls(*args, **kwargs)        list_kwargs = {            'child': child_serializer,        }      ...        meta = getattr(cls, 'Meta', None)        list_serializer_class = getattr(meta, 'list_serializer_class',                           ListSerializer)        return list_serializer_class(*args, **list_kwargs)

Экземпляр сериалайзера Описание К какому классу относится
serializer_for_queryset Обрабатывает набор табличных записей ListSerializer класс из модуля restframework.serializers
serializer_for_queryset.child Обрабатывает каждую отдельную запись в наборе CapitalSerializer наш собственный класс, наследует от класса Serializer модуля restframework.serializers

Помимо many=True мы передали значение для атрибута instance (инстанс). В нём набор записей из модели.


Важное замечание: чтобы не запутаться и понимать, когда речь идёт о сериалайзере в целом, а когда о дочернем сериалайзере, далее по тексту мы будем говорить основной сериалайзер (в коде контроллера это serializer_for_queryset) и дочерний сериалайзер (атрибут child основного сериалайзера).


После создания основного сериалайзера мы обращаемся к его атрибуту data:


return Response(serializer_for_queryset.data)

Запускается целый набор операций, каждую из которых подробно рассмотрим далее.


Что под капотом атрибута data основного сериалайзера


Важное замечание: атрибут data есть и у основного, и у дочернего сериалайзеров. Поэтому, чтобы найти подходящий исходный код, нужно помнить: экземпляр основного (serializer_for_queryset) относится к классу ListSerializer.


Исходный код атрибута data:


class ListSerializer(BaseSerializer):    ...    @property    def data(self):        ret = super().data        return ReturnList(ret, serializer=self)

Задействован атрибут data родительского BaseSerializer. Исходный код:


class BaseSerializer(Field):            @property    def data(self):    ...        if not hasattr(self, '_data'):            if self.instance is not None and not getattr(self, '_errors', None):                self._data = self.to_representation(self.instance)            ...        return self._data

Поскольку никакие данные ещё не сгенерированы (нет атрибута _data), ничего не валидируется (нет _errors), но есть инстанс (набор записей для сериализации), запускается метод to_representation, который и обрабатывает набор записей из модели.


Как работает метод to_represantation основного сериалайзера


Возвращаемся в класс ListSerializer.


class ListSerializer(BaseSerializer):           def to_representation(self, data):        """        List of object instances -> List of dicts of primitive datatypes.        """        iterable = data.all() if isinstance(data, models.Manager) else data        return [            self.child.to_representation(item) for item in iterable        ]

Исходный код


Код нехитрый:


  • набор записей из модели (его передавали при создании сериалайзера в аргументе instance) помещается в цикл в качестве единственного аргумента data;
  • в ходе работы цикла каждая запись из набора обрабатывается методом to_representation дочернего сериалайзера (self.child.to_representation(item)). Теперь понятно, зачем нужна конструкция основной дочерний сериалайзер.

Сделаем небольшую остановку:


  • Чтобы обрабатывать не одну запись из БД, а набор, при создании сериалайзера нужно указать many=True.
  • В этом случае мы получим матрёшку основной сериалайзер с дочерним внутри.
  • Задача основного сериалайзера (он относится к классу ListSerializer) запустить цикл, в ходе которого дочерний обработает каждую запись и превратит ее в словарь.

Как работает метод to_representation дочернего сериалайзера


Дочерний сериалайзер экземпляр класса CapitalSerializer наследует от restframework.serializers.Serializer.


class Serializer(BaseSerializer, metaclass=SerializerMetaclass):    def to_representation(self, instance):        """        Object instance -> Dict of primitive datatypes.        """        ret = OrderedDict()        fields = self._readable_fields        for field in fields:            try:                attribute = field.get_attribute(instance)            except SkipField:                continue            check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject)      else attribute            if check_for_none is None:                ret[field.field_name] = None            else:                ret[field.field_name] = field.to_representation(attribute)        return ret

Исходный код


Пойдём по порядку: сначала создаётся пустой OrderedDict, далее идёт обращение к атрибуту _readable_fields.


Откуда берётся _readable_fields? Смотрим исходный код:


class Serializer(BaseSerializer, metaclass=SerializerMetaclass):           @property    def _readable_fields(self):        for field in self.fields.values():            if not field.write_only:                yield field

То есть _readable_fields это генератор, включающий поля дочернего сериалайзера, у которых нет атрибутa write_only со значением True. По умолчанию он False. Если объявить True, поле будет работать только на создание или обновление записи, но будет игнорироваться при её представлении.


В дочернем сериалайзере все поля могут работать на чтение (представление) ограничений write only не установлено. Это значит, что генератор _readable_fields будет включать три поля capital_city, capital_population, author.


Читаем код to_representation далее: генератор _readable_fields помещается в цикл, и у каждого поля вызывается метод get_attribute.


Если посмотреть код to_representation дальше, видно, что у поля вызывается и другой метод to_representation. Это не опечатка: метод to_representation под одним и тем же названием, но с разной логикой:


  • есть у основного сериалайзера в классе ListSerializer;
  • у дочернего сериалайзера в классе Serializer;
  • у каждого поля дочернего сериалайзера в классе соответствующего поля.

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


Как запись из модели обрабатывается методами полей сериалайзера


Метод get_attribute работает с инстансом (instance). Важно не путать этот инстанс с инстансом основного сериалайзера. Инстанс основного сериалайзера это набор записей из модели. Инстанс дочернего сериалайзера каждая конкретная запись.


Вспомним строку из кода to_representation основного сериалайзера:


[self.child.to_representation(item) for item in iterable]

Этот item (отдельная запись из набора) и есть инстанс, с которым работает метод get_attribute конкретного поля.


class Field:       ...    def get_attribute(self, instance):        try:            return get_attribute(instance, self.source_attrs)      ...

Исходный код


Вызывается функция get_attribute, описанная на уровне всего модуля rest_framework.fields. Функция получает на вход запись из модели и значение атрибута поля source_attrs. Это список, который возникает в результате применения метода split (разделитель точка) к строке, которая передавалась в аргументе source при создании поля. Если такой аргумент не передавали, то в качестве source будет взято имя поля.


Если вспомнить, как работает строковый метод split, станет понятно, что если при указании source не применялась точечная нотация, то список всегда будет из одного элемента.


У нас есть такие поля:


class CapitalSerializer(serializers.Serializer):    capital_city = serializers.CharField(max_length=200)    capital_population = serializers.IntegerField()    author = serializers.CharField(source='author.username', max_length=200)

Получается следующая картина:


Поле сериалайзера Значение атрибута source поля Значение source_attrs
capital_city 'capital_city' ['capital_city']
capital_population 'capital_population' ['capital_population']
author 'author.username' ['author', 'username']

Как мы уже указывали, список source_attrs в качестве аргумента attrs передаётся в метод get_attribute rest_framework.fields:


def get_attribute(instance, attrs):    for attr in attrs:        try:            if isinstance(instance, Mapping):                instance = instance[attr]            else:                instance = getattr(instance, attr)        ...    return instance

Для полей capital_city и capital_population цикл for attr in attrs отработает однократно и выполнит инструкцию instance = getattr(instance, attr). Встроенная Python-функция getattr извлекает из объекта записи (instance) значение, присвоенное конкретному атрибуту (attr) этого объекта.
При обработке записей из нашей таблицы рассматриваемую строку исходного кода можно представить примерно так:


instance = getattr(запись_о_конкретной_столице, 'capital_city')

С author.username ситуация интереснее. До значения атрибута username DRF будет добираться так:


  • На первой итерации инстанс это объект записи из модели Capital. Из source_attrs берётся первый элемент author, и значение одноимённого атрибута становится новым инстансом. author объект из модели User, с которой Capital связана через внешний ключ.
  • На следующей итерации из source_attrs берётся второй элемент username. Значение атрибута username будет взято уже от нового инстанса объекта author. Так мы и получаем имя автора.

Извлечённые из объекта табличной записи данные помещаются в упорядоченный словарь ret, но перед этим с ними работает метод to_representation поля сериалайзера:


ret[field.field_name] = field.to_representation(attribute)

Задача метода to_representation представить извлечённые из записи данные в определённом виде. Например, если поле сериалайзера относится к классу CharField, то извлечённые данные будут приведены к строке, а если IntegerField к целому числу.


В нашем случае применение to_representation по сути ничего не даст. Например, из поля табличной записи capital_city будет извлечена строка. Метод to_representation поля CharField к извлечённой строке применит метод str. Очевидно, что строка останется строкой, то есть какого-то реального преобразования не произойдёт. Но если бы из поля табличной записи IntegerField извлекались целые числа и передавались полю класса CharField, то в итоге они превращались бы в строки.


При необходимости создать собственный класс поля сериалайзера, описать специфичную логику и для метода get_attribute, и для метода to_representation, чтобы как угодно преобразовывать поступившие на сериализацию данные. Примеры есть в документации кастомные классы ColorField и ClassNameField.


Суммируем всё, что узнали


Преобразованный набор записей из Django-модели доступен в атрибуте data основного сериалайзера. При обращении к этому атрибуту задействуются следующие методы и атрибуты из-под капота DRF (разумеется, эти методы можно переопределить):


Метод, атрибут, функция Класс, модуль Действие
data serializes.BaseSerializer Запускает метод to_representation основного сериалайзера.
to_representation serializers.ListSerializer Запускает цикл, в ходе которого к каждой записи из набора применяется метод to_representation дочернего сериалайзера.
to_representation serializers.Serializer Сначала создаётся экземпляр упорядоченного словаря, пока он пустой. Далее запускается цикл по всем полям сериалайзера, у которых не выставлено write_only=True.
get_attribute fields (вызывается методом get_attribute класса fields.Field) Функция стыкует поле сериалайзера с полем записи из БД. По умолчанию идет поиск поля, чьё название совпадает с названием поля сериалайзера. Если передавался аргумент source, сопоставление будет идти со значением этого аргумента. Из найденного поля табличной записи извлекается значение текст, числа и т.д.
to_representation fields.КлассПоляКонкретногоТипа Извлечённое значение преобразуется согласно логике рассматриваемого метода. У каждого поля restframework она своя. Можно создать собственный класс поля и наделить его метод to_representation любой нужной логикой.

В словарь заносится пара ключ-значение:


  • ключ название поля сериалайзера;
  • значение данные, возвращённые методом to_representation поля сериалайзера.

Итог: список из OrderedDict в количестве, равном числу переданных и сериализованных записей из модели.




Надеюсь, статья оказалась полезной и позволила дать картину того, как под капотом DRF происходит сериализация данных из БД. Если у вас остались вопросы, задавайте их в комментариях разберёмся вместе.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru