Пишем игры без JavaScript

Леонид Лебедев

Пишем игры без JavaScript

О себе

Леонид Лебедев

О компании Туту.ру

Туту.ру

Мы продаём ж/д, авиа и автобусные билеты, туры, бронируем отели, рассказываем о расписании.

Самый посещаемый сервис туристических услуг в России (по версии comScore).

1 млн. 15 млн. 2003 г. 316
посетителей в день посетителей в месяц год основания сотрудников
Подробнее о компании

Пишем игры без JavaScript

Зачем?

Зачем?

  1. Хочу

Зачем?

  1. Хочу
  2. Могу (наверное)

Зачем?

  1. Хочу
  2. Могу (наверное)
  3. 4 fun

Как?

Как?

  1. :hover

Как?

  1. :hover
  2. cursor

Как?

  1. :hover
  2. cursor
  3. CSS animations

Как?

  1. :hover
  2. cursor
  3. CSS animations
  4. ~

Как?

  1. :hover
  2. cursor
  3. CSS animations
  4. ~
  5. flexbox (grid)

Как?

  1. :hover
  2. cursor
  3. CSS animations
  4. ~
  5. flexbox (grid)
  6. CSS Variables

Как?

  1. :hover
  2. cursor
  3. CSS animations
  4. ~
  5. flexbox (grid)
  6. CSS Variables
  7. input + label (:checked)

Ограничения

Делаем только для современных браузеров

Давайте сделаем!

Race

Концепция

Концепция

Концепция

Концепция

Цель

Сходу тяжело придумать, отложим на потом

Курсор

Можно повесить свою картинку на курсор

cursor: url('cursor.png'), default;

default — вид курсора по умолчанию для текущего элемента

Машина

Ограничения: не более 128×128

Объекты

Создаём препятствия для машины

Проблема с курсором

Оказывается, что курсор — это точка

cursor: url('cursor.png') X Y, default;
X, Y по умолчанию в верхней левой точке

Проблема с курсором

Оказывается, что курсор — это точка

cursor: url('cursor.png') X Y, default;
X, Y по умолчанию в верхней левой точке

Решение:

Наведение на объект

Объект имеет прямоугольную область, а визуально — сложную

Добавляем скорости

Добавляем скорости

			@keyframes game-car {
				0% {
					transform: translateY(0);
				}
				100% {
					transform: translateY(calc(100vh + 200px));
					/* 200px — высота объекта */
				}
			}
		

Добавляем скорости

			body:hover .car-1 {
				animation: game-car 5s linear infinite;
			}
		
game-car — название (animation-name)
5s — продолжительность (animation-duration)
linear — функция времени (animation-timing-function)
infinite — количество (animation-iteration-count)

Добавляем скорости

			body:hover .car-1 {
				animation: game-car 5s linear infinite;
			}
		
			body:hover .car-2 {
				animation: game-car 4s infinite linear;
			}
		
и т.д.

Экран поражения

Изначально экран не видно, показывается только при наведении на машину

Экран поражения

Изначально экран не видно, показывается только при наведении на машину

			.car:hover ~ .screen-lose {
				display: block;
			}
		

Экран поражения

Можно скрыть только убрав с него курсор

			.screen-lose {
				display: none;
				z-index: 999999;
			}
			.screen-lose:hover {
				display: block;
			}
		

Рандомность

При поражении пользователь уводит курсор и начинает играть сначала

Рандомность

При поражении пользователь уводит курсор и начинает играть сначала

Как сделать рандомность?

Рандомность

			body:hover .car-1 {
				animation: game-car 4s 1s infinite linear;
			}
		

Рандомность

			body:hover .car-1 {
				animation-play-state: running;
			}
			.car-1 {
				animation: game-car 4s infinite linear;
				animation-play-state: paused;
			}
		

Дизайнер

Дизайнер

Дизайнер

Дизайнер

Дизайнер

Цель

Необходимо оторваться от полиции и заехать в грузовик

Демо

Скриншот игры

Уровни

Как усложнить или упростить игру?

Уровни

Как усложнить или упростить игру?

Изначально делаем игру на относительных величинах!

Уровни

Как усложнить или упростить игру?

Изначально делаем игру на относительных величинах!

Способы:

* — криво будут вычисляться столкновения

Победа

Деньги
А как же мобильные телефоны?

2017️

Люди всё реже пользуются компьютером, и всё чаще чаще мобильным телефоном

2017️

Люди всё реже пользуются компьютером, и всё чаще чаще мобильным телефоном

Как быть?

2017️

Люди всё реже пользуются компьютером, и всё чаще чаще мобильным телефоном

Как быть?

:hover уже не работает

Выхода нет! (с)

Игра под мобильные устройства️

Будем использовать label, input, :checked

Концепция

Концепция

Концепция

Whac-A-Mole

Whac-A-Mole

Catch-A-Mole

Цель игры: словить всех кротов за отведённое время

Лунки

По клику крот исчезает

Лунки

			<div class="hole">
				<div class="hole__up"></div>
				<input type="radio" name="mole1">
				<label class="mole mole--1" for="mole1"></label>
				<div class="hole__down"></div>
			</div>
		

Игровое поле

Кроты

Таймер

Отсчитываем время до конца игры

Экраны

Первый экран Экран окончания игры

Начало игры

Клик по экрану запускает анимации

			<body>
				<input type="checkbox" id="start">
				<div class="screen screen--start">
					<label for="start">Click!</label>
				</div>
			</body>
		

Начало игры

			.start:checked ~ .timer {
				animation-name: timer;
			}
		
			.start:checked ~ .screen--finish {
				animation-name: finish;
			}
		

Конец игры

Как начать снова, если уже сыграли и поймали несколько кротов?

Конец игры

Как начать снова, если уже сыграли и поймали несколько кротов?

Перезапускаем страницу!

			<a href=""></a>
		

Уровни

Как усложнить или упростить игру?

Уровни

Как усложнить или упростить игру?

При старте выбирать сложность!

Уровни

			<body>
				<input type="checkbox" id="start-easy">
				<input type="checkbox" id="start-hard">
				<div class="screen screen--start">
					<label for="start-easy">Easy</label>
					<label for="start-hard">Hard</label>
				</div>
			</body>
		

Уровни

			.start--easy:checked ~ .timer,
			.start--easy:checked ~ .screen--finish {
				animation-duration: 15s;
			}
		
			.start--hard:checked ~ .timer,
			.start--hard:checked ~ .screen--finish {
				animation-duration: 7s;
			}
		

Уровни

Уровни

Рандомность

Сейчас пользователь знает последовательность появления кротов, т.к. анимация запускает при выборе уровня

Рандомность

Сейчас пользователь знает последовательность появления кротов, т.к. анимация запускает при выборе уровня

Как решить проблему?

Рандомность

Сейчас пользователь знает последовательность появления кротов, т.к. анимация запускает при выборе уровня

Как решить проблему?

Запускаем анимации кротов при загрузке страницы!

Счётчик

Цель игры ловить кротов

Счётчик

Цель игры ловить кротов, но как посчитать количество пойманных?

Счётчик

Цель игры ловить кротов, но как посчитать количество пойманных?

Будем использовать input!

Счётчик

Как работает input с типом radio?

Выбран первый инпут
			<input type="radio" name="name" checked>
			<input type="radio" name="name">
		

Счётчик

Как работает input с типом radio?

Выбран второй инпут
			<input type="radio" name="name">
			<input type="radio" name="name" checked>
		

Счётчик

Выбран первый инпут
			<div>
				<input type="radio" name="name" checked>
			</div>
			<div>
				<input type="radio" name="name">
			</div>
		

Счётчик

Выбран второй инпут
			<div>
				<input type="radio" name="name">
			</div>
			<div>
				<input type="radio" name="name" checked>
			</div>
		

Счётчик

Вспоминаем, как у нас устроен крот

			<input type="radio" name="mole1">
			<label class="mole mole--1" for="mole1"></label>
		

Счётчик

Вспоминаем, как у нас устроен крот

			<input type="radio" name="mole1">
			<label class="mole mole--1" for="mole1"></label>
		

Значит можно сделать такой инпут

			<input type="radio" name="mole1" checked>
		

Когда будет пойман крот, то у этого инпута пропадёт состояние checked

Счётчик

Счётчик

Счётчик

			<input type="radio" name="mole1" checked>
			<input type="radio" name="mole2" checked>
			<input type="radio" name="mole3" checked>
			...
			<img src="scores.png" alt="scores">
		
00

Счётчик

			<input type="radio" name="mole1">
			<input type="radio" name="mole2" checked>
			<input type="radio" name="mole3" checked>
			...
			<img src="scores.png" alt="scores">
		
01

Счётчик

			<input type="radio" name="mole1">
			<input type="radio" name="mole2">
			<input type="radio" name="mole3" checked>
			...
			<img src="scores.png" alt="scores">
		
02

Демо

Деньги

Контакты

github: leonidlebedev

telegram: @leonidlebedev

twitter: @leonid_lebedev

Игры: leonidlebedev/css-games

Презентация: leonidlebedev/presentations

QR