Просмотр статей по тэгу game maker

    Tiled2GM —  download Tiled2GM Converter (2,5mb)

    Tiled map loader

    While developing our game Journey to Hammerdale we have faced a problem of built-in Game Maker level edtior to be very limited in it's abilities, thus began to search for alternatives. We needed a very simple and handy map editor that would support multiple layers (and manipulations over them). A matching one was found quite fast — Tiled Map Editor. It's capabilities were fully covering our needs and so a loader for ones map format was done in Game Maker.

    Apart from actual tiles, Tiled allows to place object, and assign properties to objects and layers around the map. Support for this functionality was also added to loader. For example, in map properties level name and background color were defined. In object properties — instance-specific variables like saw's movement speed. Support for horizontal and vertical mirroring of tiles was also added in, along with layer transparency.


    Converter use .NET Framework 4.0. TiledLoader need Game Maker 8.1.

    Process is simple, though still requires a couple of actions.

    First you need to draw your map in Tiled. Map can be of any size, and contain any number of objects and/or layers. Also you can add custom properties to map, layers, and objects (property handling is described below).

    Then launch Tiled2GMConverter, and select your map in it. File will be processed and saved as a .lvl.

    The last thing to do is to open TiledLoader in Game Maker and configure it — add your objects, and if needed, property handlers.

    Map loading is done from Create event of object o_controller.


    here you specify filename, in which map is saved.

     In script define_objects you need to setup your objects (with same order as in objects-tileset). Un-recognized objects will be displayed as special object type o_not_defined, which looks like a black circle with red-cross in the middle.

     Script check_property does handling of map and layer properties. As an example, map property bgcolor is handled, which defines background color, and name, which defines window title. For layers, depth property is handled, which defines depth (draw order) for layer. If depth of layer is not defined, it is set to 10000.

     View properties can be configured in the end of load_room script, via command room_set_view.

    Property handling of object properties is done in Create event of objects. As an example, a single property is handled for o_skeleton and several properties are handled for o_doctor.

    Important: Tileset images must be placed in tilesets folder, while loaded maps must be placed in maps folder.

     Cursor control keys can be used for scrolling map in the example.


    At the moment there are several limitations for files, that are processed by converter:

    • Data encoding must be set to base64 (can be set in Tiled properties)


    • Objects must be drawn via 'object tile' instrument — other types of objects are not supported.

    • Names of tileset files must be defined inside of map, rather than separate file (this may occur if external tileset is defined in editor)

    <tileset firstgid="1" source="objects.tsx" />
    <tileset firstgid="626" name="tileset99999" tilewidth="32" tileheight="32">
    <image source="tileset99999.png" width="800" height="800" />

     here the line 
    <tileset firstgid="1" source="objects.tsx" />
     points to external file, in which tileset properties are defined:
    <tileset name="objects" tilewidth="32" tileheight="32">
    <image source="objects.png" width="800" height="800" />

    At the moment converter cannot handle such external files, so data from external file must be added in like this:
    <tileset firstgid="626" name="tileset99999" tilewidth="32" tileheight="32">
    <image source="tileset99999.png" width="800" height="800" />

     For this example, resulting code will be:
    <tileset firstgid="1" name="objects" tilewidth="32" tileheight="32">
    <image source="objects.png" width="800" height="800" />

    • Tile rotation (+- 90 degrees) is not supported.


    If you have found an error, or have suggestions, send me a message. Use contact form (select Dmi7ry)


    http://www.mapeditor.org  —  Tiled map editor.
    http://j2h.ru  —  Devlog of our game "Journey To Hammerdale".
    Tiled2GM  —  download Tiled2GM Converter (rar, 2,5mb)
    Tiled2GM  —  download Tiled2GM Converter (zip, 2,5mb)

    Tiled2GM —  скачать Tiled2GM Converter (2,5mb)

    Tiled map loader

    При разработке нашей игры Journey To Hammerdale мы столкнулись с весьма ограниченными возможностями встроенного в Game Maker редактора комнат, поэтому начали поиск альтернатив. Нужен был простой и в то же время удобный редактор карт, с поддержкой множества слоёв (с удобным управлением ими). Довольно быстро был найден такой редактор — Tiled Map Editor. Его возможности полностью обеспечивали наши запросы и поэтому был сделан загрузчик карт tiled для Game Maker.

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


    Процесс не сложен, хотя и требует некоторых действий.

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

    Далее запускаем Tiled2GMConverter, в котором указываем нужную карту. Файл обработается и сохранится с расширением .lvl

    Осталось открыть TiledLoader в Game Maker и произвести настройку: добавить свои объекты и, если нужно, обработчики свойств.

    Загрузка карты вызывается в событии Create объекта o_controller.


    здесь указывается имя файла, в котором сохранена карта.

    В скрипте define_objects нужно задать свои объекты (в том же порядке, что и в objects-tileset). Если на карте используется объект, которого нет в этом списке, то будет создан специальный объект, который показывает, что объект не задан (он выглядит как черный круг с красным крестом) — o_not_defined.

    В скрипте check_property идёт обработка свойств карты и слоёв. В качестве примера стоит обработка свойств комнаты bgcolor, задающей цвет фона и name, задающей заголовок окна. Для слоя идёт обработка свойства depth, задающего глубину слоя. Если глубина слоя не задана, то слой создаётся с глубиной 10000.

    Настройки вида можно поменять в скрипте load_room, в самом конце, в команде room_set_view.

    Обработка свойств объектов производится в событии create нужных объектов. В качестве примера стоит обработка одного свойства у объекта o_skeleton и обработка нескольких свойств у объекта o_doctor.

    Изображения тайлсетов должны находиться в папке tilesets, а загружаемые карты — в папке maps.

    Для просмотра карты можно использовать клавиши управления курсором.


    В данный момент есть несколько ограничений на файл, обрабатываемый конвертером:

    • Кодировка данных должна быть base64 (поставьте это в настройках tiled)


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

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

    <tileset firstgid="1" source="objects.tsx" />
    <tileset firstgid="626" name="tileset99999" tilewidth="32" tileheight="32">
       <image source="tileset99999.png" width="800" height="800" /> 

    <tileset firstgid="1" source="objects.tsx" />
    указывает на внешний подключаемый файл, в котором написаны параметры тайлсета:
    <tileset name="objects" tilewidth="32" tileheight="32">
       <image source="objects.png" width="800" height="800" /> 

    Пока что конвертор не работает с подгружаемыми файлами,
    поэтому данные из подгружаемого файла нужно внести подобно записи
    <tileset firstgid="626" name="tileset99999" tilewidth="32" tileheight="32">
       <image source="tileset99999.png" width="800" height="800" /> 

    В данном примере в итоге должно получиться:
    <tileset firstgid="1" name="objects" tilewidth="32" tileheight="32">
       <image source="objects.png" width="800" height="800" /> 

    • Не поддерживается вращение тайла (90/270 градусов)


    Если вы обнаружили ошибку, либо у вас есть какие-то предложения, вы можете написать мне, используя контактную форму (выбрать Dmi7ry)


    http://www.mapeditor.org — Tiled map editor.
    http://j2h.ru — Devlog of our game "Journey To Hammerdale".
    Tiled2GM —  скачать Tiled2GM Converter (2,5mb)

    Перевод статьи Fast platform collisions by Mike.
    Перевод: Dmi7ry. Публикация на других сайтах только с обязательной ссылкой на данное сообщение на этом сайте.
    Прошу прощения за любительский перевод. Корректировки принимаются.
    Хочется сделать примечание, что данный способ применим не только к платформерам, но и к TDS и другим видам, где можно использовать тайлы.

    продолжение статьи Определение столкновений

    С запуском GameMaker:HTML5, появился один новый фактор, который должен быть ключевым для любой игры, которую Вы сейчас проектируете — скорость. Видите ли, переход от исполняемых фалов для Windows к HTML5 несет некоторые проблемы производительности, и иногда весьма существенные. Очевидно, что JavaScript не такой быстрый, как родной код, и это означает, что Вам придется создавать более оптимальный, более изящный код. Это в свою очередь означает, что требуется некоторая корректировка того, как мы сейчас делаем некоторые вещи в GameMaker. Речь о играх-платформерах, так как, в то время как они хорошо работают под Windows, в GameMaker:HTML5 оригинальные примеры продемонстрировали, что они весьма далеки от оптимальности. Тем не менее, не беспокойтесь: всё, что Вы изучаете здесь, может быть перенесено на обычные приложения Windows, и Вы будете также видеть прирост скорости, таким образом, это будет весьма полезно.

    Итак, почему же? Почему в платформерах получается такой результат в JavaScript? А получается он благодаря командам перемещения вроде move_outside_solid(). Посмотрите, что в настоящий момент происходит, когда Вы пишете платформер: Вы ожидаете от системы событие столкновения, а затем используете команды вроде move_outside_solid(), чтобы двигаться за пределы объекта. Проблема с функциями вроде этой — количество работы, которую придется выполнить для того, чтобы исполнить такое простое на вид действие…

    Как GameMaker выполняет команду move_outside_solid()? Давайте рассмотрим это. Хорошо… В первую очередь, прочитайте мою статью про столкновения (перевод тут), потому что Вы должны понимать, как работает точное столкновение, и сколько усилий нужно процессору, чтобы проделать эту работу. После прочтения Вы будете понимать, что даже одно точное столкновение может занять довольно долгое время, и возможно, Вы уже догадались, что move_outside_solid() придется делать это несколько раз для того, чтобы «выйти за пределы» столкновения, которое только что произошло..

    Итак, давайте проследим подробно, что происходит… Сначала Вы перемещаете игрока/объект как обычно, а затем система генерирует событие столкновения (возможно, с использованием медленной проверки столкновения) и после сообщает Вам, что ваш экземпляр только что столкнулся с чем-то. Теперь Вы проверяете направление, откуда Вы только что пришли, и используете move_outside_solid(), чтобы выйти «обратно» из этого столкновения. Если бы Вы были глубоко внутри столкновение (скажем, на несколько точек внутри блока, с которым столкнулись), то это может занять несколько итераций точного столкновения чтобы переместить ваш экземпляр обратно. Добавив к тому, что помимо игрока Вы можете делать то же самое и у противников, Вы сможете увидеть, что это весьма существенная растрата процессорного времени. Итак, как же еще можно сделать? Как бы Вы могли бегать по платформе, и остановить прыжки игрока (и противников) в стены, или падение сквозь пол?

    Для начала, почему бы нам не оглянуться на некоторые старые ретро системы: NES, C64, Megadrive, SNES — все эти системы хорошо известны платформерами, и делали обнаружение столкновения с платформами таким же образом, через тайлмапы. В то же время, это не тайлмапы, как их определяет GameMaker, так как GameMaker использует несколько извращенную версию тайлмапов. Большинство из этих старых систем, использует характерное фиксированное отображение экранов, то есть, экран из X на Y символов. (Например, C64 имеет экран 40×24 клеток, которые он использует в качестве символов, используемые играми в качестве тайлов). Эти символы были затем использованы в качестве тайлов, и эти тайлы были затем определены в платформах и фоне, и простые столкновения происходят с ними..

    Игра выше («The Great Giana Sisters» для C64) показывает, как, возможно, в игре выстроены тайлы на этом уровне. Большие тайлы фактически будут состоять из нескольких тайлов, связаны вместе, чтобы сделать большой объект. Это существенное отличие от тайлов GameMaker‘а, потому что они на самом деле не настоящие тайлы, а очень простые спрайты. Это проблема, потому что мы не можем легко определить, с каким тайлом мы столкнулись — по крайней мере, не без обширной проверки. Так как же эти старые и очень медленные системы, сталкиваются с фоном так быстро? Просто они использовали фиксированную сетку из тайлов. Это означало, Вы легко можете сказать, в какие тайлы Вы попали, просто путем деления своих координат (как правило, 8, 16, 32 и т.д. На самом деле, любой степени двойки), а затем используя эти числа, они указывают непосредственно в сетке тайлов..


    Итак, давайте взглянем на простой тайлмэп. Выше Вы можете видеть очень простой тайлмэп, где 1 является твердым телом, 0 пусто, и 2 — подбираемый предмет. Это означает, что все, что нам нужно сделать, это проверить тайл непосредственно под экземпляром (в нашем примере это игрок). Итак, как же мы это сделаем? Ну, если мы использовали тайлсет 16×16, и наш спрайт 16×16, тогда, стоя непосредственно на тайле, его координаты х и у будут кратны 16. Тогда проверяя тайл непосредственно под нами, нужно просто добавить 16 к Y, затем разделить координату Y на 16, и округлить результат. Это дает нам указатель на тайл (по оси Y) для тайла под ногами. Если тайл 1, то мы не падаем, если 0, то делаем падение.
    Это всё хорошо и здорово, но что, если мы падаем, и что если мы попадаем внутрь тайла? Как мы можем выйти из него без функций вроде move_outside_solid()? Здесь мы используем некоторые трюки старой школы, которые легко позволяли реализовывать платформеры и стрелялки на старых 1МГц системах.

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

    %1      1
    %10     2
    %100    4
    %1000   8
    %10000 16

    Каждый установленный бит добавляет степень двойки к итогу. Как Вы можете видеть из приведенных выше цифр, у них есть только один установленный бит, и поэтому результат — «чистая» степень числа 2 (1,2,4,8,16,32,64,128 и т.д., все степени двойки. Каждое число умножается на 2, оно удваивается.)

    Итак, если у нас есть некоторые комбинации этих битов … Что это значит?

    %110   6
    %1101 13
    %11    3
    %1001  9

    Используя таблицу приведенную выше, вы можете сложить биты вместе, и получить результирующие числа. Довольно понятно пока. Так компьютеры хранят числа, при этом каждый байт содержит значения 8 бит, что означает диапазон чисел от 0 до 255. Для больших чисел, компьютер просто использует больше байт. 2 байта даёт 16 бит, то есть число от 0 до 65535, и так далее…

    Итак… Зачем этот урок по основам вычислений? А… Вот теперь начинается самое интересное. Что произойдет, если мы будем смещать эти биты? Допустим, сдвинуть их влево или вправо на какое-то количество бит? Хорошо, %1 сдвигаемый влево на три бита даст %1000, и это дает результатом число 8. Соответственно, если мы имеем %1000 и сдвигаем вправо на три бита, мы должны получить %1, что даст нам в результате число 1. Другими словами, мы можем сделать простое умножение и деление, сдвигая биты (Это опять же, то, как компьютер делает основную двоичную математику).

    Так… Что произойдет, если мы «сбросим» младшие биты?.. Допустим, у нас было %1011 (11), и мы сделаем с ним AND %1000 (8), мы бы в конечном итоге получили… 8. Обнулив эти младшие биты, мы эффективно округляем до ближайшего наименьшего числа, кратного 8.

    Теперь это удобно …. Что, если наш tilemap был сделан из 16×16, и что если бы мы «залезли» в один на 4 пикселя по координате Y? Например, Y координата была 68. Как мы можем переместить его обратно из тайла? Ну, поскольку мы знаем, что все тайлы на фиксированных границах пикселей, мы знаем, что ВНЕ тайла координата будет 64. Используя двоичные трюки, о которых говорили выше, мы можем сделать простой AND с Y координатой (Y = Y & $fffffff0), и это избавит нас от изменения значения младших битов множителя 16, и помещает его вне столкновения, и обратно до 64, так как %1001000 (68) и $fffffff0 = %1000000 (64).

    Итак, давайте посмотрим на это снова. Если мы знаем, что есть столкновение по Y (см. ниже), мы можем просто вернуться назад прямо в пустое пространство с помощью операции AND с $fffffff0 и удаления проблемных битов.

    Эта система столкновений молниеносна, но для её использования Вы должны иметь фиксированную тайловую карту (tilemap), а не такую, которая помещает плитки в произвольном месте. В будущих версиях GameMaker эта способность будет удалена, но это также даст доступ к карте для использования со столкновениями, так как это бесценный инструмент. После столкновения с картой, Вы можете столкнуться с чем угодно на этом уровне. Собираемые предметы, ловушки, твердые объекты, триггеры, почти все, что Вы используете для экземпляров с точки зрения столкновения, Вы можете использовать тайлмэпы, делая это быстрее. У вас есть ограничение: ваши объекты должны вписываться размером в тайл, но для большинства вещей это не проблема. В конце концов, если Вы хотите, чтобы сработал триггер чего-либо, когда игрок идет по ней, не все ли равно, если он на несколько пикселей левее? То же самое с бонусами… Вы просто должны привыкнуть размещать их в этой манере, а затем Вы можете использовать tilemap для фактического столкновения.

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

    Mike. 13 Октября 2011

    Оригинал (английский): Collision detection by Mike.
    Перевод: Dmi7ry, ArVorozh. Публикация на других сайтах только с обязательной ссылкой на данное сообщение.
    Попытался перевести на сайте translated.by, думал что помогут. Однако только один человек перевёл «начерно» пару абзацев, остальное пришлось мучить самому. С моим ужасным английским результат получается далеко не совершенным. А также несколько странный местами стиль написания автора может затруднить понимание. Продолжением данной статьи является статья Быстрые столкновения в платформере.

    Определение столкновений

    Итак, я был очень занят HTML5 версией GameMaker и, когда я добавил код для столкновений, стало ясно, что основной популярный способ создания столкновений довольно медленный. Я не говорю о том, что нельзя сделать быструю обработку столкновений в GameMaker, просто таким образом составлены примеры, не удивительно, что некоторые люди иногда считают их медленными. Так что я опишу, как я обычно делаю столкновения. Во-первых, я использовал то, что GameMaker называет «точное столкновение» лишь однажды. И, оглядываясь назад, я понимаю, что мог бы обойтись без этого; опыт имеет свои преимущества…

    Итак, для начала… что конкретно означает «точное столкновение«? Ну, проще говоря… это использование пиксельных данных одного изображения для сталкивания с набором пикселей другого изображения, таким образом столкновение будет только тогда, когда два нужных пикселя соприкасаются. Посмотрите на изображения двух кругов: вы можете видеть, что пересекаются их ограничительные рамки, но не круги. Что же это означает? Если вы используете простую систему столкновений ограничительных рамок, то они вызовут событие, в то время, когда точного столкновения на самом деле нет. Теперь может показаться очевидным, если вы используете точные столкновения, то получаете их, когда они на самом деле произошли. Тем не менее… что же требуется сделать GameMaker’у  для того, чтобы определить, что 2 случайных растровых изображения соприкоснулись; запомним, что эти формы могут быть чем угодно, а не только кругами.

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

    for (n=0; n<Obj1_Instance_Countl; n++)
        for (f=0; f<Obj2_Instance_Countl; f++)
            Test_Collisions( n, j );

    Теперь, если представить все события столкновения, которые у вас происходят между различными типами объектов, можно увидеть, что на это уйдёт уйма времени. Одно из изменений, которые мы сделаем со временем — блочная сортировка экземпляров (она же карманная, корзинная). Это означает, что мы будем проверять столкновение только  тех объектов, которые на самом деле близки друг к другу. Но мы пока что не сделали это…

    Итак… Наконец, мы имеем два экземпляра, которые нужно проверить, что же сделает Test_Collisions() на самом деле? Ну, первое, что он делает — проверяет ограничивающие рамки. Это простая проверка, которая позволяет закончить проверку быстро, если объекты далеко друг от друга.

    if ( bbox1.right < bbox2.left ) exit;
    if ( bbox1.bottom < bbox2.top ) exit;
    if ( bbox1.left > bbox2.right ) exit;
    if ( bbox1.top > bbox2.bottom ) exit;

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

    Далее, система отрабатывает перекрытия между ограничивающими прямоугольниками (как показано на следующем рисунке). Теперь каждый пиксель в спрайте можно рассматривать как ИСТИНА/ЛОЖЬ, то есть, если это не цвет фона (в данном случае, белый), то там имеется пиксель. Так, изображение показывает два перекрывающихся массива. Один — синий круг, а другой — красный круг. Затем мы в цикле просматриваем соответствующую секцию (медленно) и проверяем, не было ли двух пикселей в одной и той же позиции. Если нет, то мы ничего не делаем, так что событие не происходит. Вот некоторый псевдо-код для обнаружения столкновения между растровыми изображениями…

    for ( y=YStartPos;y<YEndPos;y++)
        for ( x=XStartPos;x<xendpos;x++)
            if (x < xSprite1Start) || (x> xSprite1End ) continue;
            if(y < ySprite1Start) || (y> ySprite1End ) continue;
            if(x < xSprite2Start) || (x> xSprite2End ) continue;
            if(y < ySprite2Start) || (y> ySprite2End ) continue;
            if(( CollisionMask1[ x+(y*width)]!=0 ) && ( CollisionMask2[ x+(y*width)]!=0 ) )
                return TRUE;
    return FALSE;

    Хотя это и простой псевдо-код, теперь вы можете видеть, что это не будет быстро! Даже если уменьшить проверку до пересекающихся частей, все равно нужно «прогнать» в цикле все это, прежде чем определить, что нет никакого столкновения! А если у вас их много, то вы поставите свой компьютер на колени! Что плохо… GameMaker хочет, чтобы вы использовали точные столкновения по умолчанию. Это ужасно.

    Правда в том, что только в очень РЕДКИХ случаях вы захотите делать точную проверку столкновения; Лемминги ходят по фону, или они должны ходить вокруг фигур, это довольно редкие случаи, и обычно это может быть сделано разными способами. Лемминги никогда делают проверку столкновения с фоном всего спрайта, на самом деле делается проверка только одного пикселя у ног лемминга, в маске. И вы можете сделать это прямо в GML, если вы хотите! По факту, Лемминги имели в своём распоряжении игровое поле размером 1600×160, и вы можете легко преобразовать это в битовую маску (бит на пиксель) размером 200×160. Это, в свою очередь означает, что вам нужен массив размером 32000 байт. И это прекрасно вписывается! Если вы не хотите заходить так далеко, вы могли бы использовать 160 массивов, по 1600 байт каждый. Затем иметь контрольный массив с каждым из них в качестве линии столкновения. Тогда можно легко проверить этот массив в GML используя X и Y координаты леммингов.

    Но что насчёт нормальных игр? Стрелялок и платформеров? Они никогда не должны использовать точное обнаружение столкновений, в этом просто нет необходимости. Во-первых, при использовании точного определения столкновений, нет возможности для ошибок в пользу игрока. Все должно быть совершенным. Нельзя «залезть» даже на один пиксель на злодея или на фон блока. С точки зрения геймплея, это ужасно. Там всегда должно быть немного пространства для ошибок, потому что как люди, мы просто не точны, когда управляем играми. Джойстики/клавиши не достаточно хороши, и наши решения далеко не достаточно хороши. Так что это означает, что игроки в конечном итоге либо станут сверх осторожными и не приблизятся близко к злодеям/фонам, либо они просто будут расстраиваться и сдаваться.

    Итак, какое лучшее решение? Ну, лично я всегда использую либо столкновение с прямоугольником, либо столкновение с окружностью. Оба этих метода быстры и просты в реализации, и, когда вы используете такие вещи, как «корзины», чтобы объединять объекты вместе, вы можете также сократить то, что вы должны проверить в первую очередь! Для тех, кто не знает … «Корзины» — простой способ объединения объектов/экземпляров вместе в группы. Для столкновения, мы стремимся иметь сетку корзин и размещать объекты, во все ячейки корзин, которых они касаются. Это означает, если вы хотите проверить столкновения, вам больше не придется проверять столкновение всех объектов ко всем… Только к тем, которые в окружающих корзинах. Это намного, намного быстрее.

    Итак… как определить «справедливый» ограничительный прямоугольник? Обычно я стараюсь задать прямоугольник, который полностью «вписывается» в противника, это помогает избежать случаев (например, 2 абзаца выше), где игроки умирают, даже вообще не касаясь злодеев. Игроки более чем готовы простить те случаи, когда вы столкнетесь с объектом немного, но они весьма неумолимы в тех случаях, когда они умирают, не задев ничего. Итак, как показано на персонаже слева, желтый ограничительный прямоугольник находится в пределах игрока, но его также более чем достаточно, чтобы быть убитым злодеями или пулями. Также тут нет никаких правил, говорящих, что эту ограничительную рамку, вы будете использовать для столкновения с фоном… так что скорее всего, вы будете иметь то, что не позволяет игроку забраться глубоко внутрь фона. Что-нибудь, что хорошо выглядит и удачно соприкасается — это все, что вам нужно; если пистолет залезает на фон, это в действительности не так существенно…

    Теперь, когда я сказал, что я бы использовал прямоугольник или окружность, одна вещь, которую я бы не стал делать сам — использование ограничивающего прямоугольника, как выше. Причиной этого является то, что «IF‘ы» медленны, так что если вы можете свести их к минимуму, будет лучше! Поэтому я использую трюк, который я узнал от Дэйва Джонса, когда он делал Blood Money; я использую центр прямоугольника с 1/2 ширины и 1/2 высоты.

    Теперь вспомним, что эти прямоугольники — ВНУТРИ спрайтов, таким образом, они, вероятно, будут хорошо друг в друге, означая, что игрок знает, что сейчас его поджарят как гуся. Итак, в этом случае Вы можете видеть 1/2 ширины и 1/2 высоты, 16×32 и 20×20, в то время как расстояние до центров 25×35. Так как же я решаю, что есть столкновение?

    Это очень просто… Итак, я буду делать X, и вы легко увидите, как Y работает. Я просто вычитаю 2 X координаты, и это дает расстояние между центрами (в данном случае 25 пикселей), и если это расстояние составляет менее половины сумм ширины, (16 пикселей + 20 пикселей), то столкновение есть! Это позволяет нам сделать проверку X только с одним IF. Глядя на приведенный ниже код вы заметите, ABS (), и обычно вы должны были бы делать IF там, но если вы sneeky, можно сделать ABS() без IF.

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

    if( (halfwidth1+halfwidth2) < abs(x1-x2) ) exit;
    if( (halfheight1+halfheight2) < abs(y1-y2) ) exit;

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

    Снова, мне никогда не нужно это… Для фона в стиле tilemap, я всегда сталкиваюсь с массивом тайлов, а затем перемещаю себя наружу столкновения с фоном. Так как же я делаю это? Хорошо… Если вы используете тайлы, размер которых является степенью двойки (8, 16, 32, и т.п…) тогда переместиться на границу тайла достаточно просто. Например, если я сталкиваюсь с 32×32 тайлом в X=64 и Y=32, и координаты моего экземпляра размером 32×32 составляют 56,12 (тогда это перекрывается в 24,12), затем все, что мне нужно сделать, чтобы переместить образец НАРУЖУ коллизии, это бинарное И с $FFFFFFE0. Это удаляет младшую «дробную» часть битов, так же, как:

    x = x-(x%32);

    Теперь… даже если вы должны были поддерживать систему, которую GameMaker использует в настоящий момент, это все еще было бы намного быстрее не используя «точные» столкновения, но все еще медленнее, чем нормальный «pro» использовал бы. Сейчас, я мог пойти дальше, по поводу того, как сделать эффективное обнаружение столкновения, но действительно… Я должен действительно сделать отдельную статью о каждом методе, и вы затем легко видели бы, какую систему вам было бы лучше использовать в конкретном случае.. но давайте посмотрим, сколько времени я имею. 🙂

    Несколько слов в конце… Так, GameMaker часто обвиняют в медленности, но на самом деле, на современном компьютере это довольно быстрая система для 2D-игр. Однако из-за довольно хороших команд, вроде встроенной сложной системы столкновений, очень легко злоупотреблять ими, и думать, что нет ничего плохого в вашем коде…  Однако, быть хорошим кодером значит знать все о том, как выполняется код, даже если он не Ваш! Если это Ваша игра, это Ваша проблема, и GameMaker имеет все необходимые вам инструменты, чтобы сделать игру восхитительной.