DEV Community

Cover image for The Journey of Creating an Auto-Jump Dino Script
Zxce3
Zxce3

Posted on

The Journey of Creating an Auto-Jump Dino Script

I couldn’t sleep. Maybe it was the three cups of coffee I had consumed earlier, or maybe it was my mind racing with ideas. Regardless, I found myself restless and unable to drift off. Instead of fighting the insomnia, I decided to code. And what better way to spend that energy than creating a script that would make the Dino in the Chrome offline game jump by itself?

This is a story about how a small spark of an idea led to hours of tweaking, testing, and ultimately, a fully functioning auto-jump system for the T-Rex.

The Beginning: A Simple Idea

At first, I started with the most basic concept. I wanted the Dino to jump automatically whenever an obstacle was within range. The challenge seemed straightforward at the time. After a bit of thinking, I whipped up a simple script:

// Auto jump function
function autoJump() {
  const checkObstacle = setInterval(() => {
    const tRex = Runner.instance_.tRex;

    // Check if an obstacle is near
    const obstacles = Runner.instance_.horizon.obstacles;

    if (obstacles.length > 0) {
      const obstacle = obstacles[0];

      // If the obstacle is close and within jumpable range, make the Dino jump
      if (obstacle.xPos < 70 && obstacle.xPos > 20 && !tRex.jumping) {
        tRex.startJump();
      }
    }
  }, 10); // Check every 10ms
}

// Start auto jump
autoJump();
Enter fullscreen mode Exit fullscreen mode

This first version did the job. The Dino would detect obstacles and automatically jump whenever it approached one. However, there was still a lot to improve. It felt robotic and limited—it could jump, but there was no crouching or consideration of how the game’s speed affected the Dino’s reactions. I wanted something more adaptive and dynamic.

The Evolution: Adaptive Auto-Jump and Crouching

I spent the next few hours refining the code, adding more features like adaptive jumping based on the game’s speed, and integrating a crouching mechanic for when the Pterodactyls flew by. The result was a script that felt much more in tune with the actual game. The final version allowed the Dino to react not just based on fixed distances, but by adjusting to the speed of the game itself.

Here’s what I came up with:

// Create the button to toggle auto-jump
const toggleButton = createToggleButton();
document.body.appendChild(toggleButton);

let autoJumpActive = false; // Auto-jump initially inactive
let autoJumpInterval = null; // Store interval ID
let jumpCount = 0; // Count the number of jumps
let obstacleCount = 0; // Count the number of obstacles encountered
let isCrouching = false; // Track crouch state

// Function to create the toggle button
function createToggleButton() {
  const button = document.createElement('button');
  button.innerText = 'Activate Auto-Jump';
  styleToggleButton(button);
  button.addEventListener('click', toggleAutoJump);
  return button;
}

// Function to style the toggle button
function styleToggleButton(button) {
  button.style.position = 'fixed';
  button.style.top = '10px';
  button.style.left = '10px';
  button.style.padding = '10px';
  button.style.zIndex = '1000';
  button.style.backgroundColor = '#4CAF50';
  button.style.color = '#fff';
  button.style.border = 'none';
  button.style.cursor = 'pointer';
}

// Function to simulate a key press
function simulateKeyPress(keyCode, key) {
  const event = new KeyboardEvent('keydown', {
    keyCode: keyCode,
    code: key,
    key: key,
    bubbles: true,
    cancelable: true,
  });
  document.dispatchEvent(event);
}

// Function to simulate a key release
function simulateKeyRelease(keyCode, key) {
  const event = new KeyboardEvent('keyup', {
    keyCode: keyCode,
    code: key,
    key: key,
    bubbles: true,
    cancelable: true,
  });
  document.dispatchEvent(event);
}

// Function to calculate adaptive distances for jumping and crouching based on speed
function calculateAdaptiveDistance(baseDistance) {
  const speed = Runner.instance_.currentSpeed;
  return baseDistance + speed * 3; // Adjust the multiplier as needed for more precision
}

// Function to start auto-jumping and crouching
function startAutoJump() {
  autoJumpInterval = setInterval(() => {
    const tRex = Runner.instance_.tRex;
    const obstacles = Runner.instance_.horizon.obstacles;
    const speed = Runner.instance_.currentSpeed; // Get the current speed of the game

    if (obstacles.length > 0) {
      const obstacle = obstacles[0];
      const distanceToObstacle = obstacle.xPos - tRex.xPos; // Distance from Dino to the obstacle

      // Dynamically calculate the adaptive jump and crouch distances based on game speed
      const jumpDistance = calculateAdaptiveDistance(100); // Base distance is 100, adjusted by speed
      const crouchDistance = calculateAdaptiveDistance(50); // Base crouch distance is 50
      const safeDistance = 40; // Minimum safe distance to avoid jumping too early

      // Check if the Dino needs to jump or crouch
      if (distanceToObstacle < jumpDistance && distanceToObstacle > safeDistance) {
        if (!tRex.jumping && !isCrouching) { // Ensure Dino is not crouching or jumping
          jumpCount++; // Increment jump count
          simulateKeyPress(32, ' '); // Simulate jump (spacebar)
        }
      } else if (distanceToObstacle <= crouchDistance && distanceToObstacle > safeDistance && !tRex.jumping) {
        // Only crouch if the Dino is not jumping
        simulateKeyPress(40, 'ArrowDown'); // Simulate crouch (down arrow)
        isCrouching = true; // Set crouch state to true
      } else if (obstacle.typeConfig.type === 'PTERODACTYL' && obstacle.yPos < 70) {
        // Crouch if the obstacle is a Pterodactyl flying high
        simulateKeyPress(40, 'ArrowDown'); // Simulate crouch (down arrow)
        isCrouching = true; // Set crouch state to true
      }

      // Release crouch when the obstacle is passed (Dino's xPos is greater than obstacle's xPos)
      if (tRex.xPos > obstacle.xPos && isCrouching) {
        simulateKeyRelease(40, 'ArrowDown'); // Release crouch (down arrow)
        isCrouching = false; // Reset crouch state
      }
    }

    // Update obstacle count
    obstacleCount = Runner.instance_.horizon.obstacles.length;

  }, 50); // Reduced interval time to 50ms for more frequent checks
}

// Function to stop auto-jumping
function stopAutoJump() {
  clearInterval(autoJumpInterval);
  autoJumpActive = false; // Reset auto-jump state
  toggleButton.innerText = 'Activate Auto-Jump';
  toggleButton.style.backgroundColor = '#4CAF50';
}

// Function to toggle auto-jump
function toggleAutoJump() {
  if (autoJumpActive) {
    stopAutoJump();
  } else {
    startAutoJump();
    toggleButton.innerText = 'Deactivate Auto-Jump';
    toggleButton.style.backgroundColor = '#f44336';
  }
  autoJumpActive = !autoJumpActive; // Toggle the state
}

// Detecting game over
const originalGameOver = Runner.prototype.gameOver;
Runner.prototype.gameOver = function() {
  stopAutoJump(); // Stop auto-jumping on game over
  originalGameOver.apply(this, arguments); // Call the original game over function
}

// Detecting when the game restarts
const originalStartGame = Runner.prototype.startGame;
Runner.prototype.startGame = function() {
  originalStartGame.apply(this, arguments);
  if (autoJumpActive) {
    startAutoJump(); // Restart auto-jump on game restart
  }
}
Enter fullscreen mode Exit fullscreen mode

Reflections on the Coding Journey

This journey from a sleepless night to a fully functional auto-jump script was both fun and challenging. What started as a simple idea evolved into something much more complex, requiring attention to detail, adaptability, and a willingness to experiment. Each iteration brought the script closer to feeling like an integrated part of the game rather than a simple add-on.

This is the beauty of coding: you start with an idea, and through persistence and creativity, you end up with something that surpasses your original vision. And sometimes, it all begins with a few too many cups of coffee!

Top comments (0)