这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战python
相信在座的各位小伙伴对Google Chrome浏览器中的一个游戏彩蛋恐龙小游戏(Chrome Dino)
不陌生吧。在断开网络链接,咱们访问网站的时候,就会出现一个小霸王龙,在咱们再按下空格键后,便可开始这个游戏,或者在谷歌浏览器的地址栏输入chrome://dino/
, 按下空格键,也可这个开始游戏。chrome
这是一个简单的无限跑步游戏,它会让你跳过仙人掌,并闪避障碍物,游戏控制也很简单,按空格键
开始游戏,按空格键
或上箭头↑
跳跃,向下箭头↓
俯身奔跑以躲避鸟类。小程序
有时代码写的无聊时,就是玩一下这个游戏,而后我可能有点手残,玩不了多少分就game over了,因而就萌生了使用代码自动玩这个游戏的想法,说干就干,下面我就来使用Python编写一个能够自动玩这个恐龙小游戏的小程序。浏览器
看下面这个截图,在恐龙向前奔跑的过程当中,咱们能够获取恐龙前面一段区间图像并获取其中像素点的颜色
,若是颜色和背景色
不一样,那么就必定是障碍物(仙人掌或鸟类),而后按下按键作出正确动做便可。提及来很简单,实现起来却不是那么容易。 markdown
既然是要获取像素点的颜色,那么首先要截取图像,在Python中,咱们可使用下面代码截取图像(就是截图):网络
import pyautogui as gui
# 截屏
sct_img = gui.screenshot(region=(x, y, width, height))
sct_img.save("name.jpg")
复制代码
pyautogui是一个GUI自动化工具库,它有不少能够控制图形或者鼠标等等的函数,能够用程序去代替鼠标键盘的一些操做,安装命令pip install pyautogui
。app
而后咱们可使用下面一段代码获取截图图片上指定像素点的颜色:函数
def get_pixel(image, x, y):
""" 获取图像中的像素值 :param image:图片对象 :param x:x坐标 :param y:y坐标 :return:颜色值 """
px = image.load()
return px[x, y]
复制代码
返回值是一个元组,例如白色就是返回(255,255,255)
。工具
使用程序模拟键盘动做,咱们可使用keyboard
库,可使用其提供的函数进行按下按键
或释放按键
此类的动做。安装命令pip install keyboard
。 上述咱们说到这个恐龙的小游戏在操做过程当中只须要上箭头↑
跳跃,下箭头↓
俯身奔跑两个按键 因此咱们可使用如下代码:post
import keyboard
# 按下“↑”鍵 跳跃
keyboard.press('up')
# 按下“↓”鍵 俯身奔跑
keyboard.press("down")
# 释放按键“↓”
keyboard.release("down")
复制代码
手动玩了一段时间发现,障碍物可能出现的地方有如下几点:
根据截图软件得出障碍物可能出现的地方的高度即y坐标
。
注意: 个人是分辨率1920*1080的显示屏,因此是以此分辨率为基准截图并肯定坐标
我发现,在玩一段时间后,游戏节奏会加快,出现误判的概率大大增长,因此我在此加入了模拟加速的逻辑: 判断两次跳跃之间的时间间隔,若是间隔和上次不同,那么就多是节奏加快了,咱们就能够多恐龙以前的一下区间,就是加大搜索障碍物区间的大小,这样就至关于提早进行了判断,就会抵消掉一部分由于游戏节奏加快带来的影响。
所有代码以下:
import pyautogui as gui
import keyboard
import time
import math
def get_pixel(image, x, y):
""" 获取图像中的像素值 :param image:图片对象 :param x:x坐标 :param y:y坐标 :return:颜色值 """
px = image.load()
return px[x, y]
def start():
# 截屏图片尺寸
x, y, width, height = 0, 102, 1920, 872
# 用于计算时间
jumping_time = 0
last_jumping_time = 0
current_jumping_time = 0
last_interval_time = 0
# 机器人寻找障碍物的区间
y_search1, y_search2, x_start, x_end = 557, 486, 400, 415
y_search_for_bird = 460
time.sleep(3) # 留3s时间用于程序执行后将界面切换到谷歌浏览器
while True:
t1 = time.time()
# 按下q键机器人退出
if keyboard.is_pressed('q'):
break
# 截屏
sct_img = gui.screenshot(region=(x, y, width, height))
sct_img.save("dd.jpg")
# 获取截屏图片的背景色
bg_color = get_pixel(sct_img, 100, 100)
for i in reversed(range(x_start, x_end)):
# 若是在截屏图片的背景色中搜索指定区间的像素,若是该像素的颜色和背景色的颜色不一致,就是障碍物
if get_pixel(sct_img, i, y_search1) != bg_color \
or get_pixel(sct_img, i, y_search2) != bg_color:
# 按下“↑”鍵 跳跃
keyboard.press('up')
jumping_time = time.time()
current_jumping_time = jumping_time
break
if get_pixel(sct_img, i, y_search_for_bird) != bg_color:
keyboard.press("down")
time.sleep(0.4)
# 释放按键“↓”
keyboard.release("down")
break
# 本次跳跃与上次间隔时间
interval_time = current_jumping_time - last_jumping_time
# 若是本次间隔时间与上次间隔时间不相同,说明游戏加速了,也要相应调整搜索区间的宽度,至关于提早搜索
if last_interval_time != 0 and math.floor(interval_time) != math.floor(last_interval_time):
x_end += 4
if x_end >= width:
x_end = width
# 记录上次跳跃时间
last_jumping_time = jumping_time
# 记录上次跳跃与上上次间隔时间
last_interval_time = interval_time
start()
复制代码
运行截图gif以下(无聊的朋友能够看一下):
通过几回运行,最高得分是2890分,优化优化,应该还能再多,此次截图得了886分,可见虽然实现了我想要的功能,可是还有很大的提高空间。
能够还有其余没考虑好的细节,可是......
时间不容许再搞了,这个886的分数是否是就是在暗示我......
别搞了,该上会儿班了
再搞就要和工做886了,哈哈哈,886~~~
最后,感谢女友在工做和生活中的包容、理解与支持 !