使用前端方式挑戰 Chrome 小恐龍遊戲高分

本站使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)javascript

本文做者: 蘇洋html

建立時間: 2018年09月13日 統計字數: 4298字 閱讀時間: 9分鐘閱讀 本文連接: soulteary.com/2018/09/13/…前端


使用前端方式挑戰 Chrome 小恐龍遊戲高分

今天看論壇發現有人發帖說 Chrome週年慶祝 在「小恐龍」遊戲中埋入了新的菜單,能夠觸碰的 蛋糕 以及觸碰以後得到的 生日帽java

看到如今「小恐龍」這個彩蛋的改進,往事歷歷在目。可是很快,帖子中有人曬高分引發了個人注意:這個遊戲雖然說簡單,可是在分數達到必定程度後,加速度會讓玩家很難繼續遊戲。git

記得很早以前在機場玩過這個遊戲,記憶中獲取三千以上的分數仍是挺困難的,更別提八千分,因此我這裏推測這個玩家應該是有一些「特別的技巧」。github

在遊戲中取得使人歎爲觀止的高分,通常來講無非三種手段:chrome

  1. 練習:勤學苦練,熟能生巧,加上極致的耐心。
  2. 工具:使用一些輔助設施來模擬人的操做。
  3. 外掛:針對難度或者得分倍數進行改造或者直接對結果進行修改、甚至破壞遊戲規則。

第一種方式咱們暫且略過,後面若是實在閒,再進行嘗試,咱們直接開始後面兩種方案的嘗試。編程

編寫輔助工具

奔跑的小恐龍

君子性非異也,擅假於物也。瀏覽器

網上有個老外曾經編寫過一個根據判斷X軸方向小恐龍和前面物品距離進行自動跳躍的程序,在稍加改造後,將下面的代碼貼到控制檯中,便可完成小恐龍自動奔跑的神操做。bash

這裏添加了代碼避免小恐龍跳過蛋糕、避而不吃,以及調整了對障礙物須要跳躍的高度判斷,防止小恐龍看到低飛的鳥兒迎面而上,固然,還有可以在代碼執行後,自動開始遊戲。

function TrexRunnerBot() {

  const makeKeyArgs = (keyCode) => {
    const preventDefault = () => void 0;
    return {keyCode, preventDefault};
  };

  const upKeyArgs = makeKeyArgs(38);
  const downKeyArgs = makeKeyArgs(40);
  const startArgs = makeKeyArgs(32);

  if (!Runner().playing) {
    Runner().onKeyDown(startArgs);
    setTimeout(() => {
      Runner().onKeyUp(startArgs);
    }, 500);
  }

  function conquerTheGame() {
    if (!Runner || !Runner().horizon.obstacles[0]) return;

    const obstacle = Runner().horizon.obstacles[0];

    if (obstacle.typeConfig && obstacle.typeConfig.type === 'SNACK') return;

    if (needsToTackle(obstacle) && closeEnoughToTackle(obstacle)) tackle(obstacle);
  }

  function needsToTackle(obstacle) {
    return obstacle.yPos !== 50;
  }

  function closeEnoughToTackle(obstacle) {
    return obstacle.xPos <= Runner().currentSpeed * 18;
  }

  function tackle(obstacle) {
    if (isDuckable(obstacle)) {
      duck();
    } else {
      jumpOver(obstacle);
    }
  }

  function isDuckable(obstacle) {
    return obstacle.yPos === 50;
  }

  function duck() {
    Runner().onKeyDown(downKeyArgs);

    setTimeout(() => {
      Runner().onKeyUp(downKeyArgs);
    }, 500);
  }

  function jumpOver(obstacle) {
    if (isNextObstacleCloseTo(obstacle))
      jumpFast();
    else
      Runner().onKeyDown(upKeyArgs);
  }

  function isNextObstacleCloseTo(currentObstacle) {
    const nextObstacle = Runner().horizon.obstacles[1];

    return nextObstacle && nextObstacle.xPos - currentObstacle.xPos <= Runner().currentSpeed * 42;
  }

  function jumpFast() {
    Runner().onKeyDown(upKeyArgs);
    Runner().onKeyUp(upKeyArgs);
  }

  return {conquerTheGame: conquerTheGame};
}

let bot = TrexRunnerBot();
let botInterval = setInterval(bot.conquerTheGame, 2);
複製代碼

固然,爲了你可以在移動端的複製便捷,我這裏提供了壓縮版的代碼。

function TrexRunnerBot(){function f(){Runner().onKeyDown(d);setTimeout(function(){Runner().onKeyUp(d)},500)}var b=function(a){return{keyCode:a,preventDefault:function(){}}},c=b(38),d=b(40),e=b(32);Runner().playing||(Runner().onKeyDown(e),setTimeout(function(){Runner().onKeyUp(e)},500));return{conquerTheGame:function(){if(Runner&&Runner().horizon.obstacles[0]){var a=Runner().horizon.obstacles[0];if((!a.typeConfig||"SNACK"!==a.typeConfig.type)&&50!==a.yPos&&a.xPos<=18*Runner().currentSpeed)if(50=== a.yPos)f();else{var b=Runner().horizon.obstacles[1];if(b&&b.xPos-a.xPos<=42*Runner().currentSpeed)Runner().onKeyDown(c),Runner().onKeyUp(c);else Runner().onKeyDown(c)}}}}}var bot=TrexRunnerBot(),botInterval=setInterval(bot.conquerTheGame,2);
複製代碼

若是你想在桌面端瀏覽器遊玩小恐龍遊戲,除了斷網的操做外,還能夠直接訪問 chrome://dino/ 這個地址。

若是你想在手機上體驗小恐龍自動奔跑,請參考下面的操做:

  1. 飛行模式後打開 Chrome ,而後訪問任意頁面,呼出小恐龍界面。
  2. 將上面的代碼粘貼到地址欄。
  3. 在地址欄前手動加上 javascript: ,而後確認。

你的小恐龍就自個去浪了,不過這裏你獲取分數的速度依然和正常遊玩的玩家是同樣的,小恐龍走一步記一分。

那麼,接下來咱們換個套路。

改寫計分邏輯

與其說改寫,不如說「劫持」。ES5 有一個很古老的 API, Object.defineProperty(),藉助這個 API ,咱們可以輕易的修改現有對象上的屬性,配合從新定義對象具體內容的 gettersetter 描述符,能夠作到對於屬性的劫持操做,是否是很眼熟?沒錯,這個方案也是老生常談的 MVVM 框架的雙向數據綁定的實現方案之一。

let hackScore = 0;

Object.defineProperty(Runner.instance_, 'distanceRan', {
  get: () => hackScore,
  set: (value) => hackScore = value + Math.floor(Math.random() * 1000),
  configurable: true,
  enumerable: true,
});
複製代碼

一樣提供了壓縮版本。

var hackScore=0;Object.defineProperty(Runner.instance_,"distanceRan",{get:function(){return hackScore},set:function(a){return hackScore=a+Math.floor(1E3*Math.random())},configurable:!0,enumerable:!0});
複製代碼

將上面代碼執行以後,再次運行程序,你會發現你獲取分數的速度提高了一千倍。

若是你將第一個方案和這個方案的代碼結合,會得到一個可以自動奔跑得到高分的「智能小恐龍」。

不過由於咱們的「外掛」是基於計時器進行距離計算並模擬用戶操做的,當你得到很高很高的分數以後,障礙物推動速度過快,一旦你進行窗口的來回切換,遊戲進行暫停和遊玩的狀態切換,很大機率上「外掛」操做會延時,致使 GAME OVER

如何能避免這個事情呢,咱們來說講第三個套路。

破壞規則大法

若是說第一個方案起碼還有付出時間成本,模擬玩家操做一步一步循序漸進的獲取分數;第二個方案偷天換日,一步當一千步使;那麼接下來的方案就顯得十分無恥了。

Runner.instance_.gameOver=function(){};
複製代碼

下面代碼在執行以後,會清空遊戲的中斷邏輯,配合第二個方案的快速得到分數的代碼,你能夠獲得一隻擁有穿越障礙物能力的小恐龍:勇往無前,永不停歇,分數不停的增加,直到報錯。

其餘

相關代碼我推到了 GitHub 上,有興趣的同窗也能夠訪問,以瞭解更多內容。

先寫到這裏,去看蘋果發佈會了。

--EOF


我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。

在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈) 關於折騰羣入羣的那些事

關於折騰羣入羣的那些事

相關文章
相關標籤/搜索