Ultimate Google Dino Game Hack: набрать более 100 000 очков с помощью Node.js и Puppeteer. Кроме того, есть настоящий трюк, чтобы набрать 1М+ за несколько секунд 😉.

Вы когда-нибудь ловили себя на том, что бесконечно играете в игру Google Chrome Dino только для того, чтобы разочароваться из-за низкого балла? Я знаю это чувство. Как разработчик, я был полон решимости найти способ освоить эту простую, но захватывающую игру, используя свои навыки программирования. И я это сделал — я обнаружил мощную технику для достижения более 100 000 очков в игре Google Dino с использованием Node.js и Puppeteer. В этой статье я поделюсь с вами тем, как я взломал код и добился этого впечатляющего подвига, чтобы вы тоже могли это сделать.

Оставайтесь с нами до конца, чтобы узнать, как получить до 1 М+ за несколько секунд.

Дино игра

Во-первых, давайте немного поговорим о самой игре Google Dino. Это простая, но увлекательная браузерная игра, которая появляется на вашем экране, когда вы не в сети или у вас нет подключения к Интернету, или вы можете нажать chrome://dino. Вы управляете маленьким динозавром, который бежит по пустыне, избегая препятствий вроде кактусов и птиц. Цель состоит в том, чтобы выжить как можно дольше и набрать как можно больше очков. Несмотря на то, что игра кажется простой, набрать высокий балл может быть на удивление сложно — вот тут-то и появляются Node.js и Puppeteer.

Кукольник

Puppeteer — это библиотека Node.js, предоставляющая высокоуровневый API для управления безголовыми браузерами Chrome или Chromium. Он позволяет автоматизировать веб-задачи, такие как создание снимков экрана, сбор данных и моделирование взаимодействия с пользователем. С помощью Puppeteer вы можете программно управлять браузером и манипулировать веб-страницами, что делает его идеальным инструментом для таких задач, как просмотр веб-страниц, тестирование и автоматизация браузера. В случае с игрой Google Dino Puppeteer можно использовать для имитации пользовательского ввода и управления игрой, что позволяет вам достигать высоких результатов с точностью и аккуратностью.

Взлом кода: логика автоматизации

В игре Google Dino есть глобальная переменная Runner, которая содержит различные настройки и переменные среды выполнения. Одним из наиболее важных свойств Runner является instance_, в котором хранится информация о компонентах и ​​поведении игры. Например,

tRex — Свойство содержит данные о главном персонаже игры, в том числе его положение, способность к прыжкам и скорость прыжка.
horizon — Свойство включает информацию о препятствиях, облаках и других характеристиках окружающей среды, таких как положение спрайтов и частота облаков.
currentSpeed — Отслеживает текущую скорость игры.
isDarkMode — Определяет, находится ли игра в темном режиме или нет.

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

Настройка кукловода

Чтобы начать автоматизировать игру Google Dino, нам сначала нужно настроить автономный браузер и открыть игру. Это можно сделать с помощью базовой настройки, которая включает инициализацию Puppeteer и переход к URL-адресу игры. Как только игра загрузится, ее можно запустить, нажав пробел. Однако, чтобы получить высокий балл, нам нужно написать функцию keepPlaying, которая автоматизирует игру и позволит нам управлять динозавром и с точностью избегать препятствий.

const puppeteer = require('puppeteer');

(async () => {
    // Open browser
    const browser = await puppeteer.launch({
        headless: false,
        defaultViewport: { width: 1920, height: 1080 }
    });

    // Open a new page
    const page = await browser.newPage();

    try {
        // Go to chrome://dino
        await page.goto('chrome://dino');
    } catch (error) {
        console.log('ignore');
    }

    // Wait for page to fully load
    await page.waitForNavigation({
        waitUntil: 'load',
    });

    // Hit the space to start the game
    await page.keyboard.press('Space', { delay: 100 });

    // Function to automate the game
    keepPlaying(page);
})();

Автоматизировать игру

Это основная функция всего процесса.

async function keepPlaying(page) {
    const data = await page.evaluate(() => {
        return Promise.resolve(Runner.instance_);
    });

    // Process data to automate the game..
}

Сначала мы получим объект Runner.instance_ со страницы, с помощью которого мы получим текущее состояние игры и решим, делать прыжок или нет.

Сейчас мы проверим,

  1. Есть какие-либо препятствия в просмотре экрана
  2. И tRex не в прыгающем состоянии
if (data && data.horizon.obstacles.length > 0 && !data.tRex.jumping) {
    // Check if we have to make tRex jump or not...
}

Далее мы проверим, есть ли рядом с tRex какое-либо препятствие. Если есть, то нам придется заставить tRex прыгать.

Но как определить, близко какое-либо препятствие или нет? Здесь мы применим немного физики.

Физика

Воспользуемся простой формулой скорости из физики:

Будут использованы следующие данные из Runner.instance_:
data.currentSpeed: текущая скорость игры
data.tRex.config.INITIAL_JUMP_VELOCITY: скорость прыжка TRex. Он показывает, как быстро прыгает TRex.
o.xPos: положение препятствия по оси X
o.width: ширина препятствия
>DINO_INITIAL_X_POSITION: начальное положение Dino по оси X = 24
MS_PER_FRAME: миллисекунд на кадр = 16,666666667

Получение времени для TRex и препятствий

Время, необходимое T-Rex для достижения высшей точки прыжка:

const JUMP_HEIGHT = 180; // height of the jump

const jumpVelocity = data.tRex.config.INITIAL_JUMP_VELOCITY - (data.currentSpeed / 10); // Distance covered per frame
const requiredFramesForJump = JUMP_HEIGHT / jumpVelocity; // frames
const timeTakenToJump = -1 * requiredFramesForJump * MS_PER_FRAME; // milliseconds

Время, оставшееся до того, как препятствие достигнет положения T-Rex

const DINO_INITIAL_X_POSITION = 24;

const obstacleXPosition = o.xPos + (o.width / 2);
const distanceBetweenObstacleAndTRex = obstacleXPosition - DINO_INITIAL_X_POSITION; // Distance covered per frame
const requiredFramesForObstacle = distanceBetweenObstacleAndTRex / data.currentSpeed; // frames
const timeLeftForObstacle = requiredFramesForObstacle * MS_PER_FRAME; // milliseconds

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

Вот полный код:

const jumpVelocity = data.tRex.config.INITIAL_JUMP_VELOCITY - (data.currentSpeed / 10); // Distance covered per frame
const requiredFramesForJump = JUMP_HEIGHT / jumpVelocity; // frames
const timeTakenToJump = -1 * requiredFramesForJump * MS_PER_FRAME; // milliseconds

const obstacle = data.horizon.obstacles.findIndex(o => {
    const obstacleXPosition = o.xPos + (o.width / 2);
    const distanceBetweenObstacleAndTRex = obstacleXPosition - DINO_INITIAL_X_POSITION; // Distance covered per frame

    if (distanceBetweenObstacleAndTRex <= 0) {
      return false; // If obstacle already passed the TRex position, ignore it.
    }

    const requiredFramesForObstacle = distanceBetweenObstacleAndTRex / data.currentSpeed; // frames
    const timeLeftForObstacle = requiredFramesForObstacle * MS_PER_FRAME; // milliseconds

    return (timeLeftForObstacle <= timeTakenToJump) && o.yPos > 50;
});

if (obstacle !== -1) {
    await page.keyboard.press('Space', { delay: 500 });
}

Важно постоянно отслеживать положение препятствий и новые препятствия при каждом обновлении кадра. Постоянно отслеживая новые препятствия, мы можем гарантировать, что T-Rex прыгнет в нужное время, чтобы избежать столкновения с ними.

async function keepPlaying(page) {
    // Check for collision

    setTimeout(() => {
        keepPlaying(page);
    }, 16); // Check every 16ms => frame
}

Вот и все. Несмотря на кажущуюся сложность, для автоматизации игры Google Dino с помощью Node.js и Puppeteer требуется всего 60 строк кода, из которых только 20 строк посвящены реальной игровой логике.

Посмотрите видео-демонстрацию работающего скрипта, набравшего 100 000+ очков в игре Google Dino.

Полный код

const puppeteer = require('puppeteer');

const MS_PER_FRAME = 16.666666666666668;
const JUMP_HEIGHT = 180;
const DINO_INITIAL_X_POSITION = 24;

(async () => {
    // Open browser
    const browser = await puppeteer.launch({
        headless: false,
        defaultViewport: { width: 1920, height: 1080 }
    });

    // Open a new page
    const page = await browser.newPage();

    try {
        // Go to chrome://dino
        await page.goto('chrome://dino');
    } catch (error) {
        console.log('ignore');
    }

    // Wait for page to fully load
    await page.waitForNavigation({
        waitUntil: 'load',
    });

    // Hit the space to start the game
    await page.keyboard.press('Space', { delay: 100 });

    // Function to automate the game
    keepPlaying(page);
})();

async function keepPlaying(page) {
    const data = await page.evaluate(() => {
        return Promise.resolve(Runner.instance_);
    });

    if (data && data.horizon.obstacles.length > 0 && !data.tRex.jumping) {
        const jumpVelocity = data.tRex.config.INITIAL_JUMP_VELOCITY - (data.currentSpeed / 10); // Distance covered per frame
        const requiredFramesForJump = JUMP_HEIGHT / jumpVelocity; // frames
        const timeTakenToJump = -1 * requiredFramesForJump * MS_PER_FRAME; // milliseconds

        const obstacle = data.horizon.obstacles.findIndex(o => {
            const obstacleXPosition = o.xPos + (o.width / 2);
            const distanceBetweenObstacleAndTRex = obstacleXPosition - DINO_INITIAL_X_POSITION; // Distance covered per frame

            if (distanceBetweenObstacleAndTRex <= 0) {
              return false;
            }

            const requiredFramesForObstacle = distanceBetweenObstacleAndTRex / data.currentSpeed; // frames
            const timeLeftForObstacle = requiredFramesForObstacle * MS_PER_FRAME; // milliseconds

            return (timeLeftForObstacle <= timeTakenToJump) && o.yPos > 50;
        });

        if (obstacle !== -1) {
            await page.keyboard.press('Space', { delay: 500 });
        }
    }

    setTimeout(() => {
        keepPlaying(page);
    }, 16);
}

Хитрость, позволяющая набрать 1 млн+ баллов за несколько секунд

  1. Перейдите на страницу chrome://dino.
  2. Откройте Dev Tools и вставьте следующий код:
Runner.instance_.gameOver = () => {}

Runner.instance_.setSpeed(10000)

По сути, он переопределяет функцию окончания игры, поэтому даже в случае столкновения игра не закончится. Кроме того, это ускоряет игру, поэтому вы сможете быстро набрать 1 миллион очков.

НО,

После 999999 счетчик возвращается к 0 🤣. Хотя достижение 1 миллиона очков может быть невозможным, достижение 999999 очков все же может быть впечатляющим и забавным способом удивить своих друзей.

Заключение

В заключение, автоматизация игры Google Dino с помощью Node.js и Puppeteer — это увлекательный и сложный способ проверить свои навыки программирования и улучшить свои знания в области веб-автоматизации. Следуя стратегиям, изложенным в этой статье, вы сможете успешно автоматизировать игру и набрать 100 000 или более очков. Если вы нашли эту статью полезной или интересной, рассмотрите возможность поделиться ею со своими друзьями и коллегами, которые также могут быть заинтересованы в веб-автоматизации и программировании игр. Кроме того, если у вас есть какие-либо вопросы или комментарии по поводу стратегий, изложенных в этой статье, не стесняйтесь оставлять их ниже. Мы будем рады услышать ваши мысли и отзывы!

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

Если вы нашли эту статью полезной, вам также может быть интересно прочитать следующую статью по теме:



Время хлопать!

Хотите увидеть крутую анимацию? Хит эту кнопку аплодисменты, как ваша жизнь зависит от этого!

Еще больше, следуй за мной!

Что плохого в следовании? В худшем случае вас засыпают потрясающим контентом.

Продолжение следует…