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

Смотрите видео и под кат.


Разумеется, речь (пока) не идет о полноценной игре, но концепцию покажу.

Игру я назвал «помоги пробке найти друзей».
Сделать она это может построив нексус и «натренировав» себе друзей. Поэтому цель игры — помочь пробке обрести друзей.
Итак, поехали.

Во-первых, в CSS у нас вся игра завязана на чекбоксах и radio кнопках и слеекторе "~". А потому изменяемые элементы должны находиться сверху страницы.

Назовем их «состояния»
<!-- Состояние -->
	<!-- Дефолтные состояния -->
	<input type="radio" name="button-level-2" id="default-state-level-2">
	<input type="radio" name="button-level-1" id="default-state-level-1">
	<input type="radio" name="unit" id="default-state-unit">

	<!-- Кнопки -->
		<!-- Нажата кнопка выбора построек -->
		<input class="state build-button probe" type="radio" name="button-level-1" id="build-button">
		<!-- Для постройки выбран нексус -->
		<input class="state build-nexus start-build" type="radio" name="button-level-2" id="build-nexus">
		<!-- Постройка пробок -->
		<input class="state build-probe-1" type="checkbox" id="build-probe-1">
		<input class="state build-probe-2" type="checkbox" id="build-probe-2">
		<input class="state build-probe-3" type="checkbox" id="build-probe-3">
		<input class="state build-probe-4" type="checkbox" id="build-probe-4">
		<input class="state build-probe-5" type="checkbox" id="build-probe-5">
	<!-- /Кнопки -->


	<!-- Юниты -->
		<input class="state unit probe" type="radio" name="unit" id="start-probe">
		<input class="state unit nexus" type="radio" name="unit" id="nexus-select">
	<!-- /Юниты -->

<!-- /Состояние -->


Кроме того, что они должны быть вверху, они еще не должны находиться внутри блоков, тк селектор "~" выбирает элементы того же уровня.
То есть, имея разметку
<input type="radio" name="unit" id="default-state-unit">
<div id="map">
	<div class="some">Hiho</div>
</div>

Этот селектор не выберет ничего
#default-state-unit:checked ~ .some

Это происходит потому, что .some вложен в #map, то есть находится на другом уровне вложенности.
В этом случае селектор необходимо начинать с ближайшего элемента того же уровня
#default-state-unit:checked ~ #map .some


Сетка


Как мы все знаем, здания в старкрафте располагаются по сетке. Соответственно, нам надо сделать такую же сетку.
Состоять она будет из блоков, содержащих некие состояния, которые может принимать эта ячейка — например, на ней построен нексус:
<!-- Ячейка -->
<div class="cell-label">
	<!-- Нексус -->
	<label for="cell_6_nexus" class="nexus status unit">
		<span class="inner"></span>
	</label>
	<input type="checkbox" id="cell_6_nexus" class="cell-state">
	<label class="view nexus unit" for="nexus-select">
		<div class="probes">
			<div class="probe"></div>
			<div class="probe"></div>
			<div class="probe"></div>
			<div class="probe"></div>
			<div class="probe"></div>
		</div>
	</label>
</div>
<!-- /Ячейка -->

За конечное отображение у нас отвечает блок .view (их может быть множество для разных состояний).
Включается состояние при нажатии на соответствующий label: включаем чекбокс — .view виден:
#map .cell-label .cell-state:checked + .view{
	display: block;
}

Сам же лейбл виден тоже при определенных условиях. Например, когда мы собираемся строить нексус, у нас «виден» (display:block) label, отвечающий за это состояние:
.state.build-nexus:checked ~ #map .cell-label:hover label.status.nexus{
	display: block;
}

При наведении курсора на ячейку мы хотим видеть предварительно, как будет стоять наше здание. Для этого просто стилизуем вложенный в label span (span больше label'а, лейбл размером с ячейку).
Итак, мы видим предварительное расположение постройки, но блок и изображением закрывает соседние ячейки, так что на них трудно обыграть состояние :hover (которое как раз и инициирует показ предварительной постройки).
Слава богам, мы уже можем использовать CSS4 свойство
pointer-events: none;

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

Юниты


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

Заключение



Хотел сделать некоторый сброс к дефолтным состояниям некоторых радио-кнопок, отвечающих за состояния панели при выделении юнита/здания.
Вложил лейбл в лейбл в лейбл рассчитывая, что клик по содержимому лейбла вызовет клик по контейнеру. Но на мое удивление это не сработало, кликается только внутренний лейбл.
<!-- Дефолтные состояния -->
<input type="radio" name="button-level-2" id="default-state-level-2">
<input type="radio" name="button-level-1" id="default-state-level-1">
<input type="radio" name="unit" id="default-state-unit">

<!-- Сброс -->
<label for="default-state-level-2" class="reset">
	<label for="default-state-level-1" class="reset">
		<label for="default-state-unit" class="reset"></label>
	</label>
</label>
<!-- /Сброс -->


Разумеется, это всего лишь Proof-of-Concept и доделать-переделать тут можно много чего, я лишь указал направление для размышлений.

Ресурсы


Комментарии (19)


  1. Suvitruf
    27.09.2015 19:54
    +3

    Кстати, про HTML5 и StarCraft, если кто не видел: HTML5 version of StarCraft.


    1. seokirill
      27.09.2015 20:23

      Круто! Правда меню глючное и мультиплеера нет.


      1. Sasha_Pitenin
        27.09.2015 22:46
        -5

        Какой ещё мультиплеер если статья говорит этом, что тут не js, все на html & css


        1. seokirill
          27.09.2015 23:11
          +2

          Я ж на комментарий ответил, а не свою статью откомментировал.
          Оо
          По ссылке первая старка на HTML5.


      1. TimsTims
        27.09.2015 22:53
        +2

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


        1. seokirill
          27.09.2015 23:12

          Варп, кстати, несложно сделать, я просто поленился.
          А вот сбор минералов я думал-думал, так и не придумал, как его здраво сделать можно.
          Чтоб такое придумать, надо больше времени)


    1. stychos
      28.09.2015 00:26

      Ох и колотить твою налево! Как ярый задрот скбв в далёком прошлом, пустил скупую ностальгическую слезу.


  1. DAiMor
    27.09.2015 22:35

    нужно быть осторожным с селектором ":checked ~" он не работает на версии webkit что используется на iOS 9, и это решать пока похоже некому, хотя тикет висит уже долго.


    1. seokirill
      27.09.2015 23:13

      Странно.
      А в чем логика? Или это баг?


      1. DAiMor
        27.09.2015 23:16

        это баг, был обнаружен в хроме. в нашем приложении так менюшка на css должна показываться. а вот на iOS 9 в хроме не сработало, хотя в сафари все норм.


        1. seokirill
          27.09.2015 23:20

          Кстати, когда работал в веб-студии (начальник — фанат эппл), начальник меня убеждал, что эппл — многомиллионная компания, и она просто не может сделать тухло работающий продукт. Поэтому то, что в сафари SVG некорректно масштабируются — мой косяк.
          Ан-нет, оказалось я тоже не всегда косячу)


          1. SelenIT2
            28.09.2015 11:05

            Да, начиная с 8-й iOS, похоже, у Эпла какая-то непруха с CSS-селекторами пошла. То с :nth-child накосячили, то вот это…


            1. stychos
              28.09.2015 21:55

              Да там и до восьмой версии было прекрасное — например, абсолютно косячно работал select multiple. Впрочем, это касалось не только сафари, но и всех браузеров на мобильном вебките.


              1. SelenIT2
                28.09.2015 22:23

                Тогда можно припомнить и еще более раннее поведение label-ов, отказывавшихся передавать тап на соотв. input, но внезапно исправлявшихся, если задать им cursor:pointer. Казалось бы, какое дело сенсорной платформе до курсора — а вот поди ж ты! :)


  1. Coffin
    28.09.2015 09:38

    Safari Version 8.0.8 (10600.8.9) — ничего не работает :(


  1. Dementor
    29.09.2015 14:13

    Поставил два нексуса, которые породили десять юнитов.
    Я в новом CSS совсем не разбираюсь и потому вопрос: а реально ли в рамках вашей концепции без JavaScript создать несколько объектов одного класса, которые были бы самостоятельными?


    1. seokirill
      29.09.2015 14:26
      +1

      Я ждал, что кто-то заметит этот косяк))
      Если вы про то, чтобы эти два нексуса были самостоятельными, то да. Я так и планировал, но поленился.
      Просто пришлось бы для каждого нексуса свое состояние (state) вводить.


  1. aramby
    08.10.2015 01:00

    Товарищ) да вы — «машина»! ))) лайк!)


    1. seokirill
      08.10.2015 11:08

      сделал бы лучше, да пока css4 мало что работает