Комментарии 32
Ок, пришёл менеджер и говорит: надо сделать сплитскрин, чтобы два человека могли параллельно играть на одном экране. Что вы будете делать с вашими синглтон стором и синглтон лупом?
вот что касается стора — тут я в затруднении, поскольку недостаточно хорошо читаю Svelte/React-подобные исходники. По моим прикидкам, для сплитскрина один игровой экран должен быть вью-компонентом с инкапсулированным состоянием. Два таких компонента можно связать с общей моделью состояния, на изменения которого подписана логика соревнования и общий тайминг.
А тут одна общая модель для всех? Можно ли не хранить сиюминутные состояния экрана в общем сторе, сделать какой-нибудь свой отдельный стор-обсервабл?
если идти дальше и делать онлайн-матчи — то игровой экран придется сделать исполнителем для приходящих команд для изменения вью и отправителем команд нажатия — а логику обработки команд и внутреннего выносить на сервер. Но вряд ли кто-то даст денег под такой концепт игры )
Я не автор, я использовал вопрос как задачку для себя, поскольку работаю в похожей области и на горизонте как раз наклевывается мультиплеер. Если где-то мои рассуждения кажутся глупыми — не стесняйтесь указать более изящное решение.
Более изящно делать компонент приложения самодостаточным, не зависящим от глобального состояния.
хотя у меня был когда-то период God Object, а затем меловая эпоха толстых контроллеров
Я так не делал и никому не советую, но в разумных пределах iframes + postMessage иногда работает как решение для сборки самых разных компонентов от самых разных разработчиков на одной странице. Как минимум, я знаю кейс, когда игру, которая писалась на игровом фреймворке, так подключали к странице, на которой крутился обычный фронтенд — и уже на ней показывались баллы, время, отведенное на игру и другие параметры, которые менялись на самой странице согласно гениальному плану организаторов всего проекта.
PS: не делал и не советую — в смысле, рефакторить такие кейсы подобным образом.
Хороший пример, но нужно больше сложностей и проблем из реального мира. Фреймворк всё больше мне нравится.
На каких машинах тестировали?
Проекты, конечно, разные, но тем не менее, FPS монитор хрома мне выдает около 55 FPS.
Macbook air 2013
Добавим компонент кнопки
<div>
Все же лучше использовать <button>
. Каждый раз когда верстальщик делает кликабельный див вместо кнопки, pepelsbey негодует. Вот хороший доклад на эту тему, кстати: https://www.youtube.com/watch?v=ssJsjGZE2sc
Согласен. Срезал угол, чтобы не накидывать стилей…
Не срезайте углы, из-за вашей лени (оптимизации?) кто-то не сможет пользоваться интерфейсами.
А ещё, глядя на ваш SVG, видно, что вы в душе не понимаете, что там происходит. Разберитесь, там много лишнего очень красиво выровнено по строкам.
Спасибо за замечания. Исправил в меру своих знаний.
что касается интерфейсов — хотелось бы услышать разбор, какой именно accessibility из фронтенда нужен в играх такого рода, что в посте? Какой use case может возникнуть и как его можно успешно реализовать, учитывая, что в таких играх нужна очень быстрая реакция?
учитывая, что в таких играх нужна очень быстрая реакция
Больше всего фронтенду любых интерфейсов нужно, чтобы мы не делали выводов о людях, о которых ничего не знаем. Я столько дичи слышал про то, что слепые и прочие «странные люди» не ходят в интернет, не смотрят Ютуб, не покупают в интернете. Нет, это не так. Делайте хорошо и доступно, а люди разберутся, как им это использовать.
имеете в виду, что rect прекрасно можно использовать с transform
Нет, гораздо больше. Сравните:
<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>
<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>
<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>
<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 и получил их чище и меньше, без лишних обёрток, атрибутов и мишуры.
Вадим, возьму на себя смелость вам возразить. Обертки, мишура и атрибуты иногда делаются умышленно. Вставив ваш код получим следующую картинку:
Потому что:
- Атрибуты width и height подгоняют svg под нужный нам размер. Это можно сделать через css. У вас есть аргументы, почему это нужно выносить в css, особенно в контексте туториала? Да, можно изначально нарисовать в нужном размере, но я, к сожалению, не дизайнер, и взял готовое изображение.
- Атрибут transform сдвигает треугольник, чтобы визуально он казался по центру круга. В случае с правой стрелкой еще и разворачивает.
С трансформацией:
Без трансформации:
Опять же, это можно вынести в css. Я не знаю весомых аргументов делать это в css. - Поскольку в туториале я использую 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: и ее укороченной формы.
Разрабатываем игру на Svelte 3