索洪波的网站

vuePress-theme-reco 索洪波    2014 - 2022
索洪波的网站 索洪波的网站
主页
文章随笔
  • 知识整理
  • 原创特效
  • 开发日记
  • 前端工具
  • 其他
标签
原创特效
留言板
GitHub
author-avatar

索洪波

69

Article

21

Tag

主页
文章随笔
  • 知识整理
  • 原创特效
  • 开发日记
  • 前端工具
  • 其他
标签
原创特效
留言板
GitHub

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

vuePress-theme-reco 索洪波    2014 - 2022

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

索洪波 2020-09-21 其他

公司偶然断网。看着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都没有结束,就不让再跑了)。如果失败。就刷新网页重复上边步骤。