Разработка игры Slots на блокчейне

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка игры Slots на блокчейне
Средняя
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1258
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    873
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1092
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    830

Разработка игры Slots на блокчейне

Slots (игровые автоматы) — самая популярная категория казино-игр. На блокчейне ключевая задача: генерировать символы барабанов через verifiable randomness, обеспечивать заявленный RTP (Return to Player) и предотвращать манипуляции результатом ни со стороны казино, ни со стороны игрока.

Механика и математика Slots

Классический slot: 5 барабанов × 3 строки = 15 позиций. Каждый барабан имеет виртуальный стрип (например, 64 позиции с разными символами). Random number → позиция на стрипе → видимые символы. Платёж определяется комбинацией символов на paylines.

RTP 96% означает: из каждых $100 ставок игрокам возвращается $96 в долгосрочной перспективе. Это достигается через математически выверенные паблтейблы (pay tables).

Smart contract реализация

contract BlockchainSlots is VRFConsumerBaseV2Plus {
    // Виртуальные стрипы барабанов
    // Индекс = позиция на стрипе, значение = символ (0-8)
    uint8[64] public reel1Strip;
    uint8[64] public reel2Strip;
    uint8[64] public reel3Strip;
    uint8[64] public reel4Strip;
    uint8[64] public reel5Strip;
    
    // Pay table: symbol combination -> multiplier (в basis points)
    mapping(bytes32 => uint256) public payTable;
    
    struct SpinRequest {
        address player;
        uint256 betAmount;
        uint256 lines; // количество активных paylines
    }
    
    mapping(uint256 => SpinRequest) public pendingSpins;
    
    function spin(uint256 lines) external payable returns (uint256 requestId) {
        require(lines >= 1 && lines <= 20, "Invalid lines");
        require(msg.value >= MIN_BET * lines, "Insufficient bet");
        
        requestId = _requestRandomWords(3); // 3 random words
        
        pendingSpins[requestId] = SpinRequest({
            player: msg.sender,
            betAmount: msg.value,
            lines: lines,
        });
    }
    
    function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override {
        SpinRequest memory spinReq = pendingSpins[requestId];
        delete pendingSpins[requestId];
        
        // Определяем позиции барабанов из random числа
        uint8[5] memory reelPositions;
        reelPositions[0] = uint8(randomWords[0] % 64);
        reelPositions[1] = uint8((randomWords[0] >> 8) % 64);
        reelPositions[2] = uint8((randomWords[0] >> 16) % 64);
        reelPositions[3] = uint8(randomWords[1] % 64);
        reelPositions[4] = uint8((randomWords[1] >> 8) % 64);
        
        // Получаем символы для 3 рядов каждого барабана
        uint8[5][3] memory grid = _buildGrid(reelPositions);
        
        // Считаем выигрыш по всем активным paylines
        uint256 totalPayout = _calculatePayout(grid, spinReq.betAmount, spinReq.lines);
        
        if (totalPayout > 0) {
            payable(spinReq.player).transfer(totalPayout);
        }
        
        emit SpinResult(spinReq.player, reelPositions, grid, totalPayout, requestId);
    }
    
    function _buildGrid(uint8[5] memory positions) internal view returns (uint8[5][3] memory grid) {
        // Для каждого барабана берём 3 последовательных символа (wrap-around)
        for (uint i = 0; i < 5; i++) {
            uint8 pos = positions[i];
            grid[i][0] = _getSymbol(i, (pos + 63) % 64);  // строка выше
            grid[i][1] = _getSymbol(i, pos);               // средняя строка
            grid[i][2] = _getSymbol(i, (pos + 1) % 64);   // строка ниже
        }
    }
    
    function _calculatePayout(
        uint8[5][3] memory grid,
        uint256 betAmount,
        uint256 activeLines
    ) internal view returns (uint256 payout) {
        uint256 betPerLine = betAmount / activeLines;
        
        // Проверяем каждую payline
        for (uint l = 0; l < activeLines; l++) {
            uint8[5] memory line = _getPayline(l, grid);
            uint256 lineMultiplier = _getLineMultiplier(line);
            
            if (lineMultiplier > 0) {
                payout += (betPerLine * lineMultiplier) / 100;
            }
        }
    }
}

Bonus features

Slots без бонусных механик не конкурентоспособны. Обязательные фичи:

Free Spins: scatter символы (обычно 3+) запускают серию бесплатных спинов с повышенным multiplier.

Wild символы: заменяют любой другой символ для формирования winning combination.

Multiplier Wilds: wild с ×2, ×3 множителем.

Expanding Wilds: при выпадении расширяются на весь барабан.

Bonus game: специальная mini-game с pick-me механикой (выбери из N сундуков).

function _checkBonusFeatures(uint8[5][3] memory grid) internal pure 
    returns (bool hasFreeSpin, uint256 freeSpinCount, bool hasBonusGame) 
{
    uint256 scatterCount = 0;
    for (uint col = 0; col < 5; col++) {
        for (uint row = 0; row < 3; row++) {
            if (grid[col][row] == SCATTER_SYMBOL) scatterCount++;
        }
    }
    
    if (scatterCount >= 3) {
        hasFreeSpin = true;
        freeSpinCount = scatterCount == 3 ? 10 : scatterCount == 4 ? 15 : 20;
    }
    
    // Bonus game при 3+ bonus символах на payline 1
    hasBonusGame = _checkBonusLine(grid);
}

Off-chain анимации, on-chain результат

Блокчейн-Slots обычно работают так: результат (позиции барабанов) приходит из VRF, анимация прокрутки барабанов — off-chain в браузере/приложении. Пользователь видит spinning, затем итоговые символы соответствуют on-chain результату. Интеграция через event от смарт-контракта.

Задержка VRF (3-15 секунд) — проблема для UX. Решения: оптимистичная анимация (показываем "вращение" пока ждём VRF), L2 деплой (Chainlink VRF дешевле и быстрее на Arbitrum/Polygon), commit-reveal (быстрее, но менее верифицируемо).

Разработка полноценного Slots (5 барабанов, 20 линий, Free Spins, Wild) — 4-6 недель смарт-контракт + 4-8 недель frontend с анимациями (Pixi.js/Three.js). Chainlink VRF интеграция включена в смарт-контракт часть.