Pull to refresh

Comments 32

Ок, пришёл менеджер и говорит: надо сделать сплитскрин, чтобы два человека могли параллельно играть на одном экране. Что вы будете делать с вашими синглтон стором и синглтон лупом?

синглтон луп то сам по себе вещь нормальная, просто нужно не редактировать его, а иметь механизм загрузки и выгрузки задач для него. В фреймворке Phaser единый loop, который обрабатывает методы update всех живых объектов. Так что если бы мне поставили задачу расширять именно такой пример — я бы писал что-нибудь, что регистрировало бы функции в списке, по которому бы проходился loop

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

А тут одна общая модель для всех? Можно ли не хранить сиюминутные состояния экрана в общем сторе, сделать какой-нибудь свой отдельный стор-обсервабл?

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

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

Более изящно делать компонент приложения самодостаточным, не зависящим от глобального состояния.

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

Я так не делал и никому не советую, но в разумных пределах iframes + postMessage иногда работает как решение для сборки самых разных компонентов от самых разных разработчиков на одной странице. Как минимум, я знаю кейс, когда игру, которая писалась на игровом фреймворке, так подключали к странице, на которой крутился обычный фронтенд — и уже на ней показывались баллы, время, отведенное на игру и другие параметры, которые менялись на самой странице согласно гениальному плану организаторов всего проекта.

PS: не делал и не советую — в смысле, рефакторить такие кейсы подобным образом.
Поддерживаю но уточню что «изящно» звучит как-то по маркетинговому здесь было ругательство. Давайте лучше скажем правильно/дальновидно/грамотно/предусмотрительно/разумно.

Хороший пример, но нужно больше сложностей и проблем из реального мира. Фреймворк всё больше мне нравится.

Сколько FPS было в React-версии?
На каких машинах тестировали?
В React у меня сильно проседал FPS на событиях клавиатуры, даже с тротлингом
по отладчику было видно, в чем проседает React в реалтайме? Какое там узкое место?

Не, так глубоко не копал ) Просто понял, что React не для игр и забил )
из того, что я читал, понял, что у фреймворков с виртуальным DOM уходит много сил на поддержание слоя абстракции — но лично не проверял.

тут проблема в том, что обновление DOM сама по себе довольно затратная операция и со сложным макетом, особенно при эффектах типа анимированной смены экранов, подтормаживание будет заметно, даже если писать на ванилле (я писал) — поэтому в принципе для реал-тайма лучше взять что-то, что рисует на canvas хотя бы. Если будете дальше идти в том направлении и нужна будет скорость анимаций в html5, то попробуйте Phaser.js — но вот с управлением состоянием игры там придется рисовать свои архитектурные велосипеды
А как можно копать «не глубоко», не открыв Profiler?
Спасибо за замечательный туториал!
Не поделитесь бест-практис по настройке среды разработки под Svelte?
А то в IntelliJ * как-то оно не заиграло с полоборота (не смотря на установку такого плагина)…

Писал в VS code с плагином Svelte. Еще онлайн песочницы неплохо дружат со Svelte, в статье есть ссылки.
По поводу других IDE не подскажу (

Добавим компонент кнопки
<div>

Все же лучше использовать <button>. Каждый раз когда верстальщик делает кликабельный див вместо кнопки, pepelsbey негодует. Вот хороший доклад на эту тему, кстати: https://www.youtube.com/watch?v=ssJsjGZE2sc

Согласен. Срезал угол, чтобы не накидывать стилей…

Не срезайте углы, из-за вашей лени (оптимизации?) кто-то не сможет пользоваться интерфейсами.


А ещё, глядя на ваш SVG, видно, что вы в душе не понимаете, что там происходит. Разберитесь, там много лишнего очень красиво выровнено по строкам.

Спасибо за замечания. Исправил в меру своих знаний.

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

что касается интерфейсов — хотелось бы услышать разбор, какой именно accessibility из фронтенда нужен в играх такого рода, что в посте? Какой use case может возникнуть и как его можно успешно реализовать, учитывая, что в таких играх нужна очень быстрая реакция?
учитывая, что в таких играх нужна очень быстрая реакция

Больше всего фронтенду любых интерфейсов нужно, чтобы мы не делали выводов о людях, о которых ничего не знаем. Я столько дичи слышал про то, что слепые и прочие «странные люди» не ходят в интернет, не смотрят Ютуб, не покупают в интернете. Нет, это не так. Делайте хорошо и доступно, а люди разберутся, как им это использовать.

имеете в виду, что rect прекрасно можно использовать с transform

Нет, гораздо больше. Сравните:


bullet-before.svg
<svg height="40px" viewBox="0 0 427 427.08344" width="40px">
  <path
    d="m341.652344 38.511719-37.839844 37.839843 46.960938 46.960938
    37.839843-37.839844c8.503907-8.527344 15-18.839844
    19.019531-30.191406l19.492188-55.28125-55.28125 19.492188c-11.351562
    4.019531-21.664062 10.515624-30.191406 19.019531zm0 0" />
  <path
    d="m258.65625 99.078125 69.390625 69.390625
    14.425781-33.65625-50.160156-50.160156zm0 0" />
  <path
    d="m.0429688 352.972656 28.2812502-28.285156 74.113281 74.113281-28.28125
    28.28125zm0 0" />
  <path
    d="m38.226562 314.789062 208.167969-208.171874 74.113281
    74.113281-208.171874 208.171875zm0 0" />
</svg>

bullet-after.svg
<svg viewBox="0 0 427 427.08"><path d="M341.65 38.51l-37.84 37.84 46.96 46.96 37.84-37.84c8.5-8.52 15-18.84 19.02-30.19L427.13 0l-55.29 19.5a81.08 81.08 0 0 0-30.19 19.01zm0 0M258.66 99.08l69.39 69.39 14.42-33.66-50.16-50.16zm0 0M.04 352.97l28.28-28.28 74.12 74.11-28.28 28.28zm0 0M38.23 314.79l208.16-208.17 74.12 74.11L112.34 388.9zm0 0"/></svg>

left-before.svg
<svg
  width="40px"
  height="40px"
  viewBox="0 0 292.359 292.359"
  transform="translate(-5 0)">
  <path
    d="M222.979,5.424C219.364,1.807,215.08,0,210.132,0c-4.949,0-9.233,1.807-12.848,5.424L69.378,133.331
    c-3.615,3.617-5.424,7.898-5.424,12.847c0,4.949,1.809,9.233,5.424,12.847l127.906,127.907c3.614,3.617,7.898,5.428,12.848,5.428
    c4.948,0,9.232-1.811,12.847-5.428c3.617-3.614,5.427-7.898,5.427-12.847V18.271C228.405,13.322,226.596,9.042,222.979,5.424z" />
</svg>

left-after.svg
<svg viewBox="0 0 292.36 292.36"><path d="M222.98 5.42A17.55 17.55 0 0 0 210.13 0c-4.95 0-9.23 1.8-12.85 5.42L69.38 133.33a17.56 17.56 0 0 0-5.43 12.85c0 4.95 1.81 9.23 5.43 12.84l127.9 127.91a17.56 17.56 0 0 0 12.85 5.43c4.95 0 9.23-1.81 12.85-5.43a17.55 17.55 0 0 0 5.43-12.84V18.27c0-4.95-1.81-9.23-5.43-12.85z"/></svg>

Ну и аналогично с right.svg. Я просто кинул файлы в SVGOMG и получил их чище и меньше, без лишних обёрток, атрибутов и мишуры.

Вадим, возьму на себя смелость вам возразить. Обертки, мишура и атрибуты иногда делаются умышленно. Вставив ваш код получим следующую картинку:
image
Потому что:


  1. Атрибуты width и height подгоняют svg под нужный нам размер. Это можно сделать через css. У вас есть аргументы, почему это нужно выносить в css, особенно в контексте туториала? Да, можно изначально нарисовать в нужном размере, но я, к сожалению, не дизайнер, и взял готовое изображение.
  2. Атрибут transform сдвигает треугольник, чтобы визуально он казался по центру круга. В случае с правой стрелкой еще и разворачивает.
    С трансформацией:
    image
    Без трансформации:
    image
    Опять же, это можно вынести в css. Я не знаю весомых аргументов делать это в css.
  3. Поскольку в туториале я использую svg в качестве .svelte компонента, код будет превращен при билде в минифицированный js, и отступы не имею значения.
Очень круто! Спасибо большое что поделились опытом.

Одно дополнение, когда приходится писать конктрукцию вида:

<button
  on:mousedown={start}
  on:touchstart={start}
  on:mouseup={release}
  on:touchend={release}
  class={`iconButton ${active ? 'active' : ''}`}>
  <slot />
</button>


Лучше ее заменить на более чистую версию:

<button
  use:hold={[start, release]}
  class={`iconButton ${active ? 'active' : ''}`}>
  <slot />
</button>

<script>
  import hold from './actions/hold.js'
</script>


Реализация экшена:

export default function(node, [ start, end ]) {
  node.addEventListener('mousedown', start);
  node.addEventListener('touchstart', start);
  node.addEventListener('mouseup', end);
  node.addEventListener('touchend', end);
  return {
    destroy() {
      node.removeEventListener('mousedown', start);
      node.removeEventListener('touchstart', start);
      node.removeEventListener('mouseup', end);
      node.removeEventListener('touchend', end);
    }
  };
}
Сразу не заметил, но в этом же куске кода лучше сделать так:

<button use:hold={[start, release]} class:active class="iconButton">
  <slot />
</button>

С использованием директивы class: и ее укороченной формы.

Это невероятно! Я почему-то думал, что два свойства class не получится навесить, и даже не попробовал. Вы открыли мне глаза, полюбил svelte еще больше)

По этой статье видно, что canvas для разработки игр больше подходит: www.educba.com/svg-vs-canvas

Only those users with full accounts are able to leave comments. Log in, please.