как просмотреть скрипт игры

Взлом веб-приложений и игр | JS Injection

Взлом веб-приложений и игр

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

То, что мы будем делать на самом деле нельзя назвать взломом, так как мы ничего не получаем, кроме игровых преимуществ. Всё, что на самом деле мы делаем называется javascript injection.

Примером для нас послужит игра под названием Kicker King из Telegram. На её примере мы получим 20000 очков с помощью всего 1 броска. Вообще в игре 1 бросок – 1 балл.

Взлом веб-приложений и игр | Практика javascript injection

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

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

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

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

Чтобы осуществить взлом веб-приложений и игр нам нужно найти тот участок кода, который отвечает за обновление игровых баллов, в данном случае. Вообще, в случае с другими веб-приложениями, веб-играми это может быть другой участок кода, например Coins, Radius, Scale, Points или Health. В общем, всё что душе угодно.

Чтобы долго не искать, вводим в поисковике Score и ищем то, что нам нужно.

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

n – количество очков, которые вы хотите получить.

Данная консоль находиться в инспекторе элементов, пункт может называться “просмотреть код элемента”, зависит от браузера.

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

Взлом веб-приложений и игр можно осуществить и подменой js кода, загрузив локально свой файл. Для этого можно воспользоваться плагином, в Google Chrome это Resource Override. Такой метод может пригодиться если на сайте используется функция замыкания. В таком случае через консоль ничего изменить не получиться, в общем окружении переменных js нам ничего не доступно и что-то делать через консоль бесполезно.

Взлом веб-приложений и игр | Выводы

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

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

Сегодня мы поговорили о том, как взломать веб-приложения и игры. Если вам понравилась статья, оставляйте свои комментарии, подписывайтесь на обновления сайта, а также наш Telegram.

Источник

Практическое руководство по взлому (и защите) игр на Unity

Когда речь идёт о программном обеспечении, термин «взлом» зачастую ассоциируют с пиратством и нарушением авторских прав. Данная статья не об этом; напротив, я решительно не одобряю любые действия, которые прямо или косвенно могут навредить другим разработчикам. Тем не менее, эта статья всё же является практическим руководством по взлому. Используя инструменты и методы о которых далее пойдёт речь, вы сможете проверить защиту собственной Unity игры и узнаете, как обезопасить её от взлома и кражи ресурсов.

Введение

В основе взлома лежит знание: необходимо понимать особенности компиляции Unity-проекта, чтобы его взломать. Прочитав статью, вы узнаете, каким образом Unity компилирует ресурсы игры и как извлечь из них исходные материалы: текстуры, шейдеры, 3D-модели и скрипты. Эти навыки будут полезны не только для анализа безопасности проекта, но также для его продвинутой отладки. В связи с закрытостью исходного кода, Unity часто работает как «черный ящик» и порой единственный способ понять, что именно в нём происходит — это изучение скомпилированной версии скриптов. Кроме прочего, декомпиляция чужой игры может стать серьёзным подспорьем в поиске её секретов и «пасхальных яиц». Например, именно таким образом было найдено решение финальной головоломки в игре FEZ.

Находим ресурсы игры

Рассмотрим для примера игру, собранную под ОС Windows и загруженную через Steam. Чтобы добраться до директории, в которой находятся нужные нам ресурсы, откроем окно свойств игры в библиотеке Steam и в закладке «Local files» нажмём «Browse local files…».

Извлекаем текстуры и шейдеры

Графический интерфейс программы не отличается удобством, а также она страдает от нескольких критических багов. Не взирая на это, программа вполне способна извлечь большинство текстур и шейдеров из игры. Полученные в результате текстуры будут иметь формат DDS, который можно «прочитать» с помощью Windows Texture Viewer.

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

Извлекаем 3D-модели

Трёхмерные модели в типовой Unity-сборке «разбросаны» по различным ресурсам, а некоторые из них и вовсе могут генерироваться во время игры. Вместо копания в файлах, существует интересная альтернатива — получить данные о геометрии прямиком из памяти графического ускорителя. Когда игра запущена, вся информация о текстурах и моделях, видимых на экране, находится в памяти видеокарты. С помощью утилиты 3D Ripper DX можно извлечь всю эту информацию и сохранить в формате, понятном 3D-редакторам (например, 3D Studio Max). Учтите, что программа не самая простая в обращении — возможно, придётся обратиться к документации.

Взламываем PlayerPrefs

Защищаем PlayerPrefs

Помешать пользователю редактировать значения в системном реестре мы не в силах. А вот проверить, изменялись ли эти значения без нашего ведома — вполне реально. В этом нам помогут хеш-функции: сравнив контрольные суммы хранимых данных, мы сможем убедиться, что никто и ничто, кроме нашего кода эти данные не изменяло.

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

Затем его можно использовать следующим образом:

Взламываем исходный код

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

Защищаем исходный код

Раз Unity не заботится о сохранности нашего кода — сделаем это сами. Благо, существует утилита, готовая автоматически зашифровать плоды нашего интеллектуального труда: Unity 3D Obfuscator.

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

Взламываем память игры

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

Эта программа пользуется тем фактом, что разработчики игр очень редко защищают значения переменных. Рассмотрим следующий пример: в некой игре у нас есть 100 патронов; используя Cheat Engine, можно выполнить поиск участков памяти, которые хранят значение «100». Затем мы делаем выстрел — запас патронов составляет 99 единиц. Снова сканируем память, но теперь ищем значение «99». После нескольких подобных итераций можно с легкостью обнаружить расположение большинства переменных игры и произвольно их изменять.

Читайте также:  в каких программах делают скрипты

Защищаем память игры

Использовать нашу новую структуру можно следующим образом:

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

Заключение

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

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

Источник

Почему никак не узнать исходный код игры?

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

В обычных приложениях его можно узнать через DotPeek, но в большинстве игр нет.

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

Я понимаю вопросы глупые, но объясните мне пожалуйста как дурачку. Я просто не могу этого понять. =(

(Объясните пожалуйста на простых словах, без википедии, я не понимаю что там написано)

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

Потому куда важнее дать пояснение чем просто посмотреть чужой код

Источник

Игровое программирование. Уроки скриптописания

Для многих начинающих игростроевцев, которые уже собирают свою команду, чтобы слепить на коленке очередной шедевр, программирование часто видится жутким монстром, с которым непонятно как бороться. Вроде и в 3D уже рисовать умеют, и в Photoshop кисточкой сноровисто работают, и другие полезные программы неплохо знают. Но как только дело доходит до кода, начинается паника и неразбериха: “ Кто спрограммирует? Кто напишет заветные строчки? А если и напишет, то как в них потом разобраться?! ”.

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

Установка среды разработки

Классы игры и иерархия

Распаковка игровых скриптов

Настройка среды разработки

В ООП существуют три основных принципа, на которых строятся практически все логические манипуляции с объектами.

Инкапсуляция — объединение внутри объекта данных с методами для их обработки. Например, если рассматривается класс “Лампочка”, то у него должны быть методы “включить свет” и “выключить свет”.

Наследование — создание класса объектов на основе уже существующего класса. При этом создаваемый класс будет не только содержать все данные и методы базового класса, но и обладать своими собственными. Методы базового класса могут быть переопределены. Примеры наследования и переопределения: если класс “Пегас” наследуется от класса “Лошадь”, то у первого появляется новое свойство — “крылья” и соответствующий метод “махать крыльями”. Все остальное у этих двух классов одинаковое. Если мы рассмотрим класс “Русалка”, основанный на классе “Человек”, то в данном случае будет иметь место переопределение свойства “ноги” на “рыбий хвост”, а метод “двигаться” будет вместо движения ног отвечать за перемещение хвоста.

Полиморфизм — что это такое, проще всего рассмотреть на конкретном примере. Рассмотрим два класса объектов — “Пегас” и “Лошадь”. Полиморфизм заключается в том, что мы можем рассматривать любого пегаса как лошадь и, например, у обоих объектов выполнять метод “кушать траву” или “бежать галопом”.

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

Создание проекта

К сожалению, в UDE кнопка “Создать новый проект” отсутствует. Поэтому создаем в корневой папке UT2004 файл CreateNewClass.bat с командами:

echo class %pkg% extends //base class>> %pkg%\Classes\%pkg%.uc

Значение переменной pkg — это имя нашего проекта (в данном случае — Megakiller ). Остальные строки генерируют “пустой” скрипт.

Идея модификации

Перед изучением нижеследующей информации настоятельно рекомендуется изучить текстовый блок “ Анатомия Unreal-класса ”.

Внимание! Читая нижеследующие абзацы, смотрите соответствующие строки в листинге кода, приведенном на отдельной странице (номера строк указаны слева от кода).

Класс оружия

Рис. 1. Диалог создания дерева классов и архивов.

Класс альтернативной стрельбы

Рис. 2. Окна с деревом классов и списком архивов.

В начале файла объявляем несколько новых свойств для объектов класса ( строки 2-5 ): визуальный тип взрыва ( ExplosionClass ), визуальный тип следа от взрыва, например на стенах ( ExplosionDecalClass ). Тип луча при альтернативной стрельбе ( BeamEffectClass ) и радиус поражения при взрыве ( DamageRadius ).

Рис. 3. Диалог создания подкласса.

Классы повреждения

Рис. 4. Окно компиляции.

Класс игрового мутатора

— просто лежать на карте ( строка 15 ). Тут нам помогает класс WeaponPickup ( строка 15 ). Подмена осуществляется функцией ReplaceWith ( строка 19 ).

Рис. 5. Сообщение об ошибке и справка.

Дуэли на «Мегакиллерах» иногда превращают обычный бой в феерическое зрелище.

Чернокожий стрелок пытается безуспешно подстрелить «античную» мадам.

Местные леди способны просто-таки заряжать вас энергией!

Каждый Чебурашка мечтает о большой пушке!

Компиляция и тестирование

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

Принципы объектно-ориентированного программирования

Класс игры имеет унифицированную архитектуру. Структура файла следующая.

— Заголовок, содержащий объявление класса:

class ClassName extends BaseClass config(user); где ClassName — название нашего класса, BaseClass — базовый класс, на основе которого создается новый класс, config(user) — пример параметра в объявлении класса — указывает, что используются конфигурационные параметры из файла User.ini. Все игровые классы имеют в качестве родительского класс Object или любой из его классов-потомков. Лексемы class и extends являются зарезервированными обязательными атрибутами объявления игрового класса. Важно запомнить, что корректным является только тот uc-файл, имя которого совпадает с названием объявленного в нем класса. И в одном uc-файле должен быть описан только один класс.

— Объявления новых переменных (свойств класса) в следующем формате:

PropertyName; или var() SimpleType PropertyName; где PropertyClass — название класса создаваемого свойства, SimpleType — элементарный тип, такой как byte (байтовое значение от 0 до 255), int (знаковый целый тип), bool (логический тип), float (знаковый вещественный тип), string (символьная строка) и т.д. (полный список элементарных типов можно посмотреть в справке UDE), PropertyName — имя нового свойства.

— Объявления новых методов или переопределение унаследованных от базового класса имеют следующий вид:

— Задание параметров (свойств) по умолчанию класса:

defaultproperties где defaultproperties — лексема, указывающая начало блока свойств, Variable1Name — название свойства, представляющего собой некоторый другой объект класса ClassName, содержащегося в u-файле с именем Package. Параметр Variable2Name имеет элементарный тип, поэтому и присваиваемое значение Variable2Value должно иметь тот же тип. Символ «=» означает операцию присвоения значения справа переменной слева. Фигурные скобки обособляют в коде блок присвоений.

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

Источник

Создание браузерных 3d-игр с нуля на чистом html, css и js. Часть 1/2

Современная вычислительная техника позволяет создавать классные компьютерные игры! И сейчас, достаточно популярны игры с 3d-графикой, так как, играя в них, ты окунаешься в вымышленный мир и теряешь всякую связь с реальностью. Развитие интернета и браузерных технологий сделало возможным запускать головоломки и стрелялки в любимом Хроме, Мозилле или еще в чем-то там (про Эксплорер помолчим) в онлайн-режиме, без загрузки. Так вот, здесь я расскажу о том, как создать простую трехмерную браузерную игру.

1. Инструменты для разработки

Я использую для проверки сайтов и игр только 2 браузера: Chrome и Mozilla. Все остальные браузеры (кроме того самого Эксплорера) построены на движке первого, поэтому использовать их я не вижу смысла, ибо результаты точно такие же, как и в Chrome. Для написания кода достаточно Notepad++.

2. Как реализуется трехмерное пространство в html?

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

По умолчанию, дочерний блок имеет координаты (left и top) 0 пикселей по x и 0 пикселей по y. Смещение (translate), также 0 пикселей по всем трем осям. Покажем это на примере, для чего создадим новую папку. В нем создадим файлы index.html, style.css и script.js. Откроем index.html и запишем туда следующее:

В файле style.css зададим стили для элементов “container” и “world”.

Сохраним. Откроем index.html c помощью Chrome, получим:

Попробуем применить translate3d к элементу “world”:

Как вы поняли, я перешел в полноэкранный режим. Теперь зададим смещение по оси Z:
transform:translate3d(200px,100px,-1000px);

Если вы снова откроете html-файл в браузере, то никаких изменений вы не увидите. Чтобы увидеть изменения, нужно задать перспективу для объекта “container”:

Квадрат отдалился от нас. Как работает перспектива в html? Взглянем на картинку:

Теперь повернем “world” вокруг какой-нибудь оси. В сss можно использовать 2 способа вращения. Первый – вращение вокруг осей x,y и z. Для этого используются transform-свойства rotateX(), rotateY() и rotateZ(). Второй – вращение вокруг заданной оси с помощью свойства rotate3d(). Мы будем использовать первый способ, так как он больше подходит для наших задач. Обратите внимание, что оси вращения выходят из центра прямоугольника!

Заметно смещение против часовой стрелки. Если же мы добавим rotateY(), то получим смещение уже по оси Y. Важно заметить, что при вращении блока оси вращения также поворачиваются. Вы также можете поэкспериментировать с различными значениями вращения.
Теперь внутри блока “world” создадим еще один блок, для этого добавим тег в html-файл:

В style.css добавим стили к этому блоку:

То есть, элементы внутри блока “world” будут трансформироваться в составе этого блока. Попробуем повернуть “square1” по оси y, добавив к нему стиль вращения:
transform: rotateY(30deg);

«Где вращение?» — спросите вы? На самом деле именно так выглядит проекция блока “square1” на плоскость, образуемую элементом “world”. Но нам нужна не проекция, а настоящее вращение. Чтобы все элементы внутри “world” стали объемными, необходимо применить к нему свойство transform-style:preserve-3d. После подстановки свойства внутрь списка стилей “world” проверим изменения:

Отлично! Половина блока “square” скрылась за голубым блоком. Чтобы его полностью показать, уберем цвет блока “world”, а именно, удалим строку background-color:#C0FFFF; Если мы добавим еще прямоугольников внутрь блока “world”, то мы можем создать трехмерный мир. Сейчас же уберем смещение мира “world”, удалив строку со свойством transform в стилях для этого элемента.

3. Создаем движение в трехмерном мире

Для того, чтобы пользователь мог по этому миру передвигаться, нужно задать обработчики нажатия клавиш и перемещения мыши. Управление будет стандартным, какое присутствует в большинстве 3д-шутеров. Клавишами W, S, A, D мы будем перемещаться вперед, назад, влево, вправо, пробелом мы будем прыгать (проще говоря – перемещаться вверх), а мышью мы будем менять направление взгляда. Для этого откроем пока еще пустой файл script.js. Сначала впишем туда такие переменные:

Изначально клавиши не нажаты. Если мы нажмем клавишу, то значение определенной переменной изменится на 1. Если отпустим ее, то она снова станет 0. Реализуем это посредством добавления обработчиков нажатия и отжатия клавиш:

Номер 32 – код пробела. Как видите, тут появилась переменная onGround, указывающая на то, находимся ли мы на земле. Пока разрешим движение вверх, добавив после переменных press… переменную onGround:

Итак, мы добавили алгоритм нажатия и отжатия. Теперь необходимо добавить само передвижение. Что, собственно, мы передвигаем. Представим, что у нас есть объект, который мы двинаем. Назовем его “pawn”. Как и принято у нормальных разработчиков, для него мы создадим отдельный класс “Player”. Классы в javaScript создаются, как ни странно, с помощью функций:

Вставим этот код в script.js в самом начале файла. В конце же файла создадим объект данного типа:

Распишем, что означают эти переменные. x, y, z – это начальные координаты игрока, rx, ry – углы его поворота относительно осей x и y в градусах. Последняя записанная строка означает, что мы создаем объект “pawn” типа “player” (специально пишу тип, а не класс, так как классы в javascript означают несколько другие вещи) с нулевыми начальными координатами. Когда мы двигаем объект, координата мира изменяться не должна, а должна изменяться координата «pawn». Это с точки зрения переменных. А с точки зрения пользователя, игрок находится на одном месте, а вот мир двигается. Таким образом, нужно заставить программу изменять координаты игрока, обрабатывать эти изменения и двигать, в конце концов, мир. На деле это проще, чем кажется.

Итак, после загрузки документа в браузер мы запустим функцию, которая перерисовывает мир. Напишем функцию перерисовки:

В новых браузерах world будет соответствовать элементу с однако надежнее ее присвоить перед функцией update() с помощью следующей конструкции:

Мы будем изменять положение мира каждые 10 мс (100 обновлений в секунду), для чего запустим бесконечный цикл:

Запустим игру. Ура, теперь мы можем двигаться! Однако мир вылазит за пределы рамок элемента «container». Чтобы этого не происходило, зададим css-свойство для него в style.css. Добавим строку overflow:hidden; и посмотрим на изменения. Теперь мир остается в пределах контейнера.

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

Если у вас что-то по-другому, обязательно поправьте!

Мы научились двигать персонажа, однако мы еще не умеем поворачивать его! Поворот персонажа, конечно же, будет осуществляться с помощью мыши. Для мыши к переменным состояния клавиш press… мы добавим переменные состояния движения мыши:

А после обработчиков нажатия-отжатия вставим обработчик движения:

В функцию update добавим поворот:

Обратите внимание на то, что движение мыши по оси y вращает pawn по оси x и наоборот. Если мы посмотрим на результат, то ужаснемся от увиденного. Дело в том, что если смещения нет, то MouseX и MouseY остаются прежними, а не приравниваются к нулю. Значит, после каждой итерации update смещения миши должно обнуляться:

Уже лучше, мы избавились от инерции вращения, однако вращение происходит все равно странно! Чтобы понять, что все-таки происходит, добавим div-элемент «pawn» внутрь «container»:

Зададим ему стили в style.css:

Проверим результат. Теперь все ровно! Единственное — синий квадрат остается впереди, но пока оставим это. Чтобы сделать игру от первого лица, а не от третьего, нужно приблизить мир к нам на значение perspective. Сделаем это в script.js в функции update():

Теперь можно делать игру от первого лица. Скроем pawn добавив строку в style.css:

Отлично. Сразу скажу, что ориентироваться в мире с одним квадратом крайне тяжело, поэтому создадим площадку. Добавим в «world» блок «square2»:

А в style.css добавим стили для него:

Теперь все четко. Ну… не совсем. Когда мы нажимаем по клавишам, мы движемся строго по осям X и Z. А мы хотим сделать движение по направлению взгляда. Сделаем следующее: в самом начале файла script.js добавим 2 переменные:

Градус — это pi/180 от радиана. Нам придется применить синусы и косинусы, которые считаются от радиан. Что нужно сделать? Взгляните на рисунок:

Когда наш взгляд направлен под углом и мы хотим пойти вперед, то изменятся обе координаты: X и Z. В случае перемещения в сторону тригонометрические функции просто поменяются местами, а перед образовавшимся синусом изменится знак. Изменим уравнения смещений в update():

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

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

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

Добавим обработчик изменения состояния захвата курсора (захвачен или нет) перед обработчиком захвата курсора (извините за тавтологию):

А в update() добавим условие вращения “pawn”:

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

С движением мы полностью разобрались. Перейдем к генерации мира

4. Загрузка карты

Мир в нашем случае удобнее всего представить в виде множества прямоугольников, имеющих разное местоположение, поворот, размеры и цвет. Вместо цвета также можно использовать текстуры. На самом деле, все современные трехмерные миры в играх – это набор треугольников и прямоугольников, которые называют полигонами. В крутых играх их количество может достигать десятков тысяч в одном только кадре. У нас же их будет около сотни, так как браузер сам по себе имеет невысокую графическую производительность. В предыдущих пунктах мы вставляли блоки “div” внутрь “world”. Но если таких блоков много (сотни), то вставлять каждый из них в контейнер очень утомительно. Да и уровней может быть много. Поэтому пусть эти прямоугольники вставляет javaScript, а не мы. Для него же мы будем создавать специальный массив.

Откроем index.html и удалим из блока “world” все внутренние блоки:

Теперь создадим массив прямоугольников (запихнем его, примеру, между конструктором player и переменными press… в script.js):

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

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

Поясню, что происходит: мы создаем новую переменную, которая указывает на только что созданный элемент. Ему мы присваиваем id и css-класс (именно это и имеется ввиду под словом класс в языке javaScript), задаем ширину с высотой, фон и трансформацию. Примечательно, что в трансформации помимо координат центра прямоугольника мы указываем смещение на 600 и 400 и половины размеров для того, чтобы центр прямоугольника точно оказался в точке с нужными координатами. Запустим генератор мира перед таймером:

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

Если все хорошо, переходим к следующему пункту.

5. Столкновения игрока с объектами мира

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

А вызывать ее будем в update():

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

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

И обратную функцию:

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

В этом случае условие коллизии становится таким: если после смещения шара на величину v (v – это вектор) координата z между –r и r, а координаты x и y лежат в пределах прямоугольника или отстоят от него на величину, не большую r, то объявляется коллизия. В этом случае координата игрока по z после смещения будет составлять r или – r (в зависимости от того, с какой стороны придет игрок). В соответствии с этим, смещение игрока изменяется. Мы специально вызываем коллизию перед тем, как в update() координаты игрока будут обновлены, чтобы вовремя изменить смещение. Таким образом, шар никогда не пересечется с прямоугольником, как бывает в других алгоритмах коллизии. Хотя физически игрок будет представлять собой, скорее, случае куб, мы не будем обращать на это внимание. Итак, реализуем это в javaScript:

x0,y0 и z0 – начальные координаты игрока в системе координат прямоугольника (без поворотов. x1,y1 и z1 – координаты игрока после смещения без учета коллизии. point0, point0, point1 и point2 – начальный радиус-вектор, радиус-вектор после смещения без коллизии и радиус-вектор с коллизией соответственно. map[i][3] и другие, если вы помните, это углы поворота прямоугольника. Заметим, что в условии мы к размерам прямоугольника прибавляем не 100, а 98. Это костыль, зачем, подумайте сами. Запустите игру и вы увидите довольно качественные столкновения.

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

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

Источник

Читайте также:  restaurant tycoon 2 скрипты
Онлайн платформа
Анатомия Unreal-класса