Проект: делаем свою слот-машину как в онлайн-казино
easy

Проект: делаем свою слот-машину как в онлайн-казино

Безлимитные фриспины в подарок

Сегодня сделаем очень простую слот-машину (как в онлайн-казино), которая будет показывать случайные эмодзи фруктов и овощей на трёх слотах. Проект поможет попрактиковаться в CSS-анимациях, работе с DOM и массивами в JavaScript.

Проект: делаем свою слот-машину как в онлайн-казино

Логика проекта

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

Призов нет, зато фриспинов — сколько хочешь. 

Как мы это сделаем:

  1. Создадим HTML-разметку с контейнером для барабанов и кнопкой управления.
  2. Добавим стили для фона, кнопки и создадим простую анимацию вращения.
  3. Напишем код функции, который будет случайным образом генерировать эмодзи.
  4. Напишем код для логики перезапуска игры. 
  5. Поиграем бесплатно, без регистрации и СМС.

Готовим HTML-страницу

Создадим новый HTML-файл и добавим сразу в него основные элементы. Для эмодзи мы будем использовать Unicode-коды, а не сами символы, чтобы все браузеры могли корректно их отображать. Коды эмодзи можно взять из Википедии. Для HTML будем использовать HTML-формат с префиксом &#x.

По сути, всё, что нам нужно сделать, — добавить на страницу блоки:

  • для логотипа;
  • слотов с эмодзи;
  • для кнопки перезапуска.

Всё остальное будем добавлять, настраивать и обрабатывать в скрипте и CSS-файле.

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Веб-проект: Emoji Fruit Machine</title>
 <!-- Создадим файл для стилей, позже сделаем всё красиво -->
  <link rel="stylesheet" href="./style.css">
</head>
<body>
  <!-- Логотип -->
  <div class="logo">🎰</div>
  <!-- Основной контейнер -->
  <div class="container">
  <!-- Три слота -->
    <div class="reel first"></div>
    <div class="reel second"></div>
    <div class="reel third"></div>
  </div>
  <!-- Кнопка управления -->
  <div class="controls">🔄</div>
  <!-- Сразу создадим и подключим файл со скриптом, код напишем позже -->
  <script src="./script.js"></script>
</body>
</html>

Сюда мы добавили:

  • Логотип в виде эмодзи игрового автомата.
  • Контейнер с тремя слотами (.reel), где будут появляться случайные эмодзи.
  • Кнопку для перезапуска игры.

Проект: делаем свою слот-машину как в онлайн-казино

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

Берём созданный файл style.css — в него добавим стили и красиво оформим слот-машину. Для начала добавим общие настройки для страницы и контейнера:

body {
 /* Тёмно-синий фон */
 background: #293544;
 /* Выравниваем весь текст по центру */
 text-align: center;
}
/* Настраиваем контейнер для барабанов */
.container {
 /* Фиксированная ширина */
 width: 600px;
 /* Фиксированная высота */
 height: 200px;
 /* Обрезаем содержимое, выходящее за границы */
 overflow: hidden;
 /* Позиционируем */
 position: relative;
 /* Сдвигаем контейнер на середину экрана */
 left: 50%;
 /* Компенсируем смещение, центрируя контейнер */
 margin-left: -300px;
 /* Закругляем углы */
 border-radius: 30px;
 /* Фон с радиальным градиентом*/
 background: radial-gradient(ellipse at center, #2c7dfd 1%, #5d9bfd 65%);
 /* Добавляем тень для объёма */
 box-shadow: 10px 10px 50px rgba(255, 255, 255, 0.2);
}

Обновляем и видим что-то очень большое и синее.

Проект: делаем свою слот-машину как в онлайн-казино

Теперь оформляем кнопку и логотип:

/* Общие стили для кнопок */
.controls,
.logo {
 /* Фиксированная ширина */
 width: 80px;
 /* Размер шрифта */
 font-size: 40px;
 /* Выравнивание содержимого по центру */
 text-align: center;
 /* Высота строки для центрирования */
 line-height: 76px;
 /* Серый фон */
 background: #b5b5b5;
 /* Отступы 0, автоцентрирование по горизонтали */
 margin: 0 auto 0;
 /* Эффект свечения */
 box-shadow: 10px 10px 50px rgba(255, 255, 255, 0.2);
}
/* Кнопка перезапуска */
.controls {
 /* Закругляем только нижние углы */
 border-radius: 0 0 20px 20px;
 /* Делаем курсор указателем, чтобы показать, что элемент кликабельный */
 cursor: pointer;
}
/* Оформляем логотип */
.logo {
 /* Отступ сверху */
 margin-top: 50px;
 /* Закругляем только верхние углы */
 border-radius: 20px 20px 0 0;
}

Логотип и кнопка встали на место и получилось так. Уже похоже на то, что нам нужно:

Проект: делаем свою слот-машину как в онлайн-казино

Настройка барабанов

Продолжаем заниматься стилями и переходим к настройкам барабанов. Для начала нам нужно создать анимацию, которая будет их прокручивать вниз, а потом мы её применим к каждому слоту.

@keyframes reel {
 0% {
   /* В начале анимации слот находится в исходном положении */
   top: 0;
 }
 100% {
   /* Слот сдвигается вверх, создавая эффект прокрутки */
   top: -1187%;
 }
}

Теперь оформим сами слоты:

.reel {
 /* Абсолютное позиционирование внутри контейнера */
 position: absolute;
 /* Фиксированная ширина слота */
 width: 200px;
 /* Высота больше контейнера для эффекта прокрутки */
 height: 1800%;
 /* Применяем анимацию прокрутки */
 animation: reel 1.75s linear 2;
 /* Обрезаем всё, что выходит за границы */
 overflow: hidden;
}

Дальше стилизуем содержимое слота:

.inner {
 /* Ширина слота */
 width: 200px;
 /* Высота элемента для корректного отображения эмодзи */
 height: 66%;
 /* Размер эмодзи */
 font-size: 130px;
 /* Высота строки для центрирования */
 line-height: 216px;
 /* Обрезаем всё, что выходит за границы */
 overflow: hidden;
}

👉 Визуально на странице ничего пока не должно меняться — все стили будут работать уже с эмодзи.

Дальше нам нужно сделать позиционирование для слотов барабана и задать разную задержку анимации, чтобы эмодзи появлялись по очереди, слева направо. Поэтому на каждый слот добавим дополнительный стиль:

.first {
 left: 0;
 animation-delay: -0.5s;
}
.second {
 left: 200px;
 animation-delay: -0.2s;
}
.third {
 left: 400px;
 animation-delay: 0s;
}

Пока всё так же, потому что нет скрипта, который бы запускал всю написанную нами красоту:

Проект: делаем свою слот-машину как в онлайн-казино

Пишем скрипт

Сейчас мы напишем JavaScript-код, который будет:

  • генерировать случайные эмодзи для каждого слота, используя список кодов фруктов и овощей;
  • заполнять слоты эмодзи и создавать эффект вращения;
  • запускать слот-машину при каждом нажатии кнопки;
  • проигрывать анимацию, которая имитирует вращение барабанов перед остановкой.

Теперь разберёмся, как это реализовать, и начнём с функции генерации случайных эмодзи.Перед тем как добавить новые эмодзи, сначала удаляем все старые элементы с классом .inner. Это нужно, чтобы при каждом запуске слот-машины не накапливались дублирующиеся эмодзи:

// очищаем предыдущие эмодзи
document.querySelectorAll(".inner").forEach((el) => el.remove());

Затем мы создаём три массива, по одному для каждого слота. Они будут хранить сгенерированные эмодзи, которые мы затем вставим в HTML:

// создаём массивы для хранения эмодзи
let emojiList01 = [];
let emojiList02 = [];
let emojiList03 = [];

После этого создаём массив с кодами фруктов, овощей и других эмодзи, которые будут выпадать в слот-машине. Мы храним эмодзи в виде строк в шестнадцатеричном формате, а когда подставляем в HTML, то будем добавлять префикс &#x перед кодом, чтобы он превратился в настоящий эмодзи на странице:

// задаём список доступных эмодзи
const emojiValue = [
  "1F95D", "1F34B", "1F350", "1F353", "1F34A",
  "1F352", "1F348", "1F347", "1F349", "1F34F",
  "1F34E", "1F34D", "1F345", "1F951", "1F34C",
  "1F351", "1F346", "1F955", "1F344", "1F952",
];

Теперь напишем функцию, которая получает ссылку на массив, выбирает случайный эмодзи из массива emojiValue, превращает его в HTML-код и добавляет в переданный массив:

function generateEmoji(emojiList) {
  // Выбираем случайный код эмодзи из массива emojiValue
  const emojiSingle =
    emojiValue[Math.floor(Math.random() * emojiValue.length)];
  // Преобразуем Unicode-код в HTML-символ и добавляем в массив
  emojiList.push(`&#x${emojiSingle};`);
}

Далее с помощью цикла заполняем каждый из трёх массивов 11 случайными эмодзи, которые потом попадут в слоты.

// Количество эмодзи на каждом слоте
const n = 11; 
for (let i = 0; i < n; i++) {
  generateEmoji(emojiList01);
  generateEmoji(emojiList02);
  generateEmoji(emojiList03);
}

Затем сделаем вот что: вставим сразу два набора эмодзи на каждый слот, чтобы создать эффект плавного движения. Анимация, которую мы написали в CSS, смещает барабан вверх, но поскольку символы повторяются, кажется, что они вращаются по кругу.

Чтобы объединить все эмодзи в строку и удалить запятые между ними, используем метод join():

// находим первый слот и вставляем 2 набора эмодзи
document.querySelector(".first").innerHTML = `
  <div class="inner">${emojiList01.join("")}</div>
  <div class="inner">${emojiList01.join("")}</div>
`;
// находим второй слот и вставляем 2 набора эмодзи
document.querySelector(".second").innerHTML = `
  <div class="inner">${emojiList02.join("")}</div>
  <div class="inner">${emojiList02.join("")}</div>
`;
// находим третий слот и вставляем 2 набора эмодзи
document.querySelector(".third").innerHTML = `
  <div class="inner">${emojiList03.join("")}</div>
  <div class="inner">${emojiList03.join("")}</div>
`;

Итак. Мы написали функцию emojiCode(), которая очищает старые эмодзи, случайным образом заполняет три слота и создаёт эффект вращения. Если сейчас запустить эту функцию, барабаны начнут крутиться и эмодзи будут появляться в случайном порядке:

Проект: делаем свою слот-машину как в онлайн-казино

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

Запускаем игру

Сделаем так, чтобы игра работала по такой логике:

  1. При загрузке страницы слот-машина запускается автоматически.
  2. При нажатии на кнопку старые слоты удаляются.
  3. Создаются новые слоты, в которые заново загружаются случайные эмодзи.

Когда страница загрузится, мы вызываем функцию emojiCode(), чтобы сразу заполнить слоты эмодзи:

// Запускаем emojiCode при загрузке страницы
document.addEventListener("DOMContentLoaded", emojiCode);

Затем находим кнопку, по нажатию на которую игра будет запускаться заново:

// Получаем кнопку для перезапуска
const btnReload = document.querySelector(".controls");

Когда пользователь нажимает кнопку, мы предотвращаем стандартное действие:

// Добавляем обработчик события клика
btnReload.addEventListener("click", function (e) {
// Останавливаем стандартное поведение кнопки
  e.preventDefault();

Затем удаляем все элементы .reel, чтобы освободить место для новых слотов:

  // Удаляем старые барабаны
  document.querySelectorAll(".reel").forEach((el) => el.remove());

Добавляем заново три блока .reel, которые будут крутиться и показывать новые эмодзи:

  // Создаём новые барабаны
  document.querySelector(".container").innerHTML = `
    <div class="reel first"></div>
    <div class="reel second"></div>
    <div class="reel third"></div>
  `;

Снова вызываем emojiCode(), чтобы заполнить слоты случайными эмодзи:

  // Перезапускаем слот-машину
  emojiCode();
});

Теперь всё готово — можно играть и крутить барабаны бесконечно.

Мы сделали очень простую слот-машину, буквально прототип, и её в дальнейшем можно улучшить. Например:

  • Добавить проверку совпадений (три одинаковых эмодзи = победа).
  • Добавить звук вращения слотов.
  • Сделать плавную остановку каждого слота с задержкой.
  • Выдавать виртуальные призы за виртуальные комбинации в виртуальной слот-машине в виртуальном мире.

<!DOCTYPE html>
<html lang="ru">
<head>
 <meta charset="UTF-8">
 <title>Emoji Fruit Machine</title>
 <link rel="stylesheet" href="./style.css">
</head>
<body>
 <!-- Логотип -->
 <div class="logo">🎰</div>
 <!-- Основной контейнер -->
 <div class="container">
   <div class="blur">
     <div class="reel first"></div>
     <div class="reel second"></div>
     <div class="reel third"></div>
   </div>
 </div>
 <!-- Кнопка управления -->
 <div class="controls">🔄</div>
 <!-- Подключение скриптов -->
 <script src="./script.js"></script>
</body>
</html>

body {
 /* Тёмно-синий фон */
 background: #293544;
 /* Выравниваем весь текст по центру */
 text-align: center;
}

/* Настраиваем контейнер для барабанов */
.container {
 /* Фиксированная ширина */
 width: 600px;
 /* Фиксированная высота */
 height: 200px;
 /* Обрезаем содержимое, выходящее за границы */
 overflow: hidden;
 /* Позволяем точно позиционировать элементы внутри */
 position: relative;
 /* Сдвигаем контейнер на середину экрана */
 left: 50%;
 /* Компенсируем смещение, центрируя контейнер */
 margin-left: -300px;
 /* Закругляем углы */
 border-radius: 30px;

 /* Фон с радиальным градиентом*/
 background: radial-gradient(ellipse at center, #2c7dfd 1%, #5d9bfd 65%);

 /* Добавляем тень для объёма */
 box-shadow: 10px 10px 50px rgba(255, 255, 255, 0.2);
}

/* Общие стили для кнопок */
.controls,
.logo {
 /* Фиксированная ширина */
 width: 80px;
 /* Размер шрифта */
 font-size: 40px;
 /* Выравнивание содержимого по центру */
 text-align: center;
 /* Высота строки для центрирования */
 line-height: 76px;
 /* Серый фон */
 background: #b5b5b5;
 /* Отступы 0, автоцентрирование по горизонтали */
 margin: 0 auto 0;
 /* Эффект свечения */
 box-shadow: 10px 10px 50px rgba(255, 255, 255, 0.2);
}

/* Кнопка перезапуска */
.controls {
 /* Закругляем только нижние углы */
 border-radius: 0 0 20px 20px;
 /* Делаем курсор указателем, чтобы показать, что элемент кликабельный */
 cursor: pointer;
}

/* Оформляем логотип */
.logo {
 /* Отступ сверху */
 margin-top: 50px;
 /* Закругляем только верхние углы */
 border-radius: 20px 20px 0 0;
}

/* Оформляем барабаны */
.reel {
 /* Абсолютное позиционирование внутри контейнера */
 position: absolute;
 /* Фиксированная ширина барабана */
 width: 200px;
 /* Высота больше контейнера для эффекта прокрутки */
 height: 1800%;
 /* Применяем анимацию прокрутки */
 animation: reel 1.75s linear 2;
 /* Обрезаем всё, что выходит за границы */
 overflow: hidden;
}

/* Оформляем содержимое барабана */
.inner {
 /* Ширина барабана */
 width: 200px;
 /* Высота элемента для корректного отображения эмодзи */
 height: 66%;
 /* Размер эмодзи */
 font-size: 130px;
 /* Высота строки для центрирования */
 line-height: 216px;
 /* Обрезаем всё, что выходит за границы */
 overflow: hidden;
}

/* Позиционируем барабаны и задаём разную задержку анимации */
.first {
 left: 0;
 animation-delay: -0.5s;
}
.second {
 left: 200px;
 animation-delay: -0.2s;
}
.third {
 left: 400px;
 animation-delay: 0s;
}

/* Анимация вращения барабанов */
@keyframes reel {
 0% {
   /* В начале анимации барабан находится в исходном положении */
   top: 0;
 }
 100% {
   /* Барабан сдвигается вверх, создавая эффект прокрутки */
   top: -1187%;
 }
}

function emojiCode() {
 // Удаляем все элементы с классом .inner
 document.querySelectorAll(".inner").forEach((el) => el.remove());

 // Создаём пустые массивы для хранения эмодзи
 let emojiList01 = [];
 let emojiList02 = [];
 let emojiList03 = [];

 // Массив с кодами эмодзи в формате Unicode
 const emojiValue = [
   "1F95D",
   "1F34B",
   "1F350",
   "1F353",
   "1F34A",
   "1F352",
   "1F348",
   "1F347",
   "1F349",
   "1F34F",
   "1F34E",
   "1F34D",
   "1F345",
   "1F951",
   "1F34C",
   "1F351",
   "1F346",
   "1F955",
   "1F344",
   "1F952",
 ];

 // Функция для генерации случайного эмодзи и добавления его в массив
 function generateEmoji(emojiList) {
   // Выбираем случайный код эмодзи из массива emojiValue
   const emojiSingle =
     emojiValue[Math.floor(Math.random() * emojiValue.length)];

   // Добавляем эмодзи в массив, используя HTML-код &#x...; для отображения Unicode-символов
   emojiList.push(`&#x${emojiSingle};`);
 }

 // Количество эмодзи, которые нужно сгенерировать для каждого списка
 const n = 11;

 // Заполняем каждый массив 11 случайными эмодзи
 for (let i = 0; i < n; i++) {
   generateEmoji(emojiList01);
   generateEmoji(emojiList02);
   generateEmoji(emojiList03);
 }

 // Обновляем содержимое элементов с классами .first, .second и .third,
 // вставляя внутрь два дива с классом .inner, содержащие эмодзи из соответствующих массивов
 document.querySelector(".first").innerHTML = `
   <div class="inner">${emojiList01.join("")}</div>
   <div class="inner">${emojiList01.join("")}</div>
 `;
 document.querySelector(".second").innerHTML = `
   <div class="inner">${emojiList02.join("")}</div>
   <div class="inner">${emojiList02.join("")}</div>
 `;
 document.querySelector(".third").innerHTML = `
   <div class="inner">${emojiList03.join("")}</div>
   <div class="inner">${emojiList03.join("")}</div>
 `;
}

// Запуск функции emojiCode после полной загрузки документа
document.addEventListener("DOMContentLoaded", emojiCode);

// Получаем кнопку с классом .controls для управления процессом
const btnReload = document.querySelector(".controls");

// Добавляем обработчик события клика на кнопку
btnReload.addEventListener("click", function (e) {
 // Предотвращаем стандартное поведение кнопки
 e.preventDefault();

 // Удаляем все элементы с классом .reel, если есть
 document.querySelectorAll(".reel").forEach((el) => el.remove());

 // Добавляем в .container три новых div-элемента с классами .reel (first, second, third),
 // которые затем будут заполнены эмодзи в emojiCode()
 document.querySelector(".container").innerHTML = `
   <div class="reel first"></div>
   <div class="reel second"></div>
   <div class="reel third"></div>
 `;

 // Повторно запускаем emojiCode для обновления эмодзи
 emojiCode();
});

Обложка:

Алексей Сухов

Корректор:

Елена Грицун

Вёрстка:

Кирилл Климентьев

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Вам может быть интересно
easy