Второй девлог \ o / Ура!
Я планировал опубликовать его 21.04.21 (два дня назад), но я занялся каким-то личным делом, и мне нужно было отложить его на сегодня.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ. В этом журнале разработчиков я должен рассказать много вещей о программировании. Если вам не нравится это видеть, ничего страшного, просто переходите к тем частям, которые вам нравятся. В зависимости от того, какой будет эта статья после того, как я закончу, я могу отделить кодирование от последующих журналов разработчиков на отдельные статьи.
Итак, давайте погрузимся в новые вещи, которые я создал.
Начальные панели HUD
Я добавил немного HUD для игры. Полоски HP, MP и выносливости теперь расположены в нижней части экрана.
Полоса выносливости (единственная, которая сейчас взаимодействует) истощается, когда персонаж бежит. Если у игрока заканчивается выносливость, он прекращает бег и блокирует кнопку (предотвращая начало спринта при минимальном значении выносливости).
Некоторые ошибки возникли из-за того, как я это закодировал:
- Если я нажимаю кнопку спринта (сдвиг) и не двигаю своего персонажа, выносливость истощается, как будто я двигаюсь.
- Если персонаж сталкивается с заблокированной областью, а я все еще нажимаю кнопку спринта, его выносливость также истощается.
Решением для этого будет прикрепление истощения выносливости к коду движения, а не к коду ввода. Это должно быть исправлено до следующего журнала разработчиков.
Создание некоторых спрайтов
На этой неделе мне доставили планшет для рисования, и я начинаю к нему привыкать. Первый спрайт, который я сделал, был костровым (представлен на видео).
Следующим будет спрайт-лист со 100 иконами мечей (10x10 спрайтов размером 32x32) для инвентаря и добычи. Пока что чувствую себя неплохо с результатом.
Кричит для канала Adam C Younis, на котором есть много уроков по пиксельному искусству. Костер разожгли с его помощью.
Моей следующей задачей будет создание правильного набора тайлов для лесной местности, чтобы с его помощью изменить внешний вид стартовой комнаты (для этой работы я купил плиточника и надеюсь поэкспериментировать с ним. это скоро) и добить минимум 20–25 мечей.
Двуручная анимация движения персонажа
Анимация персонажа, держащего двуручное оружие / инструмент, настроена на Aseprite! Сначала я использую спрайты Sepiel. Идея состоит в том, что, когда наступит будущее, я изменю облик всех имеющихся у меня ассетов, и, возможно, базовый персонаж тоже будет изменен.
Однако я делаю вид, что использую этот спрайт как основу для рисования будущих итераций.
Новый код очереди и процессора на World Server
Теперь о «скучных» вещах (в кавычках, потому что мне очень нравится эта часть), которые касаются программирования мирового сервера и исправления некоторых проблем.
В последнем журнале разработчиков я использовал модуль узла под названием bee-queue
для обработки очередей, созданных и обрабатываемых в redis. Это приводило к нескольким ошибкам, связанным с конкретной ошибкой авторизации с помощью очереди redis. Я перепробовал множество решений в Интернете, но ни одно из них не устранило проблему.
Еще одна вещь, которая способствовала изменению кода очереди, заключалась в том, что этот модуль не позволяет использовать ioredis
в качестве клиента redis, и я застрял на использовании node-redis
, в котором много причуд реализации, которые мне не нравятся.
Итак, после множества ошибок и разочарований я решил написать свою собственную систему очередей, которая теперь неплохо работает со всем, что мне нужно. Мне было интересно разобрать эту часть кода в другой блог, но для простоты (для меня) я сделаю это на этом. Если он станет слишком большим, в будущем я отделю его.
На проекте у меня изначально две очереди. Одна - это очередь POS_UPDATE_Q
, которая будет обрабатывать (как вы догадались) все обновления позиции, отправленные на сервер клиентами.
Другой - это CHAR_UPDATE_Q
, которая (как вы снова догадались) обрабатывает обновления символов в клиентском объекте. в памяти.
Класс очереди
Класс очереди будет объектом, который будет в памяти сервера, который сохраняет интерфейс для взаимодействия с клиентом redis. В Redis каждая очередь является типом данных LIST
, что означает, что я могу добавить в нее любое количество заданий (объектов, которые будут обрабатываться).
Этот класс является наследником собственного класса EventEmitter
, который заставляет его генерировать события (да) для любого подписчика, которого я хочу.
В классе есть статический метод create
, который создаст экземпляр этого класса и выделит клиент redis по переменной _client
, если он не был определен в момент создания очереди. Этот шаблон гарантирует мне, что во всех моих очередях будет использоваться только один клиент (соединение) Redis. Возможно, это не лучший сценарий, но я хотел бы сначала попробовать это, а потом, если у меня возникнут проблемы с производительностью из-за переполненных соединений, я изменю его.
Наконец, экземпляр этого класса будет иметь методы pop
, push
и process
. Метод pop
удаляет самую старую запись о задании (очередь - это тип данных FIFO), а метод push
добавляет запись о задании на последнюю позицию очереди. Таким образом, я как бы гарантирую *, что задания обновления позиции в очереди POS_UPDATE_Q будут вставлены и удалены из очереди в хронологическом порядке. .
Метод process
- это тот метод, который обработает задание так, как я хочу. И в этом методе, и в методе create
я могу передать параметр processor
. Этот параметр представляет собой функцию, которая получит запись о задании и что-то с ней сделает. Я могу передать эту функцию при запуске process
метода очереди или просто настроить функцию, которая будет запускаться каждый раз для обработки заданий этой конкретной очереди.
* Обработка заданий производится с помощью обещаний, и для повышения производительности я не жду обещания завершения процесса задания, чтобы начать обработку следующего. Позже это может вызвать временные проблемы.
Класс процессора
Класс процессора работает с классом очереди для обработки заданий через определенные промежутки времени.
Большинство MMORPG работает с концепцией «серверных тиков», то есть интервала, в течение которого сервер обрабатывает клиентские пакеты. Я использую интервал 100 мс, поэтому идея состоит в том, что процессор выбирает все задания, добавленные в интервале 100 мс своей очереди, и обрабатывает их.
Экземпляр процессора должен вести себя при обработке: на основе событий и интервалов. При создании такого экземпляра я могу определить queue
объект, к которому этот процессор будет присоединен, функцию processHandle
, которая будет использоваться для обрабатывать задания из очереди и interval
в миллисекундах, которые процессор будет отмечать и извлекать задания (по умолчанию 0).
Если interval
равно 0, процессор будет использовать поведение на основе событий, при котором будет подписываться событие на объект очереди и обрабатывать задания, когда он генерирует job pushed
событие, мгновенно обрабатывая, когда задание добавляется в очередь.
Если interval
больше 0, это означает, что мне нужна обработка тиков, и экземпляр процессора будет использовать поведение на основе интервала, которое вызовет метод start
.
Этот метод установит всю среду для работы интервального процессора. Сначала он проверяет, запущен ли уже процессор, а если нет, он настраивает setInterval
встроенную функцию javascript, чтобы функция запускалась за interval
миллисекунд. Функция - это метод runIntervalProcess
, который внутри него заставит всю бизнес-логику обрабатывать все задания внутри временного окна.
У меня также есть метод stop
, чтобы остановить поведение интервала и очистить функцию интервала, установленную в движке NodeJs.
О, приятно упомянуть. Помните ошибку сборщика мусора, о которой я упоминал в предыдущем журнале разработки? Из-за этих новых объектов очереди и процессора у меня больше не было этой ошибки, так что я поднимаю палец вверх \ o /!
Клиентские и пользовательские вложения
Я прикрепил клиентский объект, созданный на стороне сервера, к пользователю в базе данных. Это поможет мне лучше контролировать, какие клиенты подключены и какие пользователи к нему подключены, и ограничить каждого пользователя, чтобы к его учетной записи был подключен только один клиент.
Чтобы проверить, присоединить и отсоединить клиента от пользователя, я использую UUID, сгенерированный для каждого клиента в памяти, сохраняемый в записи пользовательской базы данных, переданный через внутренний запрос, сделанный с World Server на Rest Server. Этот UUID является ключом записи Redis и используется для поиска с помощью функции filter
по списку клиентов.
Вот правила, по которым это работает эффективно:
- Если клиент пытается аутентифицироваться в учетной записи пользователя, к которой не подключен клиент, клиент подключается к пользователю через, и все работает нормально.
- Если к пользователю, с которым подключается клиент, уже подключен клиент, клиент получит предупреждение о том, что его учетная запись уже подключена.
- Когда успешно подключенный клиент выходит из системы, клиентский объект на стороне сервера отправляет запрос выхода на сервер Rest, отменяя привязку клиента к базе данных.
- Если клиент пытается войти в учетную запись пользователя с клиентом, и его запись в базе данных имеет клиентский UUID, который больше не существует в памяти мирового сервера, клиент успешно подключается.
К настоящему времени клиент успешно подключается и отключается от пользователя, но проверка все еще содержит ошибки.
Состояние ума
За это время между этими двумя блогами разработчиков я прошел много интересного в своей жизни как разработчика и лично. Я уделял игре меньше времени, но на самом деле стал более продуктивным. Научиться пользоваться планшетом для рисования стало для меня новым испытанием, и я очень хочу его решить.
В качестве хорошего совета себе и другим: если вы устали делать одно и то же снова и снова, попробуйте найти другой вызов или предмет для размышлений. Это может устранить некоторые умственные блоки и поможет сохранить мотивацию к первопричине.
Мотивация
Как и в случае с другим журналом разработчиков, моя мотивация составляет около 8/10. Я не так устал, как был, но я думаю, что этот балл по умолчанию для каждой вещи, которую мы делаем в исходном состоянии. Моя мотивация исходит из того, что я вижу, как я продвигаюсь к тому, чего хочу: к круглой, хорошо отточенной игре, в которую я могу играть и / или писать код с друзьями.
Вот и все. Спасибо, что дочитали до этого места, и увидимся в следующем журнале разработчика.