img

js控制chrome霸王龙自动躲避障碍

2021-04-07 0条评论 2.7k次阅读 JavaScript


公司偶然断网。看着chrome的错误页面,看着一样无辜的小恐龙,按下空格,随便打发一点时间。

无聊的按着上下按键,突然想到,可不可以让它自己躲避障碍物呢。

  • 打开chrome浏览器,输入 chrome://dino

  • 按F12打开控制台,输入:

var script = document.createElement('script');script.src = 'https://suohb.com/demo/chrome.trex.js';document.body.appendChild(script)
  • 点击选中网页主题,按空格键让小恐龙开始跑酷

简单介绍一下思路:

小恐龙跑酷游戏,是使用js在canvas上绘制的跑酷游戏。

我的做法的是,监控这个canvas的imageData,如果发现固定的几个位置,如果不是空白,那么就触发一下key.down或者key.up事件。让小恐龙做出躲避动作。

  • 获取使用querySelector获取到canvas元素
  • 定义好key.up和key.down的按键事件
  • 使用requestAnimationFrame在每个周期判断
  • 使用ctx.getImageData获取对应的位置是否存在像素
  • 前方是否存在需要跳跃的障碍物
  • 前方是否存在需要趴下的障碍物
  • 触发按键事件
const canvas = document.querySelector('.runner-canvas') // 获取canvas
const ctx = canvas.getContext('2d')

// 创建一个按键事件
const createCustomKeyEvent = (keyEvent, keyCode) => {
    let _event = document.createEvent('UIEvents')
    Object.defineProperty(_event, 'keyCode', { value: keyCode })
    _event.initEvent(keyEvent, true, true)
    return _event
}
// 创建按键事件
const KEYDOWN_UP = createCustomKeyEvent('keydown', 38)
const KEYDOWN_DOWN = createCustomKeyEvent('keydown', 40)
const KEYUP_UP = createCustomKeyEvent('keyup', 38)
const KEYUP_DOWN = createCustomKeyEvent('keyup', 40)
// 判断是否需要跳跃
const checkJumpPoint = () => {
    let data = ctx.getImageData(120, 115, 10, 1) // 判断canvas这个位置是否像素透明度不为空
    data = data.data.filter((item, index) => index % 4 === 3)
    return data.some((item, index) => { return item !== 0 })
}
// 判断是否需要趴下
const checkDuckPoint = () => {
    let data = ctx.getImageData(120, 105, 10, 1) // 判断canvas这个位置是否像素透明度不为空
    data = data.data.filter((item, index) => index % 4 === 3)
    return data.some((item, index) => { return item !== 0 })
}
// 判断前方脚下像素内是否没有障碍物
const checkUnderFoot = () => {
    let data = ctx.getImageData(30, 115, 90, 1) // 判断canvas这个位置是否像素透明度不为空
    data = data.data.filter((item, index) => index % 4 === 3)
    return !data.some((item, index) => { return item !== 0 })
}

let lastKey = ''
const keypress = (key) => {
    if (key !== 'up' && key !== 'down') return
    document.dispatchEvent(lastKey === 'up' ? KEYUP_UP : KEYUP_DOWN)
    setTimeout(() => {
        if (key === 'up') {
            document.dispatchEvent(KEYDOWN_UP)
        } else if (key === 'down') {
            document.dispatchEvent(KEYDOWN_DOWN)
        }
        lastKey = key
    })
}
// runtime
const runtime = () => {
    if (lastKey === 'up') {
        if (checkUnderFoot()) { // 如果当前是跳跃状态,并且已经跳过障碍物了,按下键让恐龙快速落下
            keypress('down')
        }
    } else {
        if (checkJumpPoint()) { // 但是前方是否需要跳跃
            keypress('up')
        } else if (checkDuckPoint()) { // 判断前方是否需要趴下
            keypress('down')
        }
    }
    requestAnimationFrame(runtime)
}

runtime()

/**
var script = document.createElement('script');script.src = 'https://suohb.com/demo/chrome.trex.js';document.body.appendChild(script)
 */

程序有存在的一些问题

  1. 有时候按了down但是恐龙并没有趴下,可能导致失败
  2. 十分接近的障碍物,恐龙会跳不及时

一般情况下,跑过开头之后,速度匀速之后,就不会失败(在这看跑到6W都没有结束,就不让再跑了)。如果失败。就刷新网页重复上边步骤。

转自: https://suohb.com/views/other/chrome.trex.html

💬 COMMENT


🦄 支持markdown语法

👋友