相信在座的各位小伙伴对Google Chrome浏览器中的一个游戏彩蛋恐龙小游戏(Chrome Dino)不陌生吧。在断开网络连接,我们访问网站的时候,就会出现一个小霸王龙,在我们再按下空格键后,即可开始这个游戏,或者在谷歌浏览器的地址栏输入chrome://dino/, 按下空格键,也可这个开始游戏。
这是一个简单的无限跑步游戏,它会让你跳过仙人掌,并闪避障碍物,游戏控制也很简单,按空格键开始游戏,按空格键或上箭头↑跳跃,向下箭头↓俯身奔跑以躲避鸟类。
有时代码写的无聊时,就是玩一下这个游戏,然后我可能有点手残,玩不了多少分就game over了,于是就萌生了使用代码自动玩这个游戏的想法,说干就干,下面我就来使用Python编写一个可以自动玩这个恐龙小游戏的小程序。
思路:看下面这个截图,在恐龙向前奔跑的过程中,我们可以获取恐龙前面一段区间图像并获取其中像素点的颜色,如果颜色和背景色不同,那么就一定是障碍物(仙人掌或鸟类),然后按下按键做出正确动作即可。说起来很简单,实现起来却不是那么容易。
实现 获取指定图像像素点的颜色既然是要获取像素点的颜色,那么首先要截取图像,在Python中,我们可以使用下面代码截取图像(就是截图):
import pyautogui as gui # 截屏 sct_img = gui.screenshot(region=(x, y, width, height)) sct_img.save("name.jpg")
pyautogui是一个GUI自动化工具库,它有很多可以控制图形或者鼠标等等的函数,可以用程序去代替鼠标键盘的一些 *** 作,安装命令pip install pyautogui。
然后我们可以使用下面一段代码获取截图图片上指定像素点的颜色:
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。 上述我们说到这个恐龙的小游戏在 *** 作过程中只需要上箭头↑跳跃,下箭头↓俯身奔跑两个按键 所以我们可以使用以下代码:
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()
运行截图如下:
经过几次运行,最高得分是2890分,优化优化,应该还能再多,这次截图得了886分,可见虽然实现了我想要的功能,但是还有很大的提升空间。
可以还有其他没考虑好的细节,但是......
时间不允许再搞了,这个886的分数是不是就是在暗示我......
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)