這是我參與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~~~
最後,感謝女友在工做和生活中的包容、理解與支持 !