js控制chrome霸王龙自动躲避障碍
Sonder
2021-04-07
3101字
8分钟
浏览 (2.8k)
公司偶然断网。看着chrome的错误页面,看着一样无辜的小恐龙,按下空格,随便打发一点时间。
无聊的按着上下按键,突然想到,可不可以让它自己躲避障碍物呢。
![](https://suohb.com/images/other/trex/trex.gif)
- 打开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事件。让小恐龙做出躲避动作。
![](https://suohb.com/images/other/trex/trex2.png)
- 获取使用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)
*/
程序有存在的一些问题
- 有时候按了down但是恐龙并没有趴下,可能导致失败
- 十分接近的障碍物,恐龙会跳不及时
一般情况下,跑过开头之后,速度匀速之后,就不会失败(在这看跑到6W都没有结束,就不让再跑了)。如果失败。就刷新网页重复上边步骤。